diff --git a/CPAN/Media/Scan.pm b/CPAN/Media/Scan.pm new file mode 100644 index 00000000000..2b7d3a6c607 --- /dev/null +++ b/CPAN/Media/Scan.pm @@ -0,0 +1,155 @@ +package Media::Scan; + +use strict; +use base qw(Exporter); + +use Media::Scan::Audio; +use Media::Scan::Image; +use Media::Scan::Error; +use Media::Scan::Progress; +use Media::Scan::Video; + +# Log levels +use constant MS_LOG_ERR => 1; +use constant MS_LOG_WARN => 2; +use constant MS_LOG_INFO => 3; +use constant MS_LOG_DEBUG => 4; +use constant MS_LOG_MEMORY => 9; + +# Flags +use constant MS_USE_EXTENSION => 1; +use constant MS_FULL_SCAN => 1 << 1; +use constant MS_RESCAN => 1 << 2; +use constant MS_INCLUDE_DELETED => 1 << 3; +use constant MS_WATCH_CHANGES => 1 << 4; +use constant MS_CLEARDB => 1 << 5; + +our $VERSION = '0.01'; + +our @EXPORT = qw( + MS_LOG_ERR MS_LOG_WARN MS_LOG_INFO MS_LOG_DEBUG MS_LOG_MEMORY + MS_USE_EXTENSION MS_FULL_SCAN MS_RESCAN MS_INCLUDE_DELETED + MS_WATCH_CHANGES MS_CLEARDB +); + +require XSLoader; +XSLoader::load('Media::Scan', $VERSION); + +=head2 new( \@paths, \%options ) + +Create a new Media::Scan instance and begin scanning. + +paths may be a single scalar path, or an array reference with multiple paths. + +options include: + +=over 4 + +=item loglevel (default: MS_LOG_ERR) + +One of the following levels: + + MS_LOG_ERR + MS_LOG_WARN + MS_LOG_INFO + MS_LOG_DEBUG + MS_LOG_MEMORY + +=item async (default: 0) + +If set to 1, all scanning is performed in a background thread, and the call to new() will +return immediately. Make sure to keep a reference to the Media::Scan object, or +the scan will be aborted at DESTROY-time. + +=item cachedir (default: current dir) + +An optional path for libmediascan to store some cache files. + +=item flags (default: MS_USE_EXTENSION | MS_FULL_SCAN) + +An OR'ed list of flags, the possible flags are: + + MS_USE_EXTENSION - Use a file's extension to determine how to scan it. + MS_FULL_SCAN - Perform a full scan on every file. + MS_RESCAN - Only scan files that are new or have changed since the last scan. + MS_INCLUDE_DELETED - The result callback will be called for files that have been deleted + since the last scan. + MS_WATCH_CHANGES - Continue watching for changes after the scan has completed. + MS_CLEARDB - Wipe the internal libmediascan database before scanning. + +=item ignore (default: none) + +An array reference of file extensions that should be skipped. You may also specify 3 special types: + + AUDIO - Ignore all audio files. + IMAGE - Ignore all image files. + VIDEO - Ignore all video files. + +=item thumbnails (default: none) + +An arrayref of hashes with one or more thumbnail specifications. Thumbnails are created during the +scanning process and are available within the result callback. + +The format of a thumbnail spec is: + + { format => 'AUTO', # or JPEG or PNG + width => 100, + height => 100, + keep_aspect => 1, + bgcolor => 0xffffff, + quality => 90, + } + +Most values are optional, however at least width or height must be specified. + +=item on_result + +A callback that will be called for each scanned file. The function will be passed +a L, L, or L depending on the +file type. This callback is required. + +=item on_error + +An callback that will be called when a scanning error occurs. It is passed a +L. + +=item on_progress + +An optional callback that will be passed a L at regular intervals +during scanning. + +=item on_finish + +An optional callback that is called when scanning has finished. Nothing is currently passed +to this callback, eventually a scanning summary and overall stats might be included here. + +=cut + +sub new { + my ( $class, $paths, $opts ) = @_; + + if ( ref $paths ne 'ARRAY' ) { + $paths = [ $paths ]; + } + + $opts->{loglevel} ||= MS_LOG_ERR; + $opts->{async} ||= 0; + $opts->{flags} ||= MS_USE_EXTENSION | MS_FULL_SCAN; + $opts->{paths} = $paths; + $opts->{ignore} ||= []; + $opts->{thumbnails} ||= []; + + if ( ref $opts->{ignore} ne 'ARRAY' ) { + die "ignore must be an array reference"; + } + + my $self = bless $opts, $class; + + $self->xs_new(); + + $self->xs_scan(); + + return $self; +} + +1; \ No newline at end of file diff --git a/CPAN/Media/Scan/Audio.pm b/CPAN/Media/Scan/Audio.pm new file mode 100644 index 00000000000..f4441d71b44 --- /dev/null +++ b/CPAN/Media/Scan/Audio.pm @@ -0,0 +1,8 @@ +package Media::Scan::Audio; + +use strict; +use base qw(Media::Scan::Result); + +# Implementation is in xs/Audio.xs and xs/Result.xs + +1; \ No newline at end of file diff --git a/CPAN/Media/Scan/Error.pm b/CPAN/Media/Scan/Error.pm new file mode 100644 index 00000000000..dd084c9a10c --- /dev/null +++ b/CPAN/Media/Scan/Error.pm @@ -0,0 +1,18 @@ +package Media::Scan::Error; + +use strict; + +# Implementation is in xs/Error.xs + +sub as_hash { + my $self = shift; + + return { + error_code => $self->error_code, + averror => $self->averror, + path => $self->path, + error_string => $self->error_string, + }; +} + +1; \ No newline at end of file diff --git a/CPAN/Media/Scan/Image.pm b/CPAN/Media/Scan/Image.pm new file mode 100644 index 00000000000..c8c6e32f61f --- /dev/null +++ b/CPAN/Media/Scan/Image.pm @@ -0,0 +1,19 @@ +package Media::Scan::Image; + +use strict; +use base qw(Media::Scan::Result); + +# Implementation is in xs/Image.xs and xs/Result.xs + +sub as_hash { + my $self = shift; + + return { + %{ $self->SUPER::as_hash() }, + codec => $self->codec, + width => $self->width, + height => $self->height, + }; +} + +1; \ No newline at end of file diff --git a/CPAN/Media/Scan/Progress.pm b/CPAN/Media/Scan/Progress.pm new file mode 100644 index 00000000000..5ace5e26b76 --- /dev/null +++ b/CPAN/Media/Scan/Progress.pm @@ -0,0 +1,20 @@ +package Media::Scan::Progress; + +use strict; + +# Implementation is in xs/Progress.xs + +sub as_hash { + my $self = shift; + + return { + phase => $self->phase, + cur_item => $self->cur_item, + total => $self->total, + done => $self->done, + eta => $self->eta, + rate => $self->rate, + }; +} + +1; \ No newline at end of file diff --git a/CPAN/Media/Scan/Result.pm b/CPAN/Media/Scan/Result.pm new file mode 100644 index 00000000000..2aeec967db7 --- /dev/null +++ b/CPAN/Media/Scan/Result.pm @@ -0,0 +1,24 @@ +package Media::Scan::Result; + +use strict; + +# Implementation is in xs/Result.xs + +sub as_hash { + my $self = shift; + + return { + type => $self->type, + path => $self->path, + mime_type => $self->mime_type, + dlna_profile => $self->dlna_profile, + size => $self->size, + mtime => $self->mtime, + bitrate => $self->bitrate, + duration_ms => $self->duration_ms, + hash => $self->hash, + thumbnails => $self->thumbnails, + }; +} + +1; \ No newline at end of file diff --git a/CPAN/Media/Scan/Video.pm b/CPAN/Media/Scan/Video.pm new file mode 100644 index 00000000000..0676845c008 --- /dev/null +++ b/CPAN/Media/Scan/Video.pm @@ -0,0 +1,20 @@ +package Media::Scan::Video; + +use strict; +use base qw(Media::Scan::Result); + +# Implementation is in xs/Video.xs and xs/Result.xs + +sub as_hash { + my $self = shift; + + return { + %{ $self->SUPER::as_hash() }, + codec => $self->codec, + width => $self->width, + height => $self->height, + fps => $self->fps, + }; +} + +1; \ No newline at end of file diff --git a/CPAN/XS/Object/Magic.pm b/CPAN/XS/Object/Magic.pm new file mode 100644 index 00000000000..de47d2b526d --- /dev/null +++ b/CPAN/XS/Object/Magic.pm @@ -0,0 +1,211 @@ +package XS::Object::Magic; + +use strict; +use warnings; + +require 5.008001; +use parent qw(DynaLoader); + +our $VERSION = '0.02'; +$VERSION = eval $VERSION; + +sub dl_load_flags { 0x01 } + +__PACKAGE__->bootstrap($VERSION); + +__PACKAGE__ + +__END__ + +=pod + +=head1 NAME + +XS::Object::Magic - Opaque, extensible XS pointer backed objects using C + +=head1 SYNOPSIS + + package MyObject; + + use XS::Object::Magic; + + sub new { + my $class = shift; + + # create any object representation you like + my $self = bless {}, $class; + + $self->build_struct; + + return $self; + } + + + # or using Moose + + package MyObject; + use Moose; + + sub BUILD { + shift->build_struct; + } + + + # then in XS + + MODULE = MyObject PACKAGE = MyObject + + void build_struct (SV *self) + PREINIT: + my_struct_t *thingy; + CODE: + thingy = create_whatever(); + + /* note that we dereference self first. This + * can be done using an XS typemap of course */ + xs_object_magic_attach_struct(aTHX_ SvRV(self), thingy); + + + void foo (SV *self) + PREINIT: + my_struct_t *thingy = xs_object_magic_get_struct_rv(aTHX_ self) + CODE: + my_struct_foo(thingy); /* delegate to C api */ + + + /* using typemap */ + void foo (my_struct_t *thingy) + CODE: + my_struct_foo(thingy); + + /* or better yet */ + PREFIX = my_struct_ + + void + my_struct_foo (thingy) + my_struct_t *thingy; + + + /* don't forget a destructor */ + void + DESTROY (my_struct_t *thingy) + CODE: + Safefree(thingy); + + /* note that xs_object_magic_get_struct() will + * still return a pointe which is now invalid */ + + +=head1 DESCRPTION + +This way of associating structs with Perl space objects is designed to supercede +Perl's builtin C with something that is designed to be: + +=over 4 + +=item Extensible + +The association of the pointer using C can be done on any data +type, so you can associate C structs with any representation type. + +This means that you can add pointers to any object (hand coded, L or +otherwise), while still having instance data in regular hashes. + +=item Opaque + +The C pointer is neither visible nor modifiable from Perl space. + +This prevents accidental corruption which could lead to segfaults using +C (e.g. C<$$ptr_obj = 0>). + +=back + +=head1 C API + +=over 4 + +=item void *xs_object_magic_get_struct_rv(aTHX_ SV *sv) + +When called on the object reference it will check that the C is a reference, +dereference it and return the associated pointer using +C. + +Basically the same as C but croaks +if no magic was found. + +Note that storing a C pointer will B cause an error. + +=item void *xs_object_magic_get_struct(aTHX_ SV *sv) + +Fetches the pointer associated with C. + +Returns C if no pointer is found. There is no way to distinguish this +from having a C pointer. + +=item MAGIC *xs_object_magic_get_mg (aTHX_ SV *sv) + +Fetches the appropriate C entry for the struct pointer storage from +C. + +This lets you manipulate Cmg_ptr> if you need to. + +=item void xs_object_magic_attach_struct(aTHX_ SV *sv, void *ptr) + +Associates C with C by adding a magic entry to C. + +=item SV *xs_object_magic_create(aTHX_ void *ptr, HV *stash) + +Convenience function that creates a hash object blessed to C and +associates it with C. + +Can be used to easily create a constructor: + + SV * + new(char *class) + CODE: + RETVAL = xs_object_magic_create( + (void *)test_new(), + gv_stashpv(class, 0) + ); + OUTPUT: RETVAL + +=back + +=head1 TYPEMAP + +The included typemap provides a C entry which only supports the +C conversion. + +This typemap entry lets you declare methods that are invoked directly on the +associated pointer. In your own typemap add an entry: + + TYPEMAP + my_pointer_t * T_PTROBJ_MG + +and then you can use C as the argument type of the invocant: + + I32 + method (self) + my_pointer_t *self; + CODE: + ... + +Note that there is no C conversion. In order to return your object you +need to use C or some other means of getting the invocant. + +=head1 VERSION CONTROL + +L + +=head1 AUTHOR + +Florian Ragwitz, Yuval Kogman + +=head1 COPYRIGHT & LICENSE + + Copyright (c) 2009 Florian Ragwitz, Yuval Kogman. All rights reserved + This program is free software; you can redistribute + it and/or modify it under the same terms as Perl itself. + +=cut + diff --git a/CPAN/arch/5.10/MSWin32-x86-multi-thread/auto/Media/Scan/Scan.dll b/CPAN/arch/5.10/MSWin32-x86-multi-thread/auto/Media/Scan/Scan.dll new file mode 100755 index 00000000000..8282a12bfcb Binary files /dev/null and b/CPAN/arch/5.10/MSWin32-x86-multi-thread/auto/Media/Scan/Scan.dll differ diff --git a/CPAN/arch/5.10/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle b/CPAN/arch/5.10/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle new file mode 100755 index 00000000000..c0da41104c0 Binary files /dev/null and b/CPAN/arch/5.10/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle differ diff --git a/CPAN/arch/5.10/darwin-thread-multi-2level/auto/XS/Object/Magic/Magic.bundle b/CPAN/arch/5.10/darwin-thread-multi-2level/auto/XS/Object/Magic/Magic.bundle new file mode 100755 index 00000000000..31ba683b6b5 Binary files /dev/null and b/CPAN/arch/5.10/darwin-thread-multi-2level/auto/XS/Object/Magic/Magic.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle index c4ca6c28e53..10fd5df736e 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle index a542af1f38f..c54f911e59e 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle index a9121874f12..c8fe0c09129 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBI/DBI.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBI/DBI.bundle index 433af9a85a1..6ae258610aa 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBI/DBI.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/DBI/DBI.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle index 7b312bae374..b2f59cc2dcb 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/EV/EV.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/EV/EV.bundle index 1184b30edc0..01c6d0e8bfb 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/EV/EV.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/EV/EV.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle index 2bf35778b20..4dbb795736b 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle index 83427c7e933..6525608c4d8 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle index f3844adde30..cac987386a8 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle index 6621bc26577..b87206785a9 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle new file mode 100755 index 00000000000..0c618a50e05 Binary files /dev/null and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle index 77b82411d5b..8faf75cc459 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle differ diff --git a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle index de81d77efda..41f77c9557b 100755 Binary files a/CPAN/arch/5.12/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle and b/CPAN/arch/5.12/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/C3/XS/XS.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/C3/XS/XS.bundle index 49daeeacdd5..f0b1dc0fd84 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/C3/XS/XS.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/C3/XS/XS.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle index 889d9c3f6e3..7ba84aabceb 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Class/XSAccessor/XSAccessor.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle index 8892521f663..9261d8e3c73 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Compress/Raw/Zlib/Zlib.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle index 39a26298d91..558161e85cf 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBD/SQLite/SQLite.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBI/DBI.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBI/DBI.bundle index 00ca0819948..5a0796075e4 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBI/DBI.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/DBI/DBI.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle index 9db0ef3fab3..e1d96b3bd5b 100644 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Digest/SHA1/SHA1.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/EV/EV.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/EV/EV.bundle index 87249ee2cd7..b523fc95e77 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/EV/EV.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/EV/EV.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Encode/Detect/Detector/Detector.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Encode/Detect/Detector/Detector.bundle index 3fb3de7d15b..aa4506f78f0 100644 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Encode/Detect/Detector/Detector.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Encode/Detect/Detector/Detector.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle index 45f19dfae7a..5707f214cde 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Font/FreeType/FreeType.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/HTML/Parser/Parser.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/HTML/Parser/Parser.bundle index ef3690b859a..58fa69282b9 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/HTML/Parser/Parser.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/HTML/Parser/Parser.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/IO/AIO/AIO.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/IO/AIO/AIO.bundle index 998f5333234..cbd25eb0cb5 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/IO/AIO/AIO.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/IO/AIO/AIO.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle index 87201ba9073..0831bf37025 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Image/Scale/Scale.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/JSON/XS/XS.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/JSON/XS/XS.bundle index cf3c6ad28fa..44d2695fddb 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/JSON/XS/XS.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/JSON/XS/XS.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/Hebrew.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/Hebrew.bundle index 255e0078992..9edbe602210 100644 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/Hebrew.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/Hebrew.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/autosplit.ix b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/autosplit.ix new file mode 100644 index 00000000000..08bb0688503 --- /dev/null +++ b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Locale/Hebrew/autosplit.ix @@ -0,0 +1,3 @@ +# Index created by AutoSplit for blib/lib/Locale/Hebrew.pm +# (file acts as timestamp) +1; diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle index a981d889936..42af42c7349 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/MP3/Cut/Gapless/Gapless.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle index ad13caee7be..3b3e9a04fd8 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Mac/FSEvents/FSEvents.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle new file mode 100755 index 00000000000..a2f93e9ad80 Binary files /dev/null and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Media/Scan/Scan.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Sub/Name/Name.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Sub/Name/Name.bundle index c1ac2b7329c..ec0cd4a1913 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Sub/Name/Name.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Sub/Name/Name.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Template/Stash/XS/XS.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Template/Stash/XS/XS.bundle index 433c4a59d91..6ac4e19da61 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Template/Stash/XS/XS.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/Template/Stash/XS/XS.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle index a74744077c7..b214b810ec5 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/XML/Parser/Expat/Expat.bundle differ diff --git a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle index 89efb0ad8b6..090c7012aa3 100755 Binary files a/CPAN/arch/5.8/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle and b/CPAN/arch/5.8/darwin-thread-multi-2level/auto/YAML/Syck/Syck.bundle differ diff --git a/Changelog.html b/Changelog.html index b6bdbf4cabf..e798b29e5ea 100644 --- a/Changelog.html +++ b/Changelog.html @@ -1,7 +1,7 @@ -

Squeezebox Server Change Logs

+

Logitech Media Server Change Logs

    -
  • Squeezebox Server 7.x - Current version is 7.6

    +

  • Logitech Media Server 7.x - Current version is 7.6

  • SlimServer 6.x

  • SlimServer 5.x

  • SliMP3 Server 4.x

    diff --git a/Changelog7.html b/Changelog7.html index a445de5acb5..09763940f1a 100644 --- a/Changelog7.html +++ b/Changelog7.html @@ -1,3 +1,16 @@ +

    Version 7.7.0 aka Logitech Media Server

    +
      +
    • New Features:
    • +
        +
      • Experimental UPnP/DLNA support:
      • +
          +
        • Music library is exposed as a Media Server.
        • +
        • All connected players are exposed as Media Renderers.
        • +
        +
      +
      +
    +

    Version 7.6.0

    • Firmware updates:
    • diff --git a/HTML/Default/ajaxProgress.txt b/HTML/Default/ajaxProgress.txt index e243b5925c9..454cb00871e 100644 --- a/HTML/Default/ajaxProgress.txt +++ b/HTML/Default/ajaxProgress.txt @@ -1,7 +1,8 @@ { 'scans':[ [% FOREACH item = progress_items %]{ - 'Name':'[% item.obj.name _ "_PROGRESS" | string | uri | replace("'", "%27") %]', + [% IF item.fullname; name = item.fullname; ELSE; name = item.obj.name _ "_PROGRESS" | string; END %] + 'Name':'[% name | uri | replace("'", "%27") %]', 'Done':'[% item.obj.done | uri | replace("'", "%27") %]', 'Total':'[% (item.obj.total || item.obj.done) | uri | replace("'", "%27") %]', 'Active':'[% IF item.obj.active %][% "RUNNING" | string | replace("'", "%27") %][% ELSE %][% "COMPLETE" | string | uri | replace("'", "%27") %][% END %]', diff --git a/HTML/Default/html/Wizard.js b/HTML/Default/html/Wizard.js index a3b76cc6858..9fbb4f35c42 100644 --- a/HTML/Default/html/Wizard.js +++ b/HTML/Default/html/Wizard.js @@ -163,9 +163,9 @@ Wizard = { }, audiodir_p: { - validator: function(){ - this._validatePref('server', 'audiodir'); - }, + //validator: function(){ + // this._validatePref('server', 'audiodir'); + //}, skip: function(){ return !this.useAudioDir; diff --git a/HTML/Default/html/ext/README.TXT b/HTML/Default/html/ext/README.TXT index 2a3b7bc0748..53190b39b2b 100644 --- a/HTML/Default/html/ext/README.TXT +++ b/HTML/Default/html/ext/README.TXT @@ -8,7 +8,7 @@ I've built two versions of the ExtJS framework optimized for our needs: to speed up page loading/building - ext-main: this version includes all the ExtJS code required in the rest of - the Squeezebox Server web UI, but still much less than ext-all + the Logitech Media Server web UI, but still much less than ext-all In order to build/update these two files download the latest version of ExtJS from extjs.com. Copy /trunk/tools/JSBuilder/JSBuilder2.jar to the extracted extjs-x.y.z diff --git a/HTML/Default/html/ext/ext-squeezebox.jsb2 b/HTML/Default/html/ext/ext-squeezebox.jsb2 index 7cc7f84adba..19b7b4ec3f3 100644 --- a/HTML/Default/html/ext/ext-squeezebox.jsb2 +++ b/HTML/Default/html/ext/ext-squeezebox.jsb2 @@ -1,7 +1,7 @@ { "projectName": "Ext JS", "deployDir": "ext-sb", - "licenseText": "Ext JS Library for Squeezebox Server", + "licenseText": "Ext JS Library for Logitech Media Server", "pkgs": [{ "name": "Ext Base", "file": "adapter/ext/ext-base.js", diff --git a/HTML/Default/slimserver.css b/HTML/Default/slimserver.css index 79cc272d63c..87726a90981 100644 --- a/HTML/Default/slimserver.css +++ b/HTML/Default/slimserver.css @@ -154,8 +154,8 @@ img#background { top: 15px; left: 20px; height: 40px; - width: 144px; - background: url(html/images/squeezebox_server.png) no-repeat; + width: 158px; + background: url(html/images/logitech_media_server.png) no-repeat; } #logitechLogo { diff --git a/HTML/EN/ajaxProgress.txt b/HTML/EN/ajaxProgress.txt index 850d5e4a8cd..63be518d87b 100644 --- a/HTML/EN/ajaxProgress.txt +++ b/HTML/EN/ajaxProgress.txt @@ -1,7 +1,7 @@ [% num = 0 %] [% FOREACH item = progress_items %] -Name[% num %]|[% item.obj.name _ "_PROGRESS" | string %] +Name[% num %]|[% IF item.fullname; item.fullname; ELSE; item.obj.name _ "_PROGRESS" | string; END %] Done[% num %]|[% item.obj.done %] Total[% num %]|[% item.obj.total || item.obj.done %] Active[% num %]|[% IF item.obj.active %][% "RUNNING" | string %][% ELSE %][% "COMPLETE" | string %][% END %] diff --git a/HTML/EN/cmdwrappers b/HTML/EN/cmdwrappers index 1fdb9a18548..e03ab0f1d3f 100644 --- a/HTML/EN/cmdwrappers +++ b/HTML/EN/cmdwrappers @@ -125,7 +125,7 @@ END %] cmdimage = "b_down.gif" -%] [%- END %] -[%# this is the warning shown while Squeezebox Server is still scanning -%] +[%# this is the warning shown while server is still scanning -%] [% BLOCK scanwarning %] [% "NOTE" | string %] [% "SCAN_WARNING" | string -%] [%- IF audiodir -%] diff --git a/HTML/EN/html/SqueezeJS/Strings.js b/HTML/EN/html/SqueezeJS/Strings.js index 91f2904a255..6c909816efd 100644 --- a/HTML/EN/html/SqueezeJS/Strings.js +++ b/HTML/EN/html/SqueezeJS/Strings.js @@ -1,5 +1,5 @@ /* - * Globally used Squeezebox Server strings. + * Globally used Logitech Media Server strings. * This file should be PROCESSed if SqueezeJS.UI is used. */ [% PROCESS jsString id='POWER' jsId='' %] diff --git a/HTML/EN/html/SqueezeJS/UI.js b/HTML/EN/html/SqueezeJS/UI.js index 18a1774d97e..6c16da58758 100644 --- a/HTML/EN/html/SqueezeJS/UI.js +++ b/HTML/EN/html/SqueezeJS/UI.js @@ -2166,7 +2166,7 @@ SqueezeJS.UI.ScannerInfoExtended = function(){ } // hide results from previous scans - for (var i=scans.length; i<=10; i++) { + for (var i=scans.length; i<=50; i++) { Ext.get('progress'+i).setDisplayed(false); } } diff --git a/HTML/EN/html/docs/artwork.html b/HTML/EN/html/docs/artwork.html index 90927cb9dfd..e1449405609 100644 --- a/HTML/EN/html/docs/artwork.html +++ b/HTML/EN/html/docs/artwork.html @@ -3,7 +3,7 @@ [% PROCESS helpheader.html %]

      -The Squeezebox Server can display artwork associated with each album. +The Logitech Media Server can display artwork associated with each album. This "cover art" is typically a copy of the CD/album's cover.

      @@ -55,10 +55,10 @@

      Technical details

      1. cover.jpg, cover.gif,
      2. folder.jpg, folder.gif,
      3. album.jpg, album.gif,
      4. thumb.jpg, thumb.gif,
      5. albumartsmall.jpg, albumartsmall.gif

    -The Squeezebox Server will use the first image file located in this search.

    +The Logitech Media Server will use the first image file located in this search.

    -Squeezebox Server looks in the same path as the song, thus you would be looking for the +Logitech Media Server looks in the same path as the song, thus you would be looking for the same artfile in this case. However there is an option in Server Settings, Advanced, Formatting for setting filenames for Artwork, Artwork Thumbnail, and for setting a central location for artwork files. You can enter a specific filename @@ -71,7 +71,7 @@

    Technical details

    As an example, you could create a single directory of songs and name all your artwork as artist-album.jpg. For this, enter a setting of

      %ARTIST-ALBUM.jpg
    -

    for Artwork or Artwork Thumbnail in the server settings section. The extension can be specified for any Squeezebox Server supported format, .jpg is +

    for Artwork or Artwork Thumbnail in the server settings section. The extension can be specified for any Logitech Media Server supported format, .jpg is assumed if no extension is given.

    @@ -131,7 +131,7 @@

    Technical details

    The above list is included for completeness, it is unlikely that anyone would actually want to have differing artwork files for songs of different bitrates, but the -ability is in the Squeezebox Server. +ability is in the Logitech Media Server.

    diff --git a/HTML/EN/html/docs/buttons.html b/HTML/EN/html/docs/buttons.html index f4498b0b3a3..07eacb82d51 100644 --- a/HTML/EN/html/docs/buttons.html +++ b/HTML/EN/html/docs/buttons.html @@ -43,7 +43,7 @@

    Mappings

    Code to Button Name

    The code to button name mapping is contained within .ir files located - in the IR subfolder of the Squeezebox Server folder. The files + in the IR subfolder of the Logitech Media Server folder. The files consist of lines with the button name followed by an equals sign (=) followed by the IR code in hex (no 0x necessary). Everything after a # is considered a comment. Leading and trailing whitespace is ignored, as is whitespace @@ -81,7 +81,7 @@

    Code to Button Name
    Button Name to Function

    The button name to function mapping is contained within .map files - located in the IR subfolder of the Squeezebox Server folder. + located in the IR subfolder of the Logitech Media Server folder. The files consist of lines with the button name followed by an equals sign (=) followed by the function. Everything after a # is considered a comment. Leading and trailing whitespace diff --git a/HTML/EN/html/docs/cli-api.html b/HTML/EN/html/docs/cli-api.html index 9fc71e03dea..6a77dc16c1a 100644 --- a/HTML/EN/html/docs/cli-api.html +++ b/HTML/EN/html/docs/cli-api.html @@ -10,12 +10,12 @@

    Introduction

    - The Squeezebox Server provides a command-line interface to the + the Logitech Media Server provides a command-line interface to the players via TCP/IP. After starting the server, commands and queries may be sent by connecting to a specific TCP/IP port. The server will reply echoing the request (for commands) or by returning the - requested data (for queries). By default, the Squeezebox Server will listen + requested data (for queries). By default, the server will listen for connections on TCP/IP port 9090. This format is designed for ease of integration into AMX, Crestron and other automation systems. @@ -24,7 +24,7 @@

    Introduction

    The end of line separator is line feed (<LF> ASCII decimal 10, hexadecimal 0x0A). The server accepts LF, CR or 0x00 (or any combination thereof) as end of line, and replies with whatever was used for the command. - For strings, Squeezebox Server uses the UTF-8 character-set encoding. + For strings, Logitech Media Server uses the UTF-8 character-set encoding.

    To use the command line interface interactively, use the telnet @@ -298,9 +298,9 @@

    <playerid> is the unique identifier for the player, usually (but not guaranteed to be) the MAC address of the - player. Some commands are global to the Squeezebox Server and do not + player. Some commands are global to the server and do not require a <playerid>. For commands requiring it, - a random player will be selected by the Squeezebox Server if the + a random player will be selected by the server if the <playerid> is omitted, and returned in the server reply. <playerid> may be obtained by using the "player id" or "players" queries. @@ -308,7 +308,7 @@

    <p0> through <pN> are positional parameters. Pass a "?" to obtain a - value for that parameter in the Squeezebox Server response (i.e. send a + value for that parameter in the server response (i.e. send a query). Details of the parameters vary for each command as described below.

    @@ -478,7 +478,7 @@

    Extended command format

    Notes

      -
    • The Security settings of the Squeezebox Server preferences apply to CLI +
    • The Security settings of the server preferences apply to CLI connections when they are established. A change in security settings do not affect established connections. The connection is only accepted from allowed hosts. If password protection is @@ -487,7 +487,7 @@

      Notes

      user and/or password, or using any other command as the first one, results in the server disconnecting.
    • -
    • All Squeezebox Server preferences apply to the CLI data. For examples, the +
    • All Logitech Media Server preferences apply to the CLI data. For examples, the preference about composers appearing in the artists list applies to the data returned by the "artists" query.
    • @@ -509,7 +509,7 @@

      Notes

      the given song, the server returns special "no artwork" image. Please refer to the Artwork Setup documentation for more details on artwork management in - Squeezebox Server. Use the following URL: + Logitech Media Server. Use the following URL:
      http://<server>:<port>/music/<track_id>/cover.jpg @@ -598,7 +598,7 @@

      • General: general management of the Command Line - Interface and of the Squeezebox Server. + Interface and of the server.
      • Players: management of players. @@ -625,8 +625,8 @@

      • Plugins: commands and queries - proposed by various Squeezebox Server plugins. These are only available if - the plugin is enabled in the Squeezebox Server configuration. The query + proposed by various server plugins. These are only available if + the plugin is enabled in the server configuration. The query "can" can be used to determine if a command or query is available.
      • @@ -698,7 +698,7 @@

        The "login" command allows the caller to authenticate itself on - the server, as defined in the Security pane of the Squeezebox Server preferences. + the server, as defined in the Security pane of the server preferences. Like any other command, the user and password must be escaped. If successful, the server replaces the password with 6 star characters. If unsuccessful, the server disconnects. If security is off this command is @@ -760,7 +760,7 @@

        - The "version" query returns version number of Squeezebox Server. + The "version" query returns version number of the server.

        Examples: @@ -785,7 +785,7 @@

        The "listen" command enables to receive asynchronously internal server commands (notifications) on the CLI connection. Notifications concern - all activity in the Squeezebox Server, not just the activity triggered by the + all activity in the server, not just the activity triggered by the command-line. Use 0 to clear, 1 to set, ? to query, and no parameter to toggle the listen state of the command-line connection.
        @@ -866,7 +866,7 @@

        The "pref" command allows the caller to set and query the - Squeezebox Server's internal preference values. The following affect the + server's internal preference values. The following affect the behaviour of CLI queries and commands:

        • @@ -961,7 +961,7 @@

          The "pref validate" command allows the caller to validate a - Squeezebox Server's internal preference value without setting it. + server's internal preference value without setting it.

          If you want to validate a preference from an other namespace than "server" @@ -2138,7 +2138,7 @@

          The "playerpref" command allows the caller to set and query the - Squeezebox Server's internal player-specific preferences values. + server's internal player-specific preferences values.

          If you want to query/set a preference from an other namespace than "server" @@ -2174,7 +2174,7 @@

          The "playerpref validate" command allows the caller to validate a - Squeezebox Server's internal player-specific preference value without setting it. + server's internal player-specific preference value without setting it.

          If you want to validate a preference from an other namespace than "server" @@ -2342,7 +2342,7 @@

          The "disconnect" command tells a Squeezebox 2 or newer player - on another Squeezebox Server instance to disconnect from its server and + on another server instance to disconnect from its server and connect to us. This is the opposite of "connect", where we tell a player connected to us to connect to a different server.
          @@ -2376,7 +2376,7 @@

          The "players" query returns information about all "players" (physical players as well as streaming clients) - known by the Squeezebox Server. + known by the server.

          Accepted tagged parameters: @@ -2424,7 +2424,7 @@

          count - Number of players known by Squeezebox Server. Equivalent to + Number of players known by the server. Equivalent to "player count ?". @@ -2641,11 +2641,11 @@

          - The "rescan" command causes Squeezebox Server to rescan the entire music + The "rescan" command causes the server to rescan the entire music library, reloading the music file information. If "playlists" is indicated ("rescan playlists"), only the playlist directory is rescanned. Issued with a "?", "rescan ?" returns if the - Squeezebox Server is currently scanning. Scanning occurs when Squeezebox Server starts and + server is currently scanning. Scanning occurs when the server starts and following "rescan" and "wipecache" commands.

          @@ -2787,7 +2787,7 @@

          - The "abortscan" command causes Squeezebox Server to cancel a running scan. + The "abortscan" command causes the server to cancel a running scan. Please note that after stopping a scan this way you'll have to fully rescan your music collection to get consistent data.

          @@ -2811,7 +2811,7 @@

          - The "wipecache" command allows the caller to have the Squeezebox Server + The "wipecache" command allows the caller to have the server rescan its music library, reloading the music file information. This differs from the "rescan" command in that it first clears the tag database. During a rescan triggered by "wipecache", @@ -3233,7 +3233,7 @@

          rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -3453,7 +3453,7 @@

          rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -3503,7 +3503,7 @@

            album - Album name, including Squeezebox Server's added "(N of M)" if + Album name, including the server's added "(N of M)" if the server is set to group multi disc albums together. See tag "title" for the unmodified value. @@ -3516,7 +3516,7 @@

            year - Album year. This is determined by Squeezebox Server based on the album + Album year. This is determined by the server based on the album tracks. @@ -3773,7 +3773,7 @@

          The "musicfolder" query returns the content of a given music - folder, starting from the top level directory configured in Squeezebox Server. + folder, starting from the top level directory configured in the server.

          Accepted tagged parameters: @@ -3810,7 +3810,7 @@

          Browses the folder identified by "url". If the content - of "url" did not happen to be in the Squeezebox Server database, it is + of "url" did not happen to be in the server database, it is added to it.
          "url" has precedence over "folder_id" if both are @@ -4000,7 +4000,7 @@

          rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -4126,7 +4126,7 @@

          rescan - Returned with value 1 if the Squeezebox Server is still scanning the database. The results may therefore be incomplete. + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -4532,7 +4532,7 @@

          rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -4799,7 +4799,7 @@

          modificationTime - Date and time song file was last changed. + Date and time song file was last changed on disk. @@ -4846,6 +4846,28 @@

          Genre IDs, separated by commas (only useful if the server is set to handle multiple items in tags). + + + D + + + addedTime + + + Date and time song file was first added to the database. + + + + + U + + + lastUpdated + + + Date and time song file was last updated in the database. + + q @@ -5014,7 +5036,7 @@

          album:All%20for%20You modificationTime:Thursday%2C%20March%201%2C%202007%2C%209:21:58%20PM type:mp3 genre_id:2 bitrate:160kbps%20VBR artist_id:3 tracknum:12 tagversion:ID3v2.3.0 year:1995 samplerate:44100 - url:file:%2F%2F%2FUsers%2Ffred%2FPrograms%2FSqueezebox Server%2FMusic%2F12%2520-%2520If%2520I%2520Had%2520You.mp3 + url:file:%2F%2F%2FUsers%2Ffred%2FPrograms%2FLogitech Media Server%2FMusic%2F12%2520-%2520If%2520I%2520Had%2520You.mp3 <LF>"

      @@ -5032,7 +5054,7 @@

      - The "titles" command returns all titles known by the Squeezebox Server. + The "titles" command returns all titles known by the server.

      Accepted tagged parameters: @@ -5138,7 +5160,7 @@

      rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -5267,7 +5289,7 @@

      rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -6503,7 +6525,7 @@

      rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The command may therefore have missed items. Not returned if no scan is in progress. @@ -6648,7 +6670,7 @@

      rescan - Returned with value 1 if Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -6702,7 +6724,7 @@

      version - Squeezebox Server version. Equivalent to + Logitech Media Server version. Equivalent to "version ?" @@ -6711,7 +6733,7 @@

      info total albums - Number of albums known to Squeezebox Server. Equivalent to + Number of albums known to the server. Equivalent to "info total albums ?" @@ -6720,7 +6742,7 @@

      info total artists - Number of artists known to Squeezebox Server. Equivalent to + Number of artists known to the server. Equivalent to "info total artists ?" @@ -6729,7 +6751,7 @@

      info total genres - Number of genres known to Squeezebox Server. Equivalent to + Number of genres known to the server. Equivalent to "info total genres ?" @@ -6738,7 +6760,7 @@

      info total songs - Number of songs known to Squeezebox Server. Equivalent to + Number of songs known to the server. Equivalent to "info total songs ?" @@ -6766,7 +6788,7 @@

      player count - Number of players known by Squeezebox Server. Equivalent to + Number of players known by the server. Equivalent to "player count ?". @@ -6936,13 +6958,13 @@

      other player count - Number of players connected to other discovered Squeezebox Servers in the local network. + Number of players connected to other discovered servers in the local network. - For each player connected to some other Squeezebox Server in the local network: + For each player connected to some other server in the local network: @@ -6967,7 +6989,7 @@

        server - Squeezebox Server to which the player is connected + The server to which the player is connected @@ -7022,9 +7044,9 @@

      player, including the current playlist. Set the <start> parameter to "-" to get the playlist data starting from the current song.
      - In this "curent" mode and if repeat is on, Squeezebox Server will attempt + In this "curent" mode and if repeat is on, the server will attempt to return <itemsPerResponse> elements, by repeating the playlist at - most once, unless shuffling is on and Squeezebox Server is configured to re-shuffle + most once, unless shuffling is on and the server is configured to re-shuffle the playlist at each loop (in which case it is impossible to predict the song following the last one in the playlist until this last song has finished playing). @@ -7089,7 +7111,7 @@

      change detection "algorithm".
      If the player is manually (through the web page) or automatically - deleted from Squeezebox Server, the status query returns the "error" + deleted from the server, the status query returns the "error" tag with value "invalid player" and the subscription is terminated.
      Please note this mechanism is completely distinct from the @@ -7115,7 +7137,7 @@

      rescan - Returned with value 1 if the Squeezebox Server is still scanning the + Returned with value 1 if the server is still scanning the database. The results may therefore be incomplete. Not returned if no scan is in progress. @@ -7555,7 +7577,7 @@

      • filter:foldersonly - list folders only
      • filter:filesonly - list files only -
      • filter:musicfiles - list all files considered music files by Squeezebox Server; +
      • filter:musicfiles - list all files considered music files by the server; this is the same filter as is used when scanning the disk for music
      • filter:filetype:xyz - list file type .xyz only
      • filter:xyz - any expression filter path/filenames @@ -7636,7 +7658,7 @@

        A new client is notified using "client new". "client disconnect" is sent when a client disconnects. Unless it reconnects (as signaled by "client reconnect") before a number of - minutes, the client will be automatically forgotten by Squeezebox Server (as + minutes, the client will be automatically forgotten by the server (as indicated by command/notification "client forget".)

        @@ -7865,7 +7887,7 @@

        url (or playlisturl) URL of the alarm playlist. Default: the current playlist. - url should be a valid Squeezebox Server audio url. + url should be a valid Logitech Media Server audio url. The special value 0 means the current playlist.
        Example values:
          @@ -8095,8 +8117,8 @@

          Plugins commands and queries

          - The following command and queries are proposed by Squeezebox Server plugins. The - plugin must be enabled in the Squeezebox Server configuration for the commands + The following command and queries are proposed by server plugins. The + plugin must be enabled in the server configuration for the commands and queries to be available to the CLI client. Please use query "can" to determine if the given command or query is available. Query "radios" can diff --git a/HTML/EN/html/docs/display.html b/HTML/EN/html/docs/display.html index ac97312b0c4..22ed9098dd3 100644 --- a/HTML/EN/html/docs/display.html +++ b/HTML/EN/html/docs/display.html @@ -580,12 +580,12 @@

          Character Displays
          display. These may be defined by plugins and used anywhere on the display.

          -

          Squeezebox Server allows you to define many custom characters using: +

          Logitech Media Server allows you to define many custom characters using: Slim::Display::Text::setCustomChar().

          Each display screen can use up to 8 custom characters. If more custom characters exist on a screen they will be replaced with a blank -character. [NB Squeezebox Server also uses custom characters for the +character. [NB Logitech Media Server also uses custom characters for the predefined symbols which also count towards this limit.]

          Each custom character is 5 pixels wide and 7 pixels high plus an diff --git a/HTML/EN/html/docs/fonts.html b/HTML/EN/html/docs/fonts.html index 6931e5a2e9a..4be23781915 100644 --- a/HTML/EN/html/docs/fonts.html +++ b/HTML/EN/html/docs/fonts.html @@ -47,7 +47,7 @@

          Squeezebox Graphics Font Files

        The inter-character spacing character must always be present. -However if any pixels are set in it, then Squeezebox Server interprets this +However if any pixels are set in it, then the server interprets this to mean no inter-character spacing. This is useful for font files defining custom characters which are intented to be displayed without space between them. @@ -56,7 +56,7 @@

        Squeezebox Graphics Font Files

        We used photoshop to create the font files, saving them as 1bpp Windows BMP files. -

        If you modify a font file, you'll need to restart Squeezebox Server +

        If you modify a font file, you'll need to restart the server to see your changes.

        Custom Fonts
        @@ -65,7 +65,7 @@
        Custom Fonts
        should be distributed with font files which follow the naming convention:

        < fontname > . < line_number > . font . bmp -

        These files should be placed in the plugin's root directory and Squeezebox Server +

        These files should be placed in the plugin's root directory and the server restarted before they are available to the server.

        Custom fonts files define characters for the fontname specified by diff --git a/HTML/EN/html/docs/http.html b/HTML/EN/html/docs/http.html index e21c0e2cf03..d7d3258d394 100644 --- a/HTML/EN/html/docs/http.html +++ b/HTML/EN/html/docs/http.html @@ -1,19 +1,19 @@ -[% pagetitle = 'Squeezebox Server Web Interface' %] +[% pagetitle = 'Logitech Media Server Web Interface' %] [% techinfo = '1' %] [% lefttoright = '1' %] [% PROCESS helpheader.html %]

        Overview

        This document describes the interface to the HTTP server that's built into - the Squeezebox Server.

        -

        The Squeezebox Server provides an HTTP server that can be used to:

        + the Logitech Media Server.

        +

        Logitech Media Server provides an HTTP server that can be used to:

        1. Browse the music library.
        2. View the status and playlist of the player.
        3. Control the player.
        4. Configure the server.
        -

        When the Squeezebox Server is started, it starts listening for HTTP connections +

        When the server is started, it starts listening for HTTP connections on the default port of 9000.

        The HTTP server may be accessed by the user with a traditional web browser to navigate around the music library and control the player. The HTTP server @@ -21,7 +21,7 @@

        Overview

        or curl, for example) as a way to access and control the player via HTTP. The server can return XML instead of HTML for such "automation" uses (see The XML Skin documentation.)

        -

        In the examples in this document the Squeezebox Server is running on a computer +

        In the examples in this document the server is running on a computer with the IP address of 10.0.1.201.

        HTTP Access

        To access the main page to control the player via a web browser use this URL: @@ -57,7 +57,7 @@

        HTTP Access

        Note: Commands that use paths to songs or playlists can use relative paths from the root of the Music Library folder to specify songs. For example, if the Music Library is specified as "D:\mymusic" and you'd like to refer to a song in that folder named "foo.mp3" you can specify just "foo.mp3" in the command parameter. Likewise, to refer to items in the Saved Playlist folder, you can use a prefix of "__playlists/" before the path. For example, to refer to the saved playlist "bar.m3u" in the Saved Playlists folder, you can specify a path of "__playlists/bar.m3u".

        Commands

        The following is a summary of the supported commands. Additional information - about the command set is available in the Squeezebox Server + about the command set is available in the Logitech Media Server Command Line Interface documentation.

        @@ -337,37 +337,37 @@

        Commands

        CSRF Security Measures

        -

        To protect against "Cross Site Request Forgery" (CSRF) security threats, Squeezebox Server applies special scrutiny to HTTP requests for functions that can make changes to your system or manipulate playlists or players. -This scrutiny is important to understand if you want to "bookmark" such a URL, or control Squeezebox Server via the HTTP interface. -Squeezebox Server requires one of four things to be true in order to allow such control-oriented URLs to be accepted:
        +

        To protect against "Cross Site Request Forgery" (CSRF) security threats, Logitech Media Server applies special scrutiny to HTTP requests for functions that can make changes to your system or manipulate playlists or players. +This scrutiny is important to understand if you want to "bookmark" such a URL, or control the server via the HTTP interface. +Logitech Media Server requires one of four things to be true in order to allow such control-oriented URLs to be accepted:

        -
        Referer request header matches Squeezebox Server URL -
        Squeezebox Server will accept an HTTP URL/command if the request includes a "Referer" request header that matches the "Host" request header. -If you're using a web browser and clicking on links in the web interface (for instance, the Previous/Skip/Play/Pause links on the right-hand player pane), your browser will send a Referer header that tells Squeezebox Server it's following a link you clicked on from a Squeezebox Server page, and the request will be accepted. +
        Referer request header matches Logitech Media Server URL +
        The server will accept an HTTP URL/command if the request includes a "Referer" request header that matches the "Host" request header. +If you're using a web browser and clicking on links in the web interface (for instance, the Previous/Skip/Play/Pause links on the right-hand player pane), your browser will send a Referer header that tells Logitech Media Server it's following a link you clicked on from a Logitech Media Server page, and the request will be accepted. If you are using custom software to make the HTTP requests, simply make sure the HTTP request includes a Referer header with the same value as the URL you are requesting, and a Host header that includes the :port information (as described in the HTTP standard) and all will be fine.
        Submission includes form-specific token -
        Squeezebox Server embeds special authorization tokens in most settings pages in the web interface. If a request includes a +
        The server embeds special authorization tokens in most settings pages in the web interface. If a request includes a valid form authorization token, it will be processed.
        "cauth" URL parameter presented and valid
        If you're using a Bookmark/Favorite, no Referer request header is sent. -In such a case, Squeezebox Server cannot tell if your request is legitimate, or your browser following an <IMG> tag in a hostile web page or HTML email. +In such a case, the server cannot tell if your request is legitimate, or your browser following an <IMG> tag in a hostile web page or HTML email. In such cases, you will see a "403 Forbidden" error page. -On this page you'll see a URL similar to what you requested, but with a ";cauth=" parameter added to the end, e.g. when denying a bookmarked request for http://10.0.1.201:9000/status.html?p0=rescan, Squeezebox Server will offer you a clickable link with a URL like

        +On this page you'll see a URL similar to what you requested, but with a ";cauth=" parameter added to the end, e.g. when denying a bookmarked request for http://10.0.1.201:9000/status.html?p0=rescan, the server will offer you a clickable link with a URL like

        http://10.0.1.201:9000/status.html?p0=rescan;cauth=aa2d378f7e9f18611e951e7c6b30eea8

        By clicking on this link, you can execute your HTTP command. If you want to bookmark a URL that gives such an error, bookmark the "cauth" URL displayed on the error page. -"cauth" URIs are unique for each Squeezebox Server installation. They are based on a special "securitySecret" that is randomly assigned the first time you start the Squeezebox Server software. +"cauth" URIs are unique for each Logitech Media Server installation. They are based on a special "securitySecret" that is randomly assigned the first time you start the server software. This allows the same URL like http://10.0.1.201:9000/status.html?p0=rescan;cauth=aa2d378f7e9f18611e951e7c6b30eea8 -to always work on your Squeezebox Server installation (so you can bookmark it or use it in your home automation system), but not work on another Squeezebox Server setup. -This unpredicatbility makes it virtually impossible for a hostile web site to trick your Squeezebox Server into doing something you don't want. +to always work on your server installation (so you can bookmark it or use it in your home automation system), but not work on another server setup. +This unpredicatbility makes it virtually impossible for a hostile web site to trick your server into doing something you don't want.

        By default, the same "cauth" value is accepted for any URI. So once you note the "cauth" value for your system, you can use that same value with any URI/command documented here. @@ -376,13 +376,13 @@

        CSRF Security Measures



        If you want greater protection against CSRF attacks, you may set your csrfProtectionLevel server preference to "HIGH" so that each different command/URI will insist on a unique (but reusable) "cauth=" value. For instance, the "cauth" parameter for http://10.0.1.201:9000/status.html?p0=playlist&p1=play&p2=soothing would be completely different for the parameter for http://10.0.1.201:9000/status.html?p0=playlist&p1=play&p2=loud-alarm -This also makes it more difficult for an attacker to trick your Squeezebox Server into doing something you don't want. +This also makes it more difficult for an attacker to trick your server into doing something you don't want.
        Request appears to be an AJAX/XmlHttpRequest call
        Requests bearing X-Requested-With headers indicating that they are legitimate XmlHttpRequest calls will be allowed, -as Javascript/XmlHttpRequest security guidelines and Squeezebox Server username/password authentication should make -JAX/XmlHttpRequest calls safe to act on. +as Javascript/XmlHttpRequest security guidelines and the server username/password authentication should make +AJAX/XmlHttpRequest calls safe to act on.
        @@ -421,7 +421,7 @@

        Multiple Players

        Player Status

        -

        When you use the HTTP interface to control the Squeezebox Server (and player) to +

        When you use the HTTP interface to control the server (and player) to obtain status the server returns a response that contains:

        • A header indicating a content type
        • @@ -472,8 +472,8 @@

          The following is an example of an HTTP status transactions. -The text in blue is sent from the client to the Squeezebox Server HTTP server. -Text in red is returned by the Squeezebox Server HTTP server. +The text in blue is sent from the client to the HTTP server. +Text in red is returned by the HTTP server.

          
           GET /status.html?p0=pause&p1=1 HTTP/1.0
          diff --git a/HTML/EN/html/docs/index.html b/HTML/EN/html/docs/index.html
          index d1a2917d8d0..d4aa16722db 100644
          --- a/HTML/EN/html/docs/index.html
          +++ b/HTML/EN/html/docs/index.html
          @@ -3,12 +3,12 @@
           
           [% WRAPPER helpTopicList %]
           	[% PROCESS helpTopic href="artwork.html" title="Artwork Setup" %]
          -	[% PROCESS helpTopic href="http.html" title="The Squeezebox Server Remote Control" %]
          -	[% PROCESS helpTopic href="cli-api.html" title="The Squeezebox Server Command Line Interface" %]
          +	[% PROCESS helpTopic href="http.html" title="The Logitech Media Server Remote Control" %]
          +	[% PROCESS helpTopic href="cli-api.html" title="The Logitech Media Server Command Line Interface" %]
           	[% PROCESS helpTopic href="skins.html" title="Skin Creation" %]
           	[% PROCESS helpTopic href="xml_skin.html" title="The XML Skin" %]
          -	[% PROCESS helpTopic href="xpl.html" title="The Squeezebox Server xPL Interface" %]
          -	[% PROCESS helpTopic href="plugins.html" title="Squeezebox Server Plugins" %]
          +	[% PROCESS helpTopic href="xpl.html" title="The Logitech Media Server xPL Interface" %]
          +	[% PROCESS helpTopic href="plugins.html" title="Logitech Media Server Plugins" %]
           	[% PROCESS helpTopic href="buttons.html" title="Button Mapping" %]
           	[% PROCESS helpTopic href="input.html" title="Input Modes" %]
           	[% PROCESS helpTopic href="fonts.html" title="Font Files" %]
          diff --git a/HTML/EN/html/docs/input.html b/HTML/EN/html/docs/input.html
          index 6e6f5582992..15cd74a97e0 100644
          --- a/HTML/EN/html/docs/input.html
          +++ b/HTML/EN/html/docs/input.html
          @@ -5,7 +5,7 @@
           
             

          Overview

          - The Squeezebox Server software comes equipped with a number (currently five) of + The Logitech Media Server software comes equipped with a number (currently five) of generic input modes which can be used by other modes to handle interaction with the user via the remote. This allows module writers to concentrate on what to do with the input rather than the gathering of that input. diff --git a/HTML/EN/html/docs/plugins.html b/HTML/EN/html/docs/plugins.html index 3357e06dd8e..eec73ec0996 100644 --- a/HTML/EN/html/docs/plugins.html +++ b/HTML/EN/html/docs/plugins.html @@ -1,16 +1,16 @@ -[% pagetitle = 'Squeezebox Server Plugins' %] +[% pagetitle = 'Logitech Media Server Plugins' %] [% techinfo = '1' %] [% lefttoright = '1' %] [% PROCESS helpheader.html %]

          Introduction

          -

          This document illustrates the basic framework upon which to build a Plugin or module compatible with the Squeezebox Server software. -The Squeezebox Server provides a method to load custom modules at startup which are then made available to the user via remote control menus. -Each plugin serves as an area within Squeezebox Server remote menu system, available from within the Plugins menu. Plugin files are stored in -the "Plugins" folder which is in the same folder as the Squeezebox Server software. For simple plugins, a single file in this folder will suffice. +

          This document illustrates the basic framework upon which to build a Plugin or module compatible with the Logitech Media Server software. +The server provides a method to load custom modules at startup which are then made available to the user via remote control menus. +Each plugin serves as an area within the server remote menu system, available from within the Plugins menu. Plugin files are stored in +the "Plugins" folder which is in the same folder as the server software. For simple plugins, a single file in this folder will suffice. For more complex plugins, you can store an entire set of files in a sub-folder, naming the main plugin file: Plugin.pm. The Plugin interface can provide a very powerful -control and has complete access to the functionality of the Squeezebox Server. As with the rest of the Squeezebox Server, plugin modules are created +control and has complete access to the functionality of the server. As with the rest of the server, plugin modules are created using the Perl language.

          Perl Module Basics

          @@ -20,8 +20,8 @@

          Perl Module Basics

          package Plugins::pluginname;

          Where pluginname is the name of the module (which should be the same as the filename, without the .pm extension.) This defines the 'namespace' for the module. It essentially sets up the module as an entity of its own, within the server environment. This allows you to then refer to the functions and variables within this plugin by the full reference Plugins::pluginname::function.


          -

          Squeezebox Server Plugin Hooks

          -

          Each level in the Squeezebox Server menu hierarchy is considered a "mode" by the Squeezebox Server. Each time the server is started, it reads the Plugins directory for modules. Each is added, by name, into a list. Each plugin is given a mode, and a set of functions that are defined within that module. The plugins can each be enabled or disabled at will from the web interface. The plugin module itself must define a mode and functions in a form that the server is expecting. This comes from two functions: sub setMode() and sub getFunctions(). A third subroutine, sub getDisplayName() is required to provide the name that the server should display for the plugin. Simple examples of these three functions are below. We will now build a template based on these main functions.

          +

          Logitech Media Server Plugin Hooks

          +

          Each level in the server menu hierarchy is considered a "mode" by the server. Each time the server is started, it reads the Plugins directory for modules. Each is added, by name, into a list. Each plugin is given a mode, and a set of functions that are defined within that module. The plugins can each be enabled or disabled at will from the web interface. The plugin module itself must define a mode and functions in a form that the server is expecting. This comes from two functions: sub setMode() and sub getFunctions(). A third subroutine, sub getDisplayName() is required to provide the name that the server should display for the plugin. Simple examples of these three functions are below. We will now build a template based on these main functions.

          Example 1

          @@ -45,7 +45,7 @@ 

          Squeezebox Server Plugin Hooks


          Modes

          -

          If you wish for your plugin to have a player display interface, then you will need to set up what is called a Mode. The remote buttons are context sensitive, meaning that they can serve different roles when the Squeezebox Server is in different modes. The setMode() +

          If you wish for your plugin to have a player display interface, then you will need to set up what is called a Mode. The remote buttons are context sensitive, meaning that they can serve different roles when the server is in different modes. The setMode() subroutine defines this mode. Within this subroutine, there must be a definition for $client->lines, which is the text to be displayed on the Slim client while in this plugin mode. Typically, this is labeled just as above, though it can be any name you wish. The lines subroutine, or other name if you have chosen one, returns a hash defining the display to be shown on the player. This can be updated at any time from any point in the plugin module by using the @@ -74,7 +74,7 @@

          Modes


          Functions

          -

          The Squeezebox Server handles all commands from the remote control for each mode by creating a hash table of functions, each button having a subroutine associated with it. The subroutine getFunctions() returns a reference to this hash, and can be any label you wish, although typically %functions is used. The call to point to this list is shown above in example 1. The function list, should look something like this example taken from rescan.pm, which is included with the Squeezebox Server:

          +

          The server handles all commands from the remote control for each mode by creating a hash table of functions, each button having a subroutine associated with it. The subroutine getFunctions() returns a reference to this hash, and can be any label you wish, although typically %functions is used. The call to point to this list is shown above in example 1. The function list, should look something like this example taken from rescan.pm, which is included with the server:

          Example 2

          @@ -113,7 +113,7 @@ 

          Functions

          function calls such as:

          $client->showBriefly();
          -

          Examples of remote control functions include: 'up','down','play,'add' (REC button),'left','right','numberScroll' and 'stop' The full button to function map is found in the Default.map file, which is in the IR directory under the Squeezebox Server directory.

          +

          Examples of remote control functions include: 'up','down','play,'add' (REC button),'left','right','numberScroll' and 'stop' The full button to function map is found in the Default.map file, which is in the IR directory under the Logitech Media Server directory.


          Player Menu

          @@ -153,7 +153,7 @@

          Lines


          Strings

          -

          The plugin API also allows you to add in your own localization. The format of the strings list follows the same format as the strings.txt file used by the Squeezebox Server for localization. The function strings() can be used within the plugin to extract a strings for the user's specified language. Defining the strings is done as follows:

          +

          The plugin API also allows you to add in your own localization. The format of the strings list follows the same format as the strings.txt file used by the server for localization. The function strings() can be used within the plugin to extract a strings for the user's specified language. Defining the strings is done as follows:

          Example 6

          sub strings { return '
          @@ -173,7 +173,7 @@ 

          Strings

          One special note, the format of the strings list is very strict. The whitespace must be a tab, not spaces, which is why the tabs are shown above.


          Web Interface

          -

          Squeezebox Server Plugins can expose their own web interface, accessible through +

          Logitech Media Server Plugins can expose their own web interface, accessible through the main server's web pages. To do this, include a function called "webPages" which returns a list of two values: a hash reference to handler functions for the plugin's pages, and a string representing the path of @@ -186,8 +186,8 @@

          Web Interface

          "index.html", "index.htm" or "index.xml".

          The index page string represents the URL path for a link that will -be included in the "Plugins" section of the Squeezebox Server index -page. When exposed through the Squeezebox Server's web interface, all plugin +be included in the "Plugins" section of the server index +page. When exposed through the server's web interface, all plugin web pages are prepended with the URL path http://<host>/plugins/<pluginname>/. However, neither the regular expression keys nor the index URL path need to take this prefix @@ -207,7 +207,7 @@

          Web Interface

          Plugins also have the option of adding links to other sections of -the Squeezebox Server index page. Specifically, links can be added to the +the server index page. Specifically, links can be added to the "browse", "search", "settings", "plugins" and "help" sections. Note that not all skins may support every section. Links can be added using the Slim::Web::Pages::addLinks() method. The method takes two @@ -243,7 +243,7 @@

          ScreenSavers

          getScreensaverFunctions()
          This subroutine, just like getFunctions points to the function has for the screensaver mode.
          setScreensaverMode
          subroutine just like setMode to initialize anything you need for the screensaver mode.
          leaveScreensaverMode
          subroutine to execute before the mode exits
          -
          $client->string('SCREENSAVER_NAME')
          SCREENSAVER_NAME should be change to a unique identifier for your plugin name. This can be the same as your plugin, or something different. This allows for future nationalisation for the other languages supported by Squeezebox Server.
          +
          $client->string('SCREENSAVER_NAME')
          SCREENSAVER_NAME should be change to a unique identifier for your plugin name. This can be the same as your plugin, or something different. This allows for future nationalisation for the other languages supported by server.

          @@ -260,7 +260,7 @@

          Other Functions


          Summary

          -

          Using the existing plugins as examples (one appears below) and this document as an explanation of what each section of the plugin can do, you should now be able to start working on a plugin of your own. Remember that this is only a framework to allow you to hook into the Squeezebox Server. There are always many other ways to implement the features of a plugin. As long as your provide the lines from the examples above, the server will try to work with your Plugin. The rest can be just about anything you want, including using any of functions and subroutines within the Squeezebox Server. Remember, there's more than one way to do it.

          +

          Using the existing plugins as examples (one appears below) and this document as an explanation of what each section of the plugin can do, you should now be able to start working on a plugin of your own. Remember that this is only a framework to allow you to hook into the server. There are always many other ways to implement the features of a plugin. As long as your provide the lines from the examples above, the server will try to work with your Plugin. The rest can be just about anything you want, including using any of functions and subroutines within the server. Remember, there's more than one way to do it.

          Happy Coding!


          NOTE:

          @@ -275,7 +275,7 @@

          Appendix: Sample Plugin

          # # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/HTML/EN/html/docs/remotestreaming.html b/HTML/EN/html/docs/remotestreaming.html index 5e096654d7b..8977a1a9f46 100644 --- a/HTML/EN/html/docs/remotestreaming.html +++ b/HTML/EN/html/docs/remotestreaming.html @@ -1,27 +1,27 @@ [% pagetitle = 'REMOTE_STREAMING' | string %] [% PROCESS helpheader.html %] -

          The Squeezebox Server was designed to stream mp3 files to a Slim Devices/Logitech network music player. However, it can also stream the same files over the Internet to an MP3 software player such as Winamp and iTunes. +

          The Logitech Media Server was designed to stream mp3 files to a Slim Devices/Logitech network music player. However, it can also stream the same files over the Internet to an MP3 software player such as Winamp and iTunes. -

          For the sake of discussion, the computer running the Squeezebox Server will be called the remote machine. +

          For the sake of discussion, the computer running the server will be called the remote machine. -

          First install and start the Squeezebox Server software on this machine. +

          First install and start the Logitech Media Server software on this machine. Make sure it is reachable over the Internet. If not, you will need to open port 9000 on your router.

          Now, use the following instructions:

            -
          1. Open the stream called http://localhost:9000/stream.mp3 in your MP3 software player. (Replace "localhost" with the IP address of the remote computer.) This will inform the Squeezebox Server that the software player is ready to receive a stream. +
          2. Open the stream called http://localhost:9000/stream.mp3 in your MP3 software player. (Replace "localhost" with the IP address of the remote computer.) This will inform the server that the software player is ready to receive a stream. -
          3. Open the web interface of the Squeezebox Server running on the remote computer by opening the web page http://localhost:9000 (Replace "localhost" with the IP address of the remote computer). You will notice a "player" corresponding to the IP address of the computer with the MP3 software player. +
          4. Open the web interface of the server running on the remote computer by opening the web page http://localhost:9000 (Replace "localhost" with the IP address of the remote computer). You will notice a "player" corresponding to the IP address of the computer with the MP3 software player. -
          5. Use the left pane of the Squeezebox Server web interface to browse and select files and playlists. When music is selected, it will appear in the right pane of the web interface. +
          6. Use the left pane of the server web interface to browse and select files and playlists. When music is selected, it will appear in the right pane of the web interface. -
          7. Click on "Play" in the right pane of the Squeezebox Server web interface to start the music. +
          8. Click on "Play" in the right pane of the server web interface to start the music.
          9. After a couple of seconds, you will hear music playing through the MP3 software player. (The delay is due to buffering in the MP3 player software.) -
          10. To change the content playing, use the Squeezebox Server on the remote machine. +
          11. To change the content playing, use the server on the remote machine. -
          12. If you are using the Squeezebox Server's password security, you'll need to use a slightly modified URL like this: http://username:password@localhost:9000/stream.mp3 +
          13. If you are using the server's password security, you'll need to use a slightly modified URL like this: http://username:password@localhost:9000/stream.mp3

          Your music can also be streamed to a Squeezebox or Transporter network music player for listening on a stereo. For more information about this product and FAQs, visit www.mysqueezebox.com. diff --git a/HTML/EN/html/docs/skins.html b/HTML/EN/html/docs/skins.html index b65d55cd8d5..63a5bbadd0d 100644 --- a/HTML/EN/html/docs/skins.html +++ b/HTML/EN/html/docs/skins.html @@ -7,9 +7,9 @@

          Overview

          WARNING: This documentation is substantially out of date.

          - The web interface to the Squeezebox Server makes use of customizable html + The web interface to the Logitech Media Server makes use of customizable html templates collected together into a skin. These skins reside in the - html subfolder of the folder where the Squeezebox Server software was + html subfolder of the folder where the server software was installed. The skin subfolders are presented for selection in the additional server settings setup page based on the name of the skin subfolder. The default skin is in the EN subfolder. Each @@ -19,7 +19,7 @@

          Overview

          When a page not in the html subfolder of either your skin - or the default skin is requested, the Squeezebox Server builds the page + or the default skin is requested, the server builds the page dynamically based on the templates within the skin subfolder. This building is accomplished by gathering information relevant to the requested page in a perl subroutine, then using that information to complete the template. @@ -27,7 +27,7 @@

          Overview


          Directory Structure

          -Squeezebox Server +Logitech Media Server
          • html
            • @@ -57,7 +57,7 @@

              Template Syntax

              Template Dependencies section of this document.

              - Squeezebox Server uses the freely available + Logitech Media Server uses the freely available Template Toolkit version 2.13 for its templates. Full documentation is available at the linked web site. Some of the simpler @@ -149,16 +149,16 @@

              Template Directives

              Template Plugins

              Template Toolkit supports the use of plugins to add functionality. These - are different from Squeezebox Server plugins. There are currently no Squeezebox Server + are different from server plugins. There are currently no server specific plugins implemented. The standard Template Toolkit plugins are available, except for those that require the use of other CPAN modules - that have not already been included with Squeezebox Server. + that have not already been included with server.


              Template Filters

              Template Toolkit makes use of perl functions called filters to perform processing - of text. Squeezebox Server includes all the standard Template Toolkit filters, plus + of text. The server includes all the standard Template Toolkit filters, plus some additional ones described here.

              @@ -276,7 +276,7 @@

              Template Dependencies

              end scratch area -->

              Non-Template Requestable Items

              - Certain requests made to the Squeezebox Server HTTP server are fulfilled outside + Certain requests made to the server HTTP server are fulfilled outside of the template mechanism. Some items are generated dynamically, while others are served up as the file exists on the server. The static item requests are satisfied by following the mechanism of @@ -491,8 +491,8 @@

              Template Functions

              Template Variables

              There are three types of variable available. The first are Template Toolkit - provided, the second are provided to all pages by Squeezebox Server, and the third are - provided to specific pages by Squeezebox Server. + provided, the second are provided to all pages by the server, and the third are + provided to specific pages by Logitech Media Server.

              Template Toolkit variables
              @@ -534,7 +534,7 @@
              Template Toolkit variables
              content
              Used in wrapper templates to refer to the wrapped content
              -
              Squeezebox Server General Variables
              +
              Server General Variables
              Content-Type
              The content type of the requested page, will usually be text/html.
              @@ -558,7 +558,7 @@
              Squeezebox Server General Variables
              Portion of the path used to determine the virtual root. This includes the skin name when a skin other than the "skin" server preference is requested. - Squeezebox Server also allows a pseudo-root of /slimserver/ to be used, which also ends + Logitech Media Server also allows a pseudo-root of /slimserver/ to be used, which also ends up in webroot. When creating absolute URLs webroot should be used as the root rather than simply using "/".
              @@ -629,7 +629,7 @@
              Page Specific Variables
              newVersion
              - Indicates the latest version of Squeezebox Server. Not defined if the + Indicates the latest version of the server. Not defined if the checkVersion server parameter is false.
              nofolder
              @@ -658,7 +658,7 @@
              Page Specific Variables
              forget
              - If this parameter is set in the HTTP request, Squeezebox Server will delete + If this parameter is set in the HTTP request, the server will delete all information about the client refered to by the player parameter.
              diff --git a/HTML/EN/html/docs/xpl.html b/HTML/EN/html/docs/xpl.html index 262cf75f49c..f26fbb99fba 100644 --- a/HTML/EN/html/docs/xpl.html +++ b/HTML/EN/html/docs/xpl.html @@ -1,10 +1,10 @@ -[% pagetitle = 'Squeezebox Server xPL Support' %] +[% pagetitle = 'Logitech Media Server xPL Support' %] [% techinfo = '1' %] [% lefttoright = '1' %] [% PROCESS helpheader.html %]

              Introduction

              -

              The Squeezebox Server software includes native support for the xPL home automation protocol. +

              The Logitech Media Server software includes native support for the xPL home automation protocol. xPL is an open standard, intended to permit the control and monitoring of devices throughout the home. The purpose of xPL is to provide an efficient, unified mechanism for devices to communicate with each other, and with an intelligent house manager. @@ -25,12 +25,12 @@

              xPL Messages

              is recommended reading for anyone who is interested in using the xPL protocol to greatest advantage.

              -

              Enabling xPL Support in Squeezebox Server

              +

              Enabling xPL Support in the server

              To enable xPL support, go to Server Settings -> Additional Server Settings -> Network.
              Scroll to the xPL section, and set xPL support to Enabled.
              -Click Change, then restart your Squeezebox Server software. +Click Change, then restart your server software.

              -

              Once enabled, each player that is connected to Squeezebox Server (including software players) will generate an xPL heartbeat message, +

              Once enabled, each player that is connected to the server (including software players) will generate an xPL heartbeat message, alerting other nodes on the network of it's presence.

              @@ -40,25 +40,25 @@

              Starting an xPL Hub

              including Windows and Linux. See the xPL Project Site for a complete list.

              -

              Controlling Squeezebox Server via xPL

              -

              You can control Squeezebox Server by sending xPL messages, either to all devices, or targetted at a particular player. +

              Controlling the server via xPL

              +

              You can control the server by sending xPL messages, either to all devices, or targetted at a particular player. There are a number of ways of sending an xPL message - see the xPL Project Site for a list of applications that support xPL, and for a variety of command-line tools.

              -

              Squeezebox Server can be controlled using four different types of xPL message.

              +

              The server can be controlled using four different types of xPL message.

              -audio.basic messages can be used to provide basic control of Squeezebox Server. This includes functions common to all audio players, such as play, stop, volume etc.

              +audio.basic messages can be used to provide basic control of the server. This includes functions common to all audio players, such as play, stop, volume etc.

              -audio.slimserv messages are used to harness the more advanced features of Squeezebox Server, performing any of the commands that can be performed +audio.slimserv messages are used to harness the more advanced features of the server, performing any of the commands that can be performed via the command-line interface.

              -remote.basic messages are used to control Squeezebox Server by simulating button presses on a remote control, +remote.basic messages are used to control the server by simulating button presses on a remote control, in a similar way to the "button" command in the command-line interface.

              osd.basic messages are used to display text on a players screen.

              -

              Squeezebox Server Status Messages

              -

              Each player that is connected to Squeezebox Server will send out a heartbeat message as soon as it connects, +

              Logitech Media Server Status Messages

              +

              Each player that is connected to the server will send out a heartbeat message as soon as it connects, and at intervals of between 5 and 30 minutes thereafter. The heartbeat message includes information about the player, such as the player's mode (playing, paused or stopped), the name of the song that is currently playing, and the text that is diff --git a/HTML/EN/html/errors/401.html b/HTML/EN/html/errors/401.html index ac44dfb7225..20b25b24c61 100644 --- a/HTML/EN/html/errors/401.html +++ b/HTML/EN/html/errors/401.html @@ -1,2 +1,2 @@ 401 Authorization Required -401 Authorization is Required to access this Squeezebox Server +401 Authorization is Required to access this Logitech Media Server diff --git a/HTML/EN/html/images/icon_grey.png b/HTML/EN/html/images/icon_grey.png new file mode 100644 index 00000000000..82dd908aaa6 Binary files /dev/null and b/HTML/EN/html/images/icon_grey.png differ diff --git a/HTML/EN/html/images/logitech_media_server.png b/HTML/EN/html/images/logitech_media_server.png new file mode 100644 index 00000000000..27b52d3d535 Binary files /dev/null and b/HTML/EN/html/images/logitech_media_server.png differ diff --git a/HTML/EN/html/mypage.ico b/HTML/EN/html/mypage.ico index 79901425c03..756f52fcc6e 100644 Binary files a/HTML/EN/html/mypage.ico and b/HTML/EN/html/mypage.ico differ diff --git a/HTML/EN/html/progress.js b/HTML/EN/html/progress.js index 049b13485a7..0fba056aabf 100644 --- a/HTML/EN/html/progress.js +++ b/HTML/EN/html/progress.js @@ -4,7 +4,7 @@ function ajaxProgressCallback(theData) { var elems = ['Name', 'Done', 'Total', 'Active', 'Time', 'Bar', 'Info']; - for (var i=0; i <= 10; i++) { + for (var i=0; i <= 50; i++) { // only show the count if it is more than one item if (parsedData['Total'+i] > 1) { diff --git a/HTML/EN/html/softsqueeze/index.html b/HTML/EN/html/softsqueeze/index.html index aa3745667b0..516546538be 100644 --- a/HTML/EN/html/softsqueeze/index.html +++ b/HTML/EN/html/softsqueeze/index.html @@ -9,7 +9,7 @@

              -In Squeezebox Server 7.4 SoftSqueeze has been replaced with +In Squeezebox 7.4 SoftSqueeze has been replaced with SqueezePlay. SoftSqueeze is still being developed and maintained by the Squeezebox community. For more information on SoftSqueeze please visit the diff --git a/HTML/EN/progress.html b/HTML/EN/progress.html index 52e7f914186..42f27d808db 100644 --- a/HTML/EN/progress.html +++ b/HTML/EN/progress.html @@ -45,7 +45,7 @@ [% IF desc && type && !ajaxUpdate %]

              [% type _ "_PROGRESS_DESC" | string %]
               
              [% END %] [% odd = 1 %] - [% FOREACH num = [0..10] %] + [% FOREACH num = [0..50] %] diff --git a/HTML/README.txt b/HTML/README.txt index 48049d86e86..54f41e03e5b 100644 --- a/HTML/README.txt +++ b/HTML/README.txt @@ -1,4 +1,4 @@ -These are HTML 'skins' for Squeezebox Server. +These are HTML 'skins' for Logitech Media Server. They are written using Template Toolkit - http://www.template-toolkit.org/ @@ -6,11 +6,11 @@ They are written using Template Toolkit - http://www.template-toolkit.org/ Classic: Owner: Logitech Inc. - Description: This is the previous Official skin for Squeezebox Server + Description: This is the previous Official skin for Logitech Media Server Default: Owner: Logitech Inc. - Description: This is the Official skin for Squeezebox Server + Description: This is the Official skin for Logitech Media Server EN: Owner: Logitech Inc. diff --git a/Installation.txt b/Installation.txt index feb762c2738..77cdaadbae2 100644 --- a/Installation.txt +++ b/Installation.txt @@ -1,10 +1,8 @@ - Welcome to Squeezebox Server + Welcome to Logitech Media Server -This document describes the steps for installing the Squeezebox Server on Unix-like platforms. +This document describes the steps for installing the Logitech Media Server on Unix-like platforms. -Version 5.8.3 or higher of Perl is required. - -Version 5.8.8 or higher of Perl is STRONGLY RECOMMENDED! +Version 5.10.0 or higher of Perl is required. Additional information can be found on the Wiki at: http://wiki.slimdevices.com/ @@ -22,7 +20,7 @@ build-perl-modules script to run successfully, you must have You must have: - make -- Perl 5.8.3 or greater, and the required development libs (if any; some +- Perl 5.10.0 or greater, and the required development libs (if any; some platforms put this in a separate package, such as 'libperl-dev') - For XML::Parser to build properly - http://expat.sourceforge.net/ @@ -51,20 +49,20 @@ Linux Notes (RPM Install): FreeBSD Notes: In a normal installation of FreeBSD the version of Perl is 5.00 and not - sufficient for use with the Squeezebox Server software, which requires 5.8.3 or greater. + sufficient for use with the Logitech Media Server software, which requires 5.10.0 or greater. - To upgrade Perl to 5.8: + To upgrade Perl to 5.10: First become the superuser, then issue the following commands - # cd /usr/ports/lang/perl5.8 + # cd /usr/ports/lang/perl5.10 # make install clean # rehash # use.perl port The Linux standard installation creates a user, slimserver, that owns all the appropriate files and is the login account for the - Squeezebox Server daemon. There is no requirement that the server daemon + Logitech Media Server daemon. There is no requirement that the server daemon execute with extensive priviledges. As always, executing the perl programs as "root" is not good security practice. @@ -80,10 +78,10 @@ Tarball Notes: This will start up the server and run itself in the background. Visit the URL that's printed out with your web browser to configure your - Squeezebox Server and see the complete documentation. + Logitech Media Server and see the complete documentation. As part of the debugging support, if there is no /etc/slimserver.conf file, or - if it is not readable when the Squeezebox Server starts, it will look for ~.slimserver.conf + if it is not readable when the Logitech Media Server starts, it will look for ~.slimserver.conf that is, the normally hidden file .slimserver.conf in the home directory of the current user. @@ -91,5 +89,5 @@ Tarball Notes: For more verbose messages, start the program with the options of --d_server To refresh the configuration parameters, you can simply delete the /etc/slimserver.conf - file (or rename it to something else). This will cause the Squeezebox Server to + file (or rename it to something else). This will cause the Logitech Media Server to search for the ~.slimserver.conf, and failing that, to recreate it with default values. diff --git a/License.de.txt b/License.de.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.de.txt +++ b/License.de.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/License.es.txt b/License.es.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.es.txt +++ b/License.es.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/License.fr.txt b/License.fr.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.fr.txt +++ b/License.fr.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/License.he.txt b/License.he.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.he.txt +++ b/License.he.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/License.it.txt b/License.it.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.it.txt +++ b/License.it.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/License.nl.txt b/License.nl.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.nl.txt +++ b/License.nl.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/License.txt b/License.txt index a65263d2bf8..f9f0489b66a 100644 --- a/License.txt +++ b/License.txt @@ -12,7 +12,7 @@ case where no particular license is given. Each of the software products we ship are licensed as follows: -- All of Squeezebox Server's perl code is licensed for redistribution +- All of Logitech Media Server's perl code is licensed for redistribution or inclusion in other software per version 2 of the GPL license, included below for your convenience. @@ -22,10 +22,10 @@ included below for your convenience. See Graphics/CODE2000.HTM for more information. - Certain integral components of Slim Server, such as CPAN modules, -are (c) of their respective authors, and are included in Squeezebox Server +are (c) of their respective authors, and are included in Logitech Media Server per their respective licenses. -- Certain ancillary programs included in the Squeezebox Server distribution +- Certain ancillary programs included in the Logitech Media Server distribution on our web site are licensed to us only for direct distribution to end-users. These include the Windows installer and Activestate binaries. diff --git a/MySQL/my-highmem.tt b/MySQL/my-highmem.tt index a0641aa06e2..2b0cac99e1a 100644 --- a/MySQL/my-highmem.tt +++ b/MySQL/my-highmem.tt @@ -1,6 +1,6 @@ # $Id$ # -# Squeezebox Server specific MySQL Server config. +# Logitech Media Server specific MySQL Server config. # High-memory configuration by Moonbase # http://forums.slimdevices.com/showthread.php?t=60682 diff --git a/MySQL/my.tt b/MySQL/my.tt index fd3a94869c9..a32aab58506 100644 --- a/MySQL/my.tt +++ b/MySQL/my.tt @@ -1,6 +1,6 @@ # $Id$ # -# Squeezebox Server specific MySQL Server config. +# Logitech Media Server specific MySQL Server config. [mysqld] innodb diff --git a/SQL/SQLite/schema_13_down.sql b/SQL/SQLite/schema_13_down.sql new file mode 100644 index 00000000000..5717fa43fbe --- /dev/null +++ b/SQL/SQLite/schema_13_down.sql @@ -0,0 +1,4 @@ + +DROP TABLE IF EXISTS videos; + +DROP TABLE IF EXISTS images; diff --git a/SQL/SQLite/schema_13_up.sql b/SQL/SQLite/schema_13_up.sql new file mode 100644 index 00000000000..3a7106734ac --- /dev/null +++ b/SQL/SQLite/schema_13_up.sql @@ -0,0 +1,44 @@ + +DROP TABLE IF EXISTS videos; +CREATE TABLE videos ( + id INTEGER PRIMARY KEY, + hash char(8) NOT NULL, + url text NOT NULL, + title blob, + titlesort text, + titlesearch text, + video_codec varchar(128), + audio_codec varchar(128), + mime_type varchar(32), + dlna_profile varchar(32), + width int(10), + height int(10), + mtime int(10), + added_time int(10), + filesize int(10), + secs float, + bitrate float, + channels tinyint(1) +); +CREATE INDEX videoURLIndex ON videos (url); +CREATE INDEX videoHashIndex ON videos (hash); + +DROP TABLE IF EXISTS images; +CREATE TABLE images ( + id INTEGER PRIMARY KEY, + hash char(8) NOT NULL, + url text NOT NULL, + title blob, + titlesort text, + titlesearch text, + image_codec varchar(128), + mime_type varchar(32), + dlna_profile varchar(32), + width int(10), + height int(10), + mtime int(10), + added_time int(10), + filesize int(10) +); +CREATE INDEX imageURLIndex ON images (url); +CREATE INDEX imageHashIndex ON images (hash); diff --git a/SQL/SQLite/schema_14_down.sql b/SQL/SQLite/schema_14_down.sql new file mode 100644 index 00000000000..e69de29bb2d diff --git a/SQL/SQLite/schema_14_up.sql b/SQL/SQLite/schema_14_up.sql new file mode 100644 index 00000000000..559253cfb9a --- /dev/null +++ b/SQL/SQLite/schema_14_up.sql @@ -0,0 +1,8 @@ + +ALTER TABLE tracks ADD added_time int(10) default NULL; + +ALTER TABLE tracks ADD updated_time int(10) default NULL; + +ALTER TABLE images ADD updated_time int(10) default NULL; + +ALTER TABLE videos ADD updated_time int(10) default NULL; diff --git a/SQL/SQLite/schema_15_down.sql b/SQL/SQLite/schema_15_down.sql new file mode 100644 index 00000000000..e69de29bb2d diff --git a/SQL/SQLite/schema_15_up.sql b/SQL/SQLite/schema_15_up.sql new file mode 100644 index 00000000000..610d61cdde6 --- /dev/null +++ b/SQL/SQLite/schema_15_up.sql @@ -0,0 +1,10 @@ + +-- to be set to EXIF DateTimeOriginal or similar +ALTER TABLE images ADD original_time int(10) NOT NULL DEFAULT 0; +CREATE INDEX imageDateTimeOriginal ON images (original_time); + +ALTER TABLE images ADD orientation int(10) NOT NULL DEFAULT 0; + +ALTER TABLE images ADD album blob default NULL; + +ALTER TABLE videos ADD album blob default NULL; diff --git a/SQL/SQLite/schema_clear.sql b/SQL/SQLite/schema_clear.sql index d2b017c7810..1a1d8543759 100644 --- a/SQL/SQLite/schema_clear.sql +++ b/SQL/SQLite/schema_clear.sql @@ -26,4 +26,8 @@ DELETE FROM unreadable_tracks; DELETE FROM scanned_files; +DELETE FROM videos; + +DELETE FROM images; + UPDATE metainformation SET value = 0 WHERE name = 'lastRescanTime'; diff --git a/Slim/Buttons/Alarm.pm b/Slim/Buttons/Alarm.pm index 63d75ea04a2..c7ab86f03b0 100644 --- a/Slim/Buttons/Alarm.pm +++ b/Slim/Buttons/Alarm.pm @@ -4,7 +4,7 @@ use strict; # Max Spicer, May 2008 # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Buttons/Block.pm b/Slim/Buttons/Block.pm index f0246f17951..f187c7857bb 100644 --- a/Slim/Buttons/Block.pm +++ b/Slim/Buttons/Block.pm @@ -1,6 +1,6 @@ package Slim::Buttons::Block; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Buttons/BrowseUPnPMediaServer.pm b/Slim/Buttons/BrowseUPnPMediaServer.pm index 1e3136e26e8..921c0641aba 100644 --- a/Slim/Buttons/BrowseUPnPMediaServer.pm +++ b/Slim/Buttons/BrowseUPnPMediaServer.pm @@ -1,6 +1,6 @@ package Slim::Buttons::BrowseUPnPMediaServer; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -11,7 +11,7 @@ Slim::Buttons::BrowseUPnPMediaServer =head1 DESCRIPTION -L is a Squeezebox Server module for +L is a Logitech Media Server module for browsing services provided by UPnP servers =cut diff --git a/Slim/Buttons/Common.pm b/Slim/Buttons/Common.pm index 8c8b93f5e2c..af14720ace1 100644 --- a/Slim/Buttons/Common.pm +++ b/Slim/Buttons/Common.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Common; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -106,7 +106,7 @@ my $prefs = preferences('server'); =head2 init( ) This method must be called before all other Slim::Buttons::* modules. It -initialises all other Squeezebox Server core button modules and registers the "Now +initialises all other Logitech Media Server core button modules and registers the "Now Playing" screensaver. =cut diff --git a/Slim/Buttons/GlobalSearch.pm b/Slim/Buttons/GlobalSearch.pm index 5d6f8d71edc..e5eead33773 100644 --- a/Slim/Buttons/GlobalSearch.pm +++ b/Slim/Buttons/GlobalSearch.pm @@ -27,7 +27,7 @@ Slim::Buttons::GlobalSearch =head1 DESCRIPTION -L is a Squeezebox Server module to easily +L is a Logitech Media Server module to easily search content in any search provider available to the server =cut diff --git a/Slim/Buttons/Home.pm b/Slim/Buttons/Home.pm index b5838a7b027..50f91fc4b15 100644 --- a/Slim/Buttons/Home.pm +++ b/Slim/Buttons/Home.pm @@ -1,6 +1,6 @@ package Slim::Buttons::Home; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -22,7 +22,7 @@ Slim::Buttons::Home =head1 DESCRIPTION -L is a Squeezebox Server module for creating and +L is a Logitech Media Server module for creating and navigating a configurable multilevel menu structure. =cut @@ -769,7 +769,7 @@ sub menuOptions { MENU: for my $menuOption (sort keys %home) { - if ($menuOption eq 'BROWSE_MUSIC_FOLDER' && !Slim::Utils::Misc::getAudioDir()) { + if ($menuOption eq 'BROWSE_MUSIC_FOLDER' && !scalar @{ Slim::Utils::Misc::getAudioDirs() }) { next; } diff --git a/Slim/Buttons/Information.pm b/Slim/Buttons/Information.pm index 910a4a197cb..5ef551e2b95 100644 --- a/Slim/Buttons/Information.pm +++ b/Slim/Buttons/Information.pm @@ -28,10 +28,10 @@ Slim::Buttons::Information =head1 DESCRIPTION -L is a Squeezebox Server module to display player library +L is a Logitech Media Server module to display player library and module information. -Displays various bits of information relating to the Squeezebox Server, +Displays various bits of information relating to the Logitech Media Server, the current player, the music library and the installed plug-in modules. diff --git a/Slim/Buttons/Input/Bar.pm b/Slim/Buttons/Input/Bar.pm index 28a05a152b8..f7fb3593e43 100644 --- a/Slim/Buttons/Input/Bar.pm +++ b/Slim/Buttons/Input/Bar.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Input::Bar; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -19,7 +19,7 @@ Slim::Buttons::Common::pushMode($client, 'INPUT.Bar', $params); =head1 DESCRIPTION -L is a Squeezebox Server module for creating and +L is a Logitech Media Server module for creating and navigating a configurable multilevel menu structure. Avilable Parameters and their defaults: diff --git a/Slim/Buttons/Input/Choice.pm b/Slim/Buttons/Input/Choice.pm index df31dbf04f0..49f08b2512f 100644 --- a/Slim/Buttons/Input/Choice.pm +++ b/Slim/Buttons/Input/Choice.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Input::Choice; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Buttons/Input/List.pm b/Slim/Buttons/Input/List.pm index d5706ff690f..6402ff7c978 100644 --- a/Slim/Buttons/Input/List.pm +++ b/Slim/Buttons/Input/List.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Input::List; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -38,7 +38,7 @@ Slim::Buttons::Input::List =head1 DESCRIPTION -L is a reusable Squeezebox Server module, creating a +L is a reusable Logitech Media Server module, creating a generic framework UI for navigating through a List of items, with configurable display parameters and entry/leave points. diff --git a/Slim/Buttons/Input/Text.pm b/Slim/Buttons/Input/Text.pm index fab1f6dd1db..684d9355913 100644 --- a/Slim/Buttons/Input/Text.pm +++ b/Slim/Buttons/Input/Text.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Input::Text; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -25,7 +25,7 @@ Slim::Buttons::Common::pushModeLeft($client, 'INPUT.Text', \%params); =head1 DESCRIPTION -L is a reusable Squeezebox Server module for creating a standard UI +L is a reusable Logitech Media Server module for creating a standard UI for inputting Text. Client parameters may determine the character sets available, and set any actions done on the resulting text. Callers include Slim::Buttons::Search. diff --git a/Slim/Buttons/Input/Time.pm b/Slim/Buttons/Input/Time.pm index 9b99aa93e01..3ac77d54562 100644 --- a/Slim/Buttons/Input/Time.pm +++ b/Slim/Buttons/Input/Time.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Input::Time; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -31,7 +31,7 @@ Slim::Buttons::Common::pushMode($client, 'INPUT.Time', \%params); =head1 DESCRIPTION -L is a reusable Squeezebox Server module to create a standard UI +L is a reusable Logitech Media Server module to create a standard UI for entering Time formatted strings. This is a slimmed down variation of Input::Text with custom handling for limiting characters based on the timeFormat server preference and typical formatting of time strings. Callers include Slim::Buttons::AlarmCLock diff --git a/Slim/Buttons/Playlist.pm b/Slim/Buttons/Playlist.pm index 659a092d6f4..bf2ced2ffb9 100644 --- a/Slim/Buttons/Playlist.pm +++ b/Slim/Buttons/Playlist.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Playlist; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -41,7 +41,7 @@ my %playlistParams = (); =head2 init( ) -This method registers the playlist mode with Squeezebox Server, and defines any functions for interaction +This method registers the playlist mode with Logitech Media Server, and defines any functions for interaction while a player is operating in this mode.. Generally only called from L @@ -312,7 +312,7 @@ sub getFunctions { =head2 setMode( $client, [ $how ]) -setMode() is a required function for any Squeezebox Server player mode. This is the entry point for a mode and defines any parameters required for +setMode() is a required function for any Logitech Media Server player mode. This is the entry point for a mode and defines any parameters required for a clean starting point. The function may also set up the reference to the applicable lines function for the player display. Requires: $client diff --git a/Slim/Buttons/Power.pm b/Slim/Buttons/Power.pm index 48f51545556..c37a7153971 100644 --- a/Slim/Buttons/Power.pm +++ b/Slim/Buttons/Power.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Power; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -13,7 +13,7 @@ Slim::Buttons::Power =head1 DESCRIPTION -L is a Squeezebox Server module to add an 'off' mode. +L is a Logitech Media Server module to add an 'off' mode. The players are never truly off, instead entering and leaving this mode in reaction to the power button. diff --git a/Slim/Buttons/RemoteTrackInfo.pm b/Slim/Buttons/RemoteTrackInfo.pm index 122215c05b8..c2d7ff41462 100644 --- a/Slim/Buttons/RemoteTrackInfo.pm +++ b/Slim/Buttons/RemoteTrackInfo.pm @@ -2,7 +2,7 @@ package Slim::Buttons::RemoteTrackInfo; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -13,7 +13,7 @@ Slim::Buttons::RemoteTrackInfo =head1 DESCRIPTION -L is a Squeezebox Server module to create a UI for viewing information +L is a Logitech Media Server module to create a UI for viewing information about remote tracks. =cut diff --git a/Slim/Buttons/ScreenSaver.pm b/Slim/Buttons/ScreenSaver.pm index 177667df2f1..67772794cfe 100644 --- a/Slim/Buttons/ScreenSaver.pm +++ b/Slim/Buttons/ScreenSaver.pm @@ -2,7 +2,7 @@ package Slim::Buttons::ScreenSaver; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Buttons/Search.pm b/Slim/Buttons/Search.pm index 49ddb39c99a..58066b972db 100644 --- a/Slim/Buttons/Search.pm +++ b/Slim/Buttons/Search.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Search; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -13,7 +13,7 @@ Slim::Buttons::Search =head1 DESCRIPTION -L is a Squeezebox Server module to create a UI for searching +L is a Logitech Media Server module to create a UI for searching the user track database. Seach by ARTIST, ALBUM and SONGS is added to the home menu structure as well as options for adding to the top level. Search input uses the INPUT.Text mode. diff --git a/Slim/Buttons/Settings.pm b/Slim/Buttons/Settings.pm index 57f830cb8d9..aba4f8d1422 100644 --- a/Slim/Buttons/Settings.pm +++ b/Slim/Buttons/Settings.pm @@ -1,6 +1,6 @@ package Slim::Buttons::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Buttons/SqueezeNetwork.pm b/Slim/Buttons/SqueezeNetwork.pm index 1dcb40701b9..78ab8587fe7 100644 --- a/Slim/Buttons/SqueezeNetwork.pm +++ b/Slim/Buttons/SqueezeNetwork.pm @@ -2,7 +2,7 @@ package Slim::Buttons::SqueezeNetwork; # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2006-2009 Logitech. +# Logitech Media Server Copyright 2006-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -14,7 +14,7 @@ Slim::Buttons::SqueezeNetwork =head1 DESCRIPTION L is simple module to offer a UI -for breaking a player's connection with Squeezebox Server in order to reconnect +for breaking a player's connection with Logitech Media Server in order to reconnect to mysqueezebox.com. =cut diff --git a/Slim/Buttons/Synchronize.pm b/Slim/Buttons/Synchronize.pm index 38cbeaef419..1081ff45e5a 100644 --- a/Slim/Buttons/Synchronize.pm +++ b/Slim/Buttons/Synchronize.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Synchronize; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -13,7 +13,7 @@ Slim::Buttons::Synchronize =head1 DESCRIPTION -L is the Squeezebox Server module to handle a player UI +L is the Logitech Media Server module to handle a player UI for synchronizing groups of players, and reporting the current status of sync groups =cut diff --git a/Slim/Buttons/TrackInfo.pm b/Slim/Buttons/TrackInfo.pm index 843accf3e2a..9e0b5ec44dd 100644 --- a/Slim/Buttons/TrackInfo.pm +++ b/Slim/Buttons/TrackInfo.pm @@ -1,6 +1,6 @@ package Slim::Buttons::TrackInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Buttons/Volume.pm b/Slim/Buttons/Volume.pm index c46305d6b5a..7d1d7cd4475 100644 --- a/Slim/Buttons/Volume.pm +++ b/Slim/Buttons/Volume.pm @@ -2,7 +2,7 @@ package Slim::Buttons::Volume; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Control/Commands.pm b/Slim/Control/Commands.pm index 491789e4372..f8c1d94b0b2 100644 --- a/Slim/Control/Commands.pm +++ b/Slim/Control/Commands.pm @@ -2,7 +2,7 @@ package Slim::Control::Commands; # $Id: Commands.pm 5121 2005-11-09 17:07:36Z dsully $ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -20,7 +20,7 @@ Slim::Control::Commands =head1 DESCRIPTION -Implements most Squeezebox Server commands and is designed to be exclusively called +Implements most Logitech Media Server commands and is designed to be exclusively called through Request.pm and the mechanisms it defines. =cut @@ -37,6 +37,8 @@ use Slim::Utils::Alarm; use Slim::Utils::Log; use Slim::Utils::Misc; use Slim::Utils::Scanner; +use Slim::Utils::Scanner::Local; +use Slim::Utils::Scanner::LMS; use Slim::Utils::Prefs; use Slim::Utils::OSDetect; @@ -272,7 +274,7 @@ sub clientConnectCommand { $host = 2; } elsif ( $host eq '0' ) { - # Squeezebox Server (used on SN) + # Logitech Media Server (used on SN) } else { $host = Slim::Utils::Network::intip($host); @@ -2488,29 +2490,45 @@ sub rescanCommand { # get our parameters my $playlistsOnly = $request->getParam('_playlists') || 0; - # if we're scanning allready, don't do it twice - if (!Slim::Music::Import->stillScanning()) { + my @dirs = @{ Slim::Utils::Misc::getMediaDirs() }; + # if we're scanning already, don't do it twice + if (!Slim::Music::Import->stillScanning() && scalar @dirs) { if ( $prefs->get('autorescan') ) { Slim::Utils::AutoRescan->shutdown; } - my $dir = Slim::Utils::Misc::getAudioDir(); - - my %args = ( - types => 'list|audio', - scanName => 'directory', - progress => 1, - ); - - if ($playlistsOnly) { - $dir = Slim::Utils::Misc::getPlaylistDir(); - $args{types} = 'list'; - } - Slim::Utils::Progress->clear(); - Slim::Utils::Scanner::Local->rescan( $dir, \%args ); + # we only want to scan folders for video/pictures + @dirs = keys %{{ map { $_, 1 } @{ Slim::Utils::Misc::getVideoDirs() }, @{ Slim::Utils::Misc::getImageDirs() } }}; + + # XXX - we need a better way to handle the async mode, eg. passing the exception list together with the folder list to Media::Scan + my $s; + $s = sub { + Slim::Utils::Scanner::LMS->rescan( shift @dirs, { + scanName => 'directory', + progress => 1, + onFinished => sub { + if (scalar @dirs) { + # XXX - delay call to self for a second, or we segfault + Slim::Utils::Timers::setTimer(undef, time() + 1, $s); + } + + else { + my $audiodirs = Slim::Utils::Misc::getAudioDirs(); + # XXX until libmediascan supports audio, run the audio scanner now + Slim::Utils::Scanner::Local->rescan( $audiodirs, { + types => 'list|audio', + scanName => 'directory', + progress => 1, + } ); + } + } + } ); + }; + + $s->(); } $request->setStatusDone(); @@ -2874,7 +2892,9 @@ sub wipecacheCommand { if ( Slim::Utils::OSDetect::isSqueezeOS() ) { # Wipe/rescan in-process on SqueezeOS - my $dir = Slim::Utils::Misc::getAudioDir(); + + # XXX - for the time being we're going to assume that the embedded server will only handle one folder + my $dir = Slim::Utils::Misc::getAudioDirs()->[0]; my %args = ( types => 'list|audio', diff --git a/Slim/Control/Jive.pm b/Slim/Control/Jive.pm index 86b3e538865..e1058ba08c1 100644 --- a/Slim/Control/Jive.pm +++ b/Slim/Control/Jive.pm @@ -1,6 +1,6 @@ package Slim::Control::Jive; -# Squeezebox Server Copyright 2001-2009 Logitech +# Logitech Media Server Copyright 2001-2011 Logitech # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Control/Queries.pm b/Slim/Control/Queries.pm index bb4ae07aafd..b84efee0b70 100644 --- a/Slim/Control/Queries.pm +++ b/Slim/Control/Queries.pm @@ -2,7 +2,7 @@ package Slim::Control::Queries; # $Id: $ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -20,7 +20,7 @@ Slim::Control::Queries =head1 DESCRIPTION -L implements most Squeezebox Server queries and is designed to +L implements most Logitech Media Server queries and is designed to be exclusively called through Request.pm and the mechanisms it defines. Except for subscribe-able queries (such as status and serverstatus), there are no @@ -1546,14 +1546,17 @@ sub modeQuery { $request->setStatusDone(); } - sub musicfolderQuery { + mediafolderQuery(@_); +} + +sub mediafolderQuery { my $request = shift; - main::INFOLOG && $log->info("musicfolderQuery()"); + main::INFOLOG && $log->info("mediafolderQuery()"); # check this is the correct query. - if ($request->isNotQuery([['musicfolder']])) { + if ($request->isNotQuery([['mediafolder']]) && $request->isNotQuery([['musicfolder']])) { $request->setStatusBadDispatch(); return; } @@ -1564,47 +1567,74 @@ sub musicfolderQuery { my $folderId = $request->getParam('folder_id'); my $want_top = $request->getParam('return_top'); my $url = $request->getParam('url'); + my $type = $request->getParam('type') || ''; my $tags = $request->getParam('tags') || ''; + my $sql; + # url overrides any folderId my $params = (); + my $mediaDirs = Slim::Utils::Misc::getMediaDirs($type || 'audio'); - if (defined $url) { - $params->{'url'} = $url; - } else { - # findAndScanDirectory sorts it out if $folderId is undef - $params->{'id'} = $folderId; - } - - # Pull the directory list, which will be used for looping. - my ($topLevelObj, $items, $count); - - # if this is a follow up query ($index > 0), try to read from the cache - if (my $cachedItem = $bmfCache{ $params->{url} || $params->{id} || 0 }) { - $items = $cachedItem->{items}; - $topLevelObj = $cachedItem->{topLevelObj}; - $count = $cachedItem->{count}; - } - else { - ($topLevelObj, $items, $count) = Slim::Utils::Misc::findAndScanDirectoryTree($params); + my ($topLevelObj, $items, $count, $topPath); + + if ( !defined $url && !defined $folderId && scalar(@$mediaDirs) > 1) { - # cache results in case the same folder is queried again shortly - # should speed up Jive BMF, as only the first chunk needs to run the full loop above - $bmfCache{ $params->{url} || $params->{id} || 0 } = { - items => $items, - topLevelObj => $topLevelObj, - count => $count, - }; - } + $items = $mediaDirs; + $count = scalar(@$items); + $topPath = ''; - if ($want_top) { - $items = [ $topLevelObj->url ]; - $count = 1; } - # create filtered data + else { + if (defined $url) { + $params->{'url'} = $url; + } + elsif ($folderId) { + $params->{'id'} = $folderId; + } + elsif (scalar @$mediaDirs) { + $params->{'url'} = $mediaDirs->[0]; + } + + if ($type) { + $params->{typeRegEx} = Slim::Music::Info::validTypeExtensions($type); + + # if we need the artwork, we'll have to look them up in their own tables for videos/images + if ($tags && $type eq 'image') { + $sql = 'SELECT * FROM images WHERE url = ?'; + } + elsif ($tags && $type eq 'video') { + $sql = 'SELECT * FROM videos WHERE url = ?'; + } + } - my $topPath = $topLevelObj->path; + # if this is a follow up query ($index > 0), try to read from the cache + if (my $cachedItem = $bmfCache{ $params->{url} || $params->{id} || 0 }) { + $items = $cachedItem->{items}; + $topLevelObj = $cachedItem->{topLevelObj}; + $count = $cachedItem->{count}; + } + else { + ($topLevelObj, $items, $count) = Slim::Utils::Misc::findAndScanDirectoryTree($params); + + # cache results in case the same folder is queried again shortly + # should speed up Jive BMF, as only the first chunk needs to run the full loop above + $bmfCache{ $params->{url} || $params->{id} || 0 } = { + items => $items, + topLevelObj => $topLevelObj, + count => $count, + }; + } + + if ($want_top) { + $items = [ $topLevelObj->url ]; + $count = 1; + } + + # create filtered data + $topPath = $topLevelObj->path if blessed($topLevelObj); + } # now build the result if (Slim::Music::Import->stillScanning()) { @@ -1618,6 +1648,8 @@ sub musicfolderQuery { my $loopname = 'folder_loop'; my $chunkCount = 0; + my $sth = $sql ? Slim::Schema->dbh->prepare_cached($sql) : undef; + for my $filename (@$items[$start..$end]) { my $url = Slim::Utils::Misc::fixPath($filename, $topPath) || next; @@ -1643,12 +1675,17 @@ sub musicfolderQuery { 'readTags' => 1, }); - if (!blessed($item) || !$item->can('content_type')) { - + my $id; + + if ( (!blessed($item) || !$item->can('content_type')) + && (!$params->{typeRegEx} || $filename !~ $params->{typeRegEx}) ) + { next; } + elsif (blessed($item)) { + $id = $item->id(); + } - my $id = $item->id(); $id += 0; $realName ||= Slim::Music::Info::fileName($url); @@ -1662,7 +1699,36 @@ sub musicfolderQuery { $request->addResultLoop($loopname, $chunkCount, 'type', 'folder'); } elsif (Slim::Music::Info::isPlaylist($item)) { $request->addResultLoop($loopname, $chunkCount, 'type', 'playlist'); - } elsif (Slim::Music::Info::isSong($item)) { + } elsif ($params->{typeRegEx} && $filename =~ $params->{typeRegEx}) { + $request->addResultLoop($loopname, $chunkCount, 'type', $type); + + # only do this for images & videos where we'll need the hash for the artwork + if ($sth) { + $sth->execute($url); + + my $itemDetails = $sth->fetchrow_hashref; + + if ($type eq 'video') { + while ( my ($k, $v) = each(%$itemDetails) ) { + $itemDetails->{"videos.$k"} = $v if $k !~ /^videos\./; + } + + _videoData($request, $loopname, $chunkCount, $tags, $itemDetails); + } + + elsif ($type eq 'image') { + utf8::decode( $itemDetails->{'images.title'} ) if exists $itemDetails->{'images.title'}; + utf8::decode( $itemDetails->{'images.album'} ) if exists $itemDetails->{'images.album'}; + + while ( my ($k, $v) = each(%$itemDetails) ) { + $itemDetails->{"images.$k"} = $v if $k !~ /^images\./; + } + _imageData($request, $loopname, $chunkCount, $tags, $itemDetails); + } + + } + + } elsif (Slim::Music::Info::isSong($item) && $type ne 'video') { $request->addResultLoop($loopname, $chunkCount, 'type', 'track'); } elsif (-d Slim::Utils::Misc::pathFromMacAlias($url)) { $request->addResultLoop($loopname, $chunkCount, 'type', 'folder'); @@ -1672,15 +1738,18 @@ sub musicfolderQuery { $tags =~ /s/ && $request->addResultLoop($loopname, $chunkCount, 'textkey', $textKey); $tags =~ /u/ && $request->addResultLoop($loopname, $chunkCount, 'url', $url); + $tags =~ /t/ && $request->addResultLoop($loopname, $chunkCount, 'title', $realName); $chunkCount++; } + + $sth->finish() if $sth; } $request->addResult('count', $count); # we might have changed - flush to the db to be in sync. - $topLevelObj->update; + $topLevelObj->update if blessed($topLevelObj); $request->setStatusDone(); } @@ -2352,10 +2421,16 @@ sub rescanprogressQuery { for my $p (@progress) { + my $name = $p->name; + if ($name =~ /(.*)\|(.*)/) { + $request->addResult('fullname', $request->string($2 . '_PROGRESS') . $request->string('COLON') . ' ' . $1); + $name = $2; + } + my $percComplete = $p->finish ? 100 : $p->total ? $p->done / $p->total * 100 : -1; - $request->addResult($p->name(), int($percComplete)); + $request->addResult($name, int($percComplete)); - push @steps, $p->name(); + push @steps, $name; $total_time += ($p->finish || time()) - $p->start; @@ -2534,8 +2609,12 @@ sub serverstatusQuery { if (Slim::Music::Import->stillScanning()) { $request->addResult('rescan', "1"); if (my $p = Slim::Schema->rs('Progress')->search({ 'type' => 'importer', 'active' => 1 })->first) { + + # remove leading path information from the progress name + my $name = $p->name; + $name =~ s/(.*)\|//; - $request->addResult('progressname', $request->string($p->name."_PROGRESS")); + $request->addResult('progressname', $request->string($name . '_PROGRESS')); $request->addResult('progressdone', $p->done); $request->addResult('progresstotal', $p->total); } @@ -4020,6 +4099,8 @@ my %tagMap = ( 'l' => ['album', 'ALBUM', 'albumname'], #->album.title 't' => ['tracknum', 'TRACK', 'tracknum'], #tracknum 'n' => ['modificationTime', 'MODTIME', 'modificationTime'], #timestamp + 'D' => ['addedTime', 'ADDTIME', 'addedTime'], #added_time + 'U' => ['lastUpdated', 'UPDTIME', 'lastUpdated'], #updated_time 'f' => ['filesize', 'FILELENGTH', 'filesize'], #filesize #tag 'i' => ['disc', 'DISC', 'disc'], #disc @@ -4101,7 +4182,9 @@ my %colMap = ( f => 'tracks.filesize', j => sub { $_[0]->{'tracks.cover'} ? 1 : 0 }, J => 'albums.artwork', - n => sub { Slim::Schema::Track->buildModificationTime( $_[0]->{'tracks.timestamp'} ) }, + n => 'tracks.timestamp', + D => 'tracks.added_time', + U => 'tracks.updated_time', C => sub { $_[0]->{'albums.compilation'} ? 1 : 0 }, Y => 'tracks.replay_gain', X => 'albums.replay_gain', @@ -4826,6 +4909,8 @@ sub _getTagDataForTracks { $tags =~ /f/ && do { $c->{'tracks.filesize'} = 1 }; $tags =~ /j/ && do { $c->{'tracks.cover'} = 1 }; $tags =~ /n/ && do { $c->{'tracks.timestamp'} = 1 }; + $tags =~ /D/ && do { $c->{'tracks.added_time'} = 1 }; + $tags =~ /U/ && do { $c->{'tracks.updated_time'} = 1 }; $tags =~ /T/ && do { $c->{'tracks.samplerate'} = 1 }; $tags =~ /I/ && do { $c->{'tracks.samplesize'} = 1 }; $tags =~ /u/ && do { $c->{'tracks.url'} = 1 }; @@ -4833,8 +4918,7 @@ sub _getTagDataForTracks { $tags =~ /x/ && do { $c->{'tracks.remote'} = 1 }; $tags =~ /c/ && do { $c->{'tracks.coverid'} = 1 }; $tags =~ /Y/ && do { $c->{'tracks.replay_gain'} = 1 }; - $tags =~ /i/ && do { $c->{'tracks.disc'} = 1 }; - + $tags =~ /i/ && do { $c->{'tracks.disc'} = 1 }; $tags =~ /g/ && do { $join_genres->(); $c->{'genres.name'} = 1; @@ -5104,6 +5188,459 @@ sub _getTagDataForTracks { return wantarray ? ( \%results, \@resultOrder, $total ) : \%results; } +### Video support + +# XXX needs to be more like titlesQuery, was originally copied from albumsQuery +sub videoTitlesQuery { + my $request = shift; + + if (!Slim::Schema::hasLibrary()) { + $request->setStatusNotDispatchable(); + return; + } + + my $sqllog = main::DEBUGLOG && logger('database.sql'); + + # get our parameters + my $index = $request->getParam('_index'); + my $quantity = $request->getParam('_quantity'); + my $tags = $request->getParam('tags') || 't'; + my $search = $request->getParam('search'); + my $sort = $request->getParam('sort'); + my $videoHash = $request->getParam('video_id'); + + #if ($sort && $request->paramNotOneOfIfDefined($sort, ['new'])) { + # $request->setStatusBadParams(); + # return; + #} + + my $collate = Slim::Utils::OSDetect->getOS()->sqlHelperClass()->collate(); + + my $sql = 'SELECT %s FROM videos '; + my $c = { 'videos.hash' => 1, 'videos.titlesearch' => 1, 'videos.titlesort' => 1 }; + my $w = []; + my $p = []; + my $order_by = "videos.titlesort $collate"; + my $limit; + + # Normalize and add any search parameters + if ( defined $videoHash ) { + push @{$w}, 'videos.hash = ?'; + push @{$p}, $videoHash; + } + # ignore everything if $videoID was specified + else { + if ($sort) { + if ( $sort eq 'new' ) { + $limit = $prefs->get('browseagelimit') || 100; + $order_by = "videos.added_time desc"; + + # Force quantity to not exceed max + if ( $quantity && $quantity > $limit ) { + $quantity = $limit; + } + } + elsif ( $sort =~ /^sql=(.+)/ ) { + $order_by = $1; + $order_by =~ s/;//g; # strip out any attempt at combining SQL statements + } + } + + if ( $search && specified($search) ) { + if ( $search =~ s/^sql=// ) { + # Raw SQL search query + $search =~ s/;//g; # strip out any attempt at combining SQL statements + push @{$w}, $search; + } + else { + my $strings = Slim::Utils::Text::searchStringSplit($search); + if ( ref $strings->[0] eq 'ARRAY' ) { + push @{$w}, '(' . join( ' OR ', map { 'videos.titlesearch LIKE ?' } @{ $strings->[0] } ) . ')'; + push @{$p}, @{ $strings->[0] }; + } + else { + push @{$w}, 'videos.titlesearch LIKE ?'; + push @{$p}, @{$strings}; + } + } + } + } + + $tags =~ /t/ && do { $c->{'videos.title'} = 1 }; + $tags =~ /d/ && do { $c->{'videos.secs'} = 1 }; + $tags =~ /o/ && do { $c->{'videos.mime_type'} = 1 }; + $tags =~ /r/ && do { $c->{'videos.bitrate'} = 1 }; + $tags =~ /f/ && do { $c->{'videos.filesize'} = 1 }; + $tags =~ /w/ && do { $c->{'videos.width'} = 1 }; + $tags =~ /h/ && do { $c->{'videos.height'} = 1 }; + $tags =~ /n/ && do { $c->{'videos.mtime'} = 1 }; + $tags =~ /D/ && do { $c->{'videos.added_time'} = 1 }; + $tags =~ /U/ && do { $c->{'videos.updated_time'} = 1 }; + $tags =~ /l/ && do { $c->{'videos.album'} = 1 }; + + if ( @{$w} ) { + $sql .= 'WHERE '; + $sql .= join( ' AND ', @{$w} ); + $sql .= ' '; + } + $sql .= "GROUP BY videos.hash ORDER BY $order_by "; + + # Add selected columns + # Bug 15997, AS mapping needed for MySQL + my @cols = keys %{$c}; + $sql = sprintf $sql, join( ', ', map { $_ . " AS '" . $_ . "'" } @cols ); + + my $stillScanning = Slim::Music::Import->stillScanning(); + + my $dbh = Slim::Schema->dbh; + + # Get count of all results, the count is cached until the next rescan done event + my $cacheKey = $sql . join( '', @{$p} ); + + my ($count) = $cache->{$cacheKey} || $dbh->selectrow_array( qq{ + SELECT COUNT(*) FROM ( $sql ) AS t1 + }, undef, @{$p} ); + + if ( !$stillScanning ) { + $cache->{$cacheKey} = $count; + } + + if ($stillScanning) { + $request->addResult('rescan', 1); + } + + $count += 0; + + my $totalCount = $count; + + # now build the result + my ($valid, $start, $end) = $request->normalize(scalar($index), scalar($quantity), $count); + + my $loopname = 'videos_loop'; + my $chunkCount = 0; + + if ($valid) { + # Limit the real query + if ( $index =~ /^\d+$/ && $quantity =~ /^\d+$/ ) { + $sql .= "LIMIT $index, $quantity "; + } + + if ( main::DEBUGLOG && $sqllog->is_debug ) { + $sqllog->debug( "Video Titles query: $sql / " . Data::Dump::dump($p) ); + } + + my $sth = $dbh->prepare_cached($sql); + $sth->execute( @{$p} ); + + # Bind selected columns in order + my $i = 1; + for my $col ( @cols ) { + $sth->bind_col( $i++, \$c->{$col} ); + } + + while ( $sth->fetch ) { + if ( $sort ne 'new' ) { + utf8::decode( $c->{'videos.titlesort'} ) if exists $c->{'videos.titlesort'}; + } + + # "raw" result formatting (for CLI or JSON RPC) + $request->addResultLoop($loopname, $chunkCount, 'id', $c->{'videos.hash'}); + + _videoData($request, $loopname, $chunkCount, $tags, $c); + + $chunkCount++; + + main::idleStreams() if !($chunkCount % 5); + } + } + + $request->addResult('count', $totalCount); + + $request->setStatusDone(); +} + +sub _videoData { + my ($request, $loopname, $chunkCount, $tags, $c) = @_; + + utf8::decode( $c->{'videos.title'} ) if exists $c->{'videos.title'}; + utf8::decode( $c->{'videos.album'} ) if exists $c->{'videos.album'}; + + $tags =~ /t/ && $request->addResultLoop($loopname, $chunkCount, 'title', $c->{'videos.title'}); + $tags =~ /d/ && $request->addResultLoop($loopname, $chunkCount, 'duration', $c->{'videos.secs'}); + $tags =~ /o/ && $request->addResultLoop($loopname, $chunkCount, 'mime_type', $c->{'videos.mime_type'}); + $tags =~ /r/ && $request->addResultLoop($loopname, $chunkCount, 'bitrate', $c->{'videos.bitrate'} / 1000); + $tags =~ /f/ && $request->addResultLoop($loopname, $chunkCount, 'filesize', $c->{'videos.filesize'}); + $tags =~ /w/ && $request->addResultLoop($loopname, $chunkCount, 'width', $c->{'videos.width'}); + $tags =~ /h/ && $request->addResultLoop($loopname, $chunkCount, 'height', $c->{'videos.height'}); + $tags =~ /n/ && $request->addResultLoop($loopname, $chunkCount, 'mtime', $c->{'videos.mtime'}); + $tags =~ /D/ && $request->addResultLoop($loopname, $chunkCount, 'added_time', $c->{'videos.added_time'}); + $tags =~ /U/ && $request->addResultLoop($loopname, $chunkCount, 'updated_time', $c->{'videos.updated_time'}); + $tags =~ /l/ && $request->addResultLoop($loopname, $chunkCount, 'album', $c->{'videos.album'}); + $tags =~ /J/ && $request->addResultLoop($loopname, $chunkCount, 'hash', $c->{'videos.hash'}); +} + +# XXX needs to be more like titlesQuery, was originally copied from albumsQuery +sub imageTitlesQuery { + my $request = shift; + + if (!Slim::Schema::hasLibrary()) { + $request->setStatusNotDispatchable(); + return; + } + + my $sqllog = main::DEBUGLOG && logger('database.sql'); + + # get our parameters + my $index = $request->getParam('_index'); + my $quantity = $request->getParam('_quantity'); + my $tags = $request->getParam('tags') || 't'; + my $search = $request->getParam('search'); + my $timeline = $request->getParam('timeline'); + my $albums = $request->getParam('albums'); + my $sort = $request->getParam('sort'); + my $imageHash = $request->getParam('image_id'); + + #if ($sort && $request->paramNotOneOfIfDefined($sort, ['new'])) { + # $request->setStatusBadParams(); + # return; + #} + + my $collate = Slim::Utils::OSDetect->getOS()->sqlHelperClass()->collate(); + + my $sql = 'SELECT %s FROM images '; + my $c = { 'images.hash' => 1, 'images.titlesearch' => 1, 'images.titlesort' => 1 }; # columns + my $w = []; # where + my $p = []; # parameters + my $group_by = "images.hash"; + my $order_by = "images.titlesort $collate"; + my $id_col = 'images.hash'; + my $title_col= 'images.title'; + my $limit; + + # Normalize and add any search parameters + if ( defined $imageHash ) { + push @{$w}, 'images.hash = ?'; + push @{$p}, $imageHash; + } + # ignore everything if $imageHash was specified + else { + if ($sort) { + if ( $sort eq 'new' ) { + $limit = $prefs->get('browseagelimit') || 100; + $order_by = "images.added_time desc"; + + # Force quantity to not exceed max + if ( $quantity && $quantity > $limit ) { + $quantity = $limit; + } + } + elsif ( $sort =~ /^sql=(.+)/ ) { + $order_by = $1; + $order_by =~ s/;//g; # strip out any attempt at combining SQL statements + } + } + + if ( $timeline ) { + $search ||= ''; + my ($year, $month, $day) = split('-', $search); + + $tags = 't' if $timeline !~ /^(?:day|albums)$/; + + if ( $timeline eq 'years' ) { + $sql = sprintf $sql, "strftime('%Y', date(original_time, 'unixepoch')) AS 'year'"; + $id_col = $order_by = $group_by = $title_col = 'year'; + $c = { year => 1 }; + } + + elsif ( $timeline eq 'months' && $year ) { + $sql = sprintf $sql, "strftime('%m', date(original_time, 'unixepoch')) AS 'month'"; + push @{$w}, "strftime('%Y', date(original_time, 'unixepoch')) == '$year'"; + $id_col = $order_by = $group_by = $title_col = 'month'; + $c = { month => 1 }; + } + + elsif ( $timeline eq 'days' && $year && $month ) { + $sql = sprintf $sql, "strftime('%d', date(original_time, 'unixepoch')) AS 'day'"; + push @{$w}, "strftime('%Y', date(original_time, 'unixepoch')) == '$year'"; + push @{$w}, "strftime('%m', date(original_time, 'unixepoch')) == '$month'"; + $id_col = $order_by = $group_by = $title_col = 'day'; + $c = { day => 1 }; + } + + elsif ( $timeline eq 'dates' ) { + my $dateFormat = $prefs->get('shortdateFormat'); + # only a subset of strftime is supported in SQLite, eg. no two letter years + $dateFormat =~ s/%y/%Y/; + + $sql = sprintf $sql, "strftime('$dateFormat', date(original_time, 'unixepoch')) AS 'date', strftime('%Y/%m/%d', date(original_time, 'unixepoch')) AS 'd'"; + $id_col = $order_by = $group_by = 'd'; + $title_col = 'date'; + $c = { date => 1, d => 1 }; + } + + elsif ( $timeline eq 'day' && $year && $month && $day ) { + push @{$w}, "date(original_time, 'unixepoch') == '$year-$month-$day'"; + $timeline = ''; + } + } + + elsif ( $albums ) { + if ( $search ) { + $search = URI::Escape::uri_unescape($search); + utf8::decode($search); + + $c->{'images.album'} = 1; + push @{$w}, "images.album == ?"; + push @{$p}, $search; + } + else { + $c = { 'images.album' => 1 }; + $id_col = $order_by = $group_by = $title_col = 'images.album'; + $tags = 't'; + } + } + + elsif ( $search && specified($search) ) { + if ( $search =~ s/^sql=// ) { + # Raw SQL search query + $search =~ s/;//g; # strip out any attempt at combining SQL statements + push @{$w}, $search; + } + else { + my $strings = Slim::Utils::Text::searchStringSplit($search); + if ( ref $strings->[0] eq 'ARRAY' ) { + push @{$w}, '(' . join( ' OR ', map { 'images.titlesearch LIKE ?' } @{ $strings->[0] } ) . ')'; + push @{$p}, @{ $strings->[0] }; + } + else { + push @{$w}, 'images.titlesearch LIKE ?'; + push @{$p}, @{$strings}; + } + } + } + } + + $tags =~ /t/ && do { $c->{$title_col} = 1 }; + $tags =~ /o/ && do { $c->{'images.mime_type'} = 1 }; + $tags =~ /f/ && do { $c->{'images.filesize'} = 1 }; + $tags =~ /w/ && do { $c->{'images.width'} = 1 }; + $tags =~ /h/ && do { $c->{'images.height'} = 1 }; + $tags =~ /O/ && do { $c->{'images.orientation'} = 1 }; + $tags =~ /n/ && do { $c->{'images.original_time'} = 1 }; + $tags =~ /D/ && do { $c->{'images.added_time'} = 1 }; + $tags =~ /U/ && do { $c->{'images.updated_time'} = 1 }; + $tags =~ /l/ && do { $c->{'images.album'} = 1 }; + + if ( @{$w} ) { + $sql .= 'WHERE '; + $sql .= join( ' AND ', @{$w} ); + $sql .= ' '; + } + $sql .= "GROUP BY $group_by " if $group_by; + $sql .= "ORDER BY $order_by " if $order_by; + + # Add selected columns + # Bug 15997, AS mapping needed for MySQL + my @cols = keys %{$c}; + $sql = sprintf $sql, join( ', ', map { $_ . " AS '" . $_ . "'" } @cols ) unless $timeline; + + my $stillScanning = Slim::Music::Import->stillScanning(); + + my $dbh = Slim::Schema->dbh; + + # Get count of all results, the count is cached until the next rescan done event + my $cacheKey = $sql . join( '', @{$p} ); + + my ($count) = $cache->{$cacheKey} || $dbh->selectrow_array( qq{ + SELECT COUNT(*) FROM ( $sql ) AS t1 + }, undef, @{$p} ); + + if ( !$stillScanning ) { + $cache->{$cacheKey} = $count; + } + + if ($stillScanning) { + $request->addResult('rescan', 1); + } + + $count += 0; + + my $totalCount = $count; + + # now build the result + my ($valid, $start, $end) = $request->normalize(scalar($index), scalar($quantity), $count); + + my $loopname = 'images_loop'; + my $chunkCount = 0; + + if ($valid) { + # Limit the real query + if ( $index =~ /^\d+$/ && $quantity =~ /^\d+$/ ) { + $sql .= "LIMIT $index, $quantity "; + } + + if ( main::DEBUGLOG && $sqllog->is_debug ) { + $sqllog->debug( "Image Titles query: $sql / " . Data::Dump::dump($p) ); + } + + my $sth = $dbh->prepare_cached($sql); + $sth->execute( @{$p} ); + + # Bind selected columns in order + my $i = 1; + for my $col ( @cols ) { + $sth->bind_col( $i++, \$c->{$col} ); + } + + while ( $sth->fetch ) { + utf8::decode( $c->{'images.title'} ) if exists $c->{'images.title'}; + utf8::decode( $c->{'images.album'} ) if exists $c->{'images.album'}; + + if ( $sort ne 'new' ) { + utf8::decode( $c->{'images.titlesort'} ) if exists $c->{'images.titlesort'}; + } + + # "raw" result formatting (for CLI or JSON RPC) + $request->addResultLoop($loopname, $chunkCount, 'id', $c->{$id_col}); + + $c->{title} = $c->{$title_col}; + + _imageData($request, $loopname, $chunkCount, $tags, $c); + + $chunkCount++; + + main::idleStreams() if !($chunkCount % 5); + } + } + + $request->addResult('count', $totalCount); + + $request->setStatusDone(); +} + + +sub _imageData { + my ($request, $loopname, $chunkCount, $tags, $c) = @_; + + $tags =~ /t/ && $request->addResultLoop($loopname, $chunkCount, 'title', $c->{'title'}); + $tags =~ /o/ && $request->addResultLoop($loopname, $chunkCount, 'mime_type', $c->{'images.mime_type'}); + $tags =~ /f/ && $request->addResultLoop($loopname, $chunkCount, 'filesize', $c->{'images.filesize'}); + $tags =~ /w/ && $request->addResultLoop($loopname, $chunkCount, 'width', $c->{'images.width'}); + $tags =~ /h/ && $request->addResultLoop($loopname, $chunkCount, 'height', $c->{'images.height'}); + $tags =~ /O/ && $request->addResultLoop($loopname, $chunkCount, 'orientation', $c->{'images.orientation'}); + $tags =~ /n/ && $request->addResultLoop($loopname, $chunkCount, 'original_time', $c->{'images.original_time'}); + $tags =~ /D/ && $request->addResultLoop($loopname, $chunkCount, 'added_time', $c->{'images.added_time'}); + $tags =~ /U/ && $request->addResultLoop($loopname, $chunkCount, 'updated_time', $c->{'images.updated_time'}); + $tags =~ /l/ && $request->addResultLoop($loopname, $chunkCount, 'album', $c->{'images.album'}); + $tags =~ /J/ && $request->addResultLoop($loopname, $chunkCount, 'hash', $c->{'images.hash'}); + + # browsing images by timeline Year -> Month -> Day + $c->{year} && $request->addResultLoop($loopname, $chunkCount, 'year', $c->{'year'}); + $c->{month} && $request->addResultLoop($loopname, $chunkCount, 'month', $c->{'month'}); + $c->{day} && $request->addResultLoop($loopname, $chunkCount, 'day', $c->{'day'}); +} + + =head1 SEE ALSO L diff --git a/Slim/Control/Request.pm b/Slim/Control/Request.pm index 8fe7b239a21..ff3ebbd05af 100644 --- a/Slim/Control/Request.pm +++ b/Slim/Control/Request.pm @@ -1,11 +1,11 @@ package Slim::Control::Request; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. -# This class implements a generic request mechanism for Squeezebox Server. +# This class implements a generic request mechanism for Logitech Media Server. # More documentation is provided below the table of commands & queries =head1 NAME @@ -14,7 +14,7 @@ Slim::Control::Request =head1 DESCRIPTION -This class implements a generic request mechanism for Squeezebox Server. +This class implements a generic request mechanism for Logitech Media Server. The general mechansim is to create a Request object and execute it. There is an option of specifying a callback function, to be called once the request is @@ -62,6 +62,9 @@ my $request = Slim::Control::Request::executeRequest($client, ['stop']); N titles N years N musicfolder + + N videos + N video_titles N playlists N playlists tracks @@ -347,7 +350,7 @@ my $request = Slim::Control::Request::executeRequest($client, ['stop']); =head2 Adding a command To add a command to the dispatch table, use the addDispatch method. If the - method is part of Squeezebox Server itself, please add it to the init method below + method is part of the server itself, please add it to the init method below and update the comment table at the top of the document. In a plugin, call the method from your initPlugin subroutine. @@ -522,7 +525,9 @@ sub init { addDispatch(['mixer', 'volume', '?'], [1, 1, 0, \&Slim::Control::Queries::mixerQuery]); addDispatch(['mixer', 'volume', '_newvalue'], [1, 0, 1, \&Slim::Control::Commands::mixerCommand]); addDispatch(['mode', '?'], [1, 1, 0, \&Slim::Control::Queries::modeQuery]); + # musicfolder is only here for backwards compatibility - it's calling mediafolder internally addDispatch(['musicfolder', '_index', '_quantity'], [0, 1, 1, \&Slim::Control::Queries::musicfolderQuery]); + addDispatch(['mediafolder', '_index', '_quantity'], [0, 1, 1, \&Slim::Control::Queries::mediafolderQuery]); addDispatch(['name', '_newvalue'], [1, 0, 0, \&Slim::Control::Commands::nameCommand]); addDispatch(['name', '?'], [1, 1, 0, \&Slim::Control::Queries::nameQuery]); addDispatch(['path', '?'], [1, 1, 0, \&Slim::Control::Queries::cursonginfoQuery]); @@ -630,6 +635,8 @@ sub init { addDispatch(['artwork', '_artworkid'], [0, 0, 0, \&Slim::Control::Queries::showArtwork]); addDispatch(['rating', '_item', '?'], [0, 1, 0, \&Slim::Control::Commands::ratingCommand]); addDispatch(['rating', '_item', '_rating'], [0, 0, 0, \&Slim::Control::Commands::ratingCommand]); + addDispatch(['video_titles', '_index', '_quantity'], [0, 1, 1, \&Slim::Control::Queries::videoTitlesQuery]); + addDispatch(['image_titles', '_index', '_quantity'], [0, 1, 1, \&Slim::Control::Queries::imageTitlesQuery]); # NOTIFICATIONS addDispatch(['client', 'disconnect'], [1, 0, 0, undef]); @@ -672,7 +679,7 @@ sub init { return if !main::WEBUI; - # Normal Squeezebox Server commands can be accessed with URLs like + # Normal Logitech Media Server commands can be accessed with URLs like # http://localhost:9000/status.html?p0=pause&player=00%3A00%3A00%3A00%3A00%3A00 # Use the protectCommand() API to prevent CSRF attacks on commands -- including commands # not intended for use via the web interface! @@ -1337,7 +1344,7 @@ my %statusMap = ( 102 => 'Bad params!', 103 => 'Missing client!', 104 => 'Unknown in dispatch table', - 105 => 'Bad Squeezebox Server config', + 105 => 'Bad Logitech Media Server config', ); # validate the Request, make sure we are dispatchable diff --git a/Slim/Control/Stdio.pm b/Slim/Control/Stdio.pm index 6d33ecfa538..58e07689802 100644 --- a/Slim/Control/Stdio.pm +++ b/Slim/Control/Stdio.pm @@ -1,6 +1,6 @@ package Slim::Control::Stdio; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/DO_NOT_INSTALL_YOUR_PLUGINS_HERE.txt b/Slim/DO_NOT_INSTALL_YOUR_PLUGINS_HERE.txt index fd7bf0f4007..48ab879563e 100644 --- a/Slim/DO_NOT_INSTALL_YOUR_PLUGINS_HERE.txt +++ b/Slim/DO_NOT_INSTALL_YOUR_PLUGINS_HERE.txt @@ -1,6 +1,6 @@ Don't install anything here - it could be wiped during the next update. Thanks. -The Slim/Plugin folder is for plugins installed with Squeezebox Server only. +The Slim/Plugin folder is for plugins installed with Logitech Media Server only. Use the user plugin folder instead. The plugin paths are listed in the web UI in Settings/Status or on the player in Settings/Information. \ No newline at end of file diff --git a/Slim/Display/Boom.pm b/Slim/Display/Boom.pm index 154200f1b3b..7722e883fb1 100644 --- a/Slim/Display/Boom.pm +++ b/Slim/Display/Boom.pm @@ -1,6 +1,6 @@ package Slim::Display::Boom; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Display.pm b/Slim/Display/Display.pm index 243281784fe..4cea0f5a8f4 100644 --- a/Slim/Display/Display.pm +++ b/Slim/Display/Display.pm @@ -2,7 +2,7 @@ package Slim::Display::Display; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/EmulatedSqueezebox2.pm b/Slim/Display/EmulatedSqueezebox2.pm index cc1229104c3..e1e95f149cb 100644 --- a/Slim/Display/EmulatedSqueezebox2.pm +++ b/Slim/Display/EmulatedSqueezebox2.pm @@ -1,6 +1,6 @@ package Slim::Display::EmulatedSqueezebox2; -# Squeezebox Server Copyright (c) 2001-2009 Logitech. +# Logitech Media Server Copyright (c) 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Graphics.pm b/Slim/Display/Graphics.pm index f297160ce5d..db5be66937b 100644 --- a/Slim/Display/Graphics.pm +++ b/Slim/Display/Graphics.pm @@ -1,6 +1,6 @@ package Slim::Display::Graphics; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Lib/Fonts.pm b/Slim/Display/Lib/Fonts.pm index fbe61379095..8611e885278 100644 --- a/Slim/Display/Lib/Fonts.pm +++ b/Slim/Display/Lib/Fonts.pm @@ -1,6 +1,6 @@ package Slim::Display::Lib::Fonts; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Lib/TextVFD.pm b/Slim/Display/Lib/TextVFD.pm index 4f069c9fcdb..9e0765beeff 100644 --- a/Slim/Display/Lib/TextVFD.pm +++ b/Slim/Display/Lib/TextVFD.pm @@ -1,6 +1,6 @@ package Slim::Display::Lib::TextVFD; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/NoDisplay.pm b/Slim/Display/NoDisplay.pm index de0fa7f8a0a..af25d804398 100644 --- a/Slim/Display/NoDisplay.pm +++ b/Slim/Display/NoDisplay.pm @@ -1,6 +1,6 @@ package Slim::Display::NoDisplay; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Squeezebox2.pm b/Slim/Display/Squeezebox2.pm index f85ab6135d9..e03e623bcfa 100644 --- a/Slim/Display/Squeezebox2.pm +++ b/Slim/Display/Squeezebox2.pm @@ -1,6 +1,6 @@ package Slim::Display::Squeezebox2; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/SqueezeboxG.pm b/Slim/Display/SqueezeboxG.pm index 596cbfb3d7c..7a549c5d56e 100644 --- a/Slim/Display/SqueezeboxG.pm +++ b/Slim/Display/SqueezeboxG.pm @@ -1,6 +1,6 @@ package Slim::Display::SqueezeboxG; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Text.pm b/Slim/Display/Text.pm index 5dc9cb331d8..778a6a52c35 100644 --- a/Slim/Display/Text.pm +++ b/Slim/Display/Text.pm @@ -1,6 +1,6 @@ package Slim::Display::Text; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Display/Transporter.pm b/Slim/Display/Transporter.pm index a4b0b982776..aede92fc010 100644 --- a/Slim/Display/Transporter.pm +++ b/Slim/Display/Transporter.pm @@ -1,6 +1,6 @@ package Slim::Display::Transporter; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats.pm b/Slim/Formats.pm index 4ad49aa56b4..1c596cbc92f 100644 --- a/Slim/Formats.pm +++ b/Slim/Formats.pm @@ -2,7 +2,7 @@ package Slim::Formats; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/AIFF.pm b/Slim/Formats/AIFF.pm index f3a271fcba4..9344782e101 100644 --- a/Slim/Formats/AIFF.pm +++ b/Slim/Formats/AIFF.pm @@ -2,7 +2,7 @@ package Slim::Formats::AIFF; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/APE.pm b/Slim/Formats/APE.pm index 8bbb63025d3..d01c68878d5 100644 --- a/Slim/Formats/APE.pm +++ b/Slim/Formats/APE.pm @@ -2,7 +2,7 @@ package Slim::Formats::APE; # $Id: APE.pm 5405 2005-12-14 22:02:37Z dean $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/FLAC.pm b/Slim/Formats/FLAC.pm index 58a082fbffc..de51e2da476 100644 --- a/Slim/Formats/FLAC.pm +++ b/Slim/Formats/FLAC.pm @@ -2,7 +2,7 @@ package Slim::Formats::FLAC; # $tagsd: FLAC.pm,v 1.5 2003/12/15 17:57:50 daniel Exp $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -369,7 +369,7 @@ sub _getXMLTags { # retrieve the xml content from the flac my $xml = $s->{tags}->{APPLICATION}->{$PEEM} || return 0; - # TODO: parse this using the same xml modules Squeezebox Server uses to parse iTunes + # TODO: parse this using the same xml modules Logitech Media Server uses to parse iTunes # even better, use RDF::Simple::Parser # crude regex matching until we get a real rdf/xml parser in place diff --git a/Slim/Formats/MP3.pm b/Slim/Formats/MP3.pm index 5877bd55f33..1bead25f316 100644 --- a/Slim/Formats/MP3.pm +++ b/Slim/Formats/MP3.pm @@ -2,7 +2,7 @@ package Slim::Formats::MP3; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/Movie.pm b/Slim/Formats/Movie.pm index 3c1be926dd5..beb2696fcd3 100644 --- a/Slim/Formats/Movie.pm +++ b/Slim/Formats/Movie.pm @@ -2,7 +2,7 @@ package Slim::Formats::Movie; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -53,6 +53,11 @@ sub getTag { return unless $info->{song_length_ms}; + # skip files with video tracks + for my $track ( @{ $info->{tracks} } ) { + return if exists $track->{width}; + } + # map the existing tag names to the expected tag names $class->_doTagMapping($tags); @@ -63,7 +68,7 @@ sub getTag { $tags->{BITRATE} = $info->{avg_bitrate}; if ( my $track = $info->{tracks}->[0] ) { - # MP4 file + # MP4 file $tags->{SAMPLESIZE} = $track->{bits_per_sample}; $tags->{CHANNELS} = $track->{channels}; diff --git a/Slim/Formats/Musepack.pm b/Slim/Formats/Musepack.pm index 9718ba70241..5804a4d85da 100644 --- a/Slim/Formats/Musepack.pm +++ b/Slim/Formats/Musepack.pm @@ -2,7 +2,7 @@ package Slim::Formats::Musepack; # $tagsd: Musepack.pm,v 1.0 2004/01/27 00:00:00 daniel Exp $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/Ogg.pm b/Slim/Formats/Ogg.pm index 1f7cd0a0105..8ba3bd6593a 100644 --- a/Slim/Formats/Ogg.pm +++ b/Slim/Formats/Ogg.pm @@ -2,7 +2,7 @@ package Slim::Formats::Ogg; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/Playlists.pm b/Slim/Formats/Playlists.pm index ab8ae7d1967..7f0f4484fcb 100644 --- a/Slim/Formats/Playlists.pm +++ b/Slim/Formats/Playlists.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License, version 2. diff --git a/Slim/Formats/Playlists/ASX.pm b/Slim/Formats/Playlists/ASX.pm index 97ae6f2ba44..b499cae34b9 100644 --- a/Slim/Formats/Playlists/ASX.pm +++ b/Slim/Formats/Playlists/ASX.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::ASX; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/Playlists/Base.pm b/Slim/Formats/Playlists/Base.pm index 1f0acf84089..3c55c5a99c3 100644 --- a/Slim/Formats/Playlists/Base.pm +++ b/Slim/Formats/Playlists/Base.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::Base; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License, version 2. diff --git a/Slim/Formats/Playlists/CUE.pm b/Slim/Formats/Playlists/CUE.pm index 9dabc221e9e..5774f640ac3 100644 --- a/Slim/Formats/Playlists/CUE.pm +++ b/Slim/Formats/Playlists/CUE.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::CUE; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, diff --git a/Slim/Formats/Playlists/M3U.pm b/Slim/Formats/Playlists/M3U.pm index 970f80de2b0..d6d66c158ba 100644 --- a/Slim/Formats/Playlists/M3U.pm +++ b/Slim/Formats/Playlists/M3U.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::M3U; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, @@ -31,7 +31,7 @@ sub read { my ($secs, $artist, $album, $title, $trackurl); my $foundBOM = 0; my $fh; - my $audiodir; + my $mediadirs; if (defined $file && ref $file) { $fh = $file; # filehandle passed @@ -152,21 +152,25 @@ sub read { } else { # Check if the playlist entry is relative to audiodir - $audiodir ||= Slim::Utils::Misc::getAudioDir(); + $mediadirs ||= Slim::Utils::Misc::getAudioDirs(); - $trackurl = Slim::Utils::Misc::fixPath($entry, $audiodir); - - if ($class->playlistEntryIsValid($trackurl, $url)) { - - main::DEBUGLOG && $log->debug(" valid entry: $trackurl"); - - push @items, $class->_updateMetaData( $trackurl, { - 'TITLE' => $title, - 'ALBUM' => $album, - 'ARTIST' => $artist, - 'SECS' => ( defined $secs && $secs > 0 ) ? $secs : undef, - } ); - + foreach my $audiodir (@$mediadirs) { + $trackurl = Slim::Utils::Misc::fixPath($entry, $audiodir); + + if ($class->playlistEntryIsValid($trackurl, $url)) { + + main::DEBUGLOG && $log->debug(" valid entry: $trackurl"); + + push @items, $class->_updateMetaData( $trackurl, { + 'TITLE' => $title, + 'ALBUM' => $album, + 'ARTIST' => $artist, + 'SECS' => ( defined $secs && $secs > 0 ) ? $secs : undef, + } ); + + last; + } + # reset the title ($secs, $artist, $album, $title, $trackurl) = (); } diff --git a/Slim/Formats/Playlists/PLS.pm b/Slim/Formats/Playlists/PLS.pm index 44b62c48ae2..d9da433cd16 100644 --- a/Slim/Formats/Playlists/PLS.pm +++ b/Slim/Formats/Playlists/PLS.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::PLS; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, diff --git a/Slim/Formats/Playlists/WPL.pm b/Slim/Formats/Playlists/WPL.pm index f6b4d87818a..8ad01664911 100644 --- a/Slim/Formats/Playlists/WPL.pm +++ b/Slim/Formats/Playlists/WPL.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::WPL; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, diff --git a/Slim/Formats/Playlists/XML.pm b/Slim/Formats/Playlists/XML.pm index bc4b75db820..de3c9f845b2 100644 --- a/Slim/Formats/Playlists/XML.pm +++ b/Slim/Formats/Playlists/XML.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::XML; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, diff --git a/Slim/Formats/Playlists/XSPF.pm b/Slim/Formats/Playlists/XSPF.pm index eff0f57fad6..ca91d6692d2 100644 --- a/Slim/Formats/Playlists/XSPF.pm +++ b/Slim/Formats/Playlists/XSPF.pm @@ -2,7 +2,7 @@ package Slim::Formats::Playlists::XSPF; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, diff --git a/Slim/Formats/RemoteMetadata.pm b/Slim/Formats/RemoteMetadata.pm index 0fc590609db..20f9919ef00 100644 --- a/Slim/Formats/RemoteMetadata.pm +++ b/Slim/Formats/RemoteMetadata.pm @@ -2,7 +2,7 @@ package Slim::Formats::RemoteMetadata; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Formats/RemoteStream.pm b/Slim/Formats/RemoteStream.pm index 5d2be4ee3e3..39d632acebb 100644 --- a/Slim/Formats/RemoteStream.pm +++ b/Slim/Formats/RemoteStream.pm @@ -2,7 +2,7 @@ package Slim::Formats::RemoteStream; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License, version 2. diff --git a/Slim/Formats/WMA.pm b/Slim/Formats/WMA.pm index 438f92828a6..2dca9654401 100644 --- a/Slim/Formats/WMA.pm +++ b/Slim/Formats/WMA.pm @@ -2,7 +2,7 @@ package Slim::Formats::WMA; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -53,7 +53,7 @@ sub getTag { return unless $info->{song_length_ms}; - # Map tags onto Squeezebox Server's preferred. + # Map tags onto Logitech Media Server's preferred. while ( my ($old, $new) = each %tagMapping ) { if ( exists $tags->{$old} ) { $tags->{$new} = delete $tags->{$old}; diff --git a/Slim/Formats/Wav.pm b/Slim/Formats/Wav.pm index 5a4281d3f3f..c1dbebb1c3d 100644 --- a/Slim/Formats/Wav.pm +++ b/Slim/Formats/Wav.pm @@ -2,7 +2,7 @@ package Slim::Formats::Wav; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel.pm b/Slim/GUI/ControlPanel.pm index d05e2a7320d..23ac2cd2a0b 100644 --- a/Slim/GUI/ControlPanel.pm +++ b/Slim/GUI/ControlPanel.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::MainFrame; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel/Account.pm b/Slim/GUI/ControlPanel/Account.pm index 9ad88a0bdb1..2779f969923 100644 --- a/Slim/GUI/ControlPanel/Account.pm +++ b/Slim/GUI/ControlPanel/Account.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::Account; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel/Advanced.pm b/Slim/GUI/ControlPanel/Advanced.pm index ad1b1789808..969789dc82f 100644 --- a/Slim/GUI/ControlPanel/Advanced.pm +++ b/Slim/GUI/ControlPanel/Advanced.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::Advanced; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel/Diagnostics.pm b/Slim/GUI/ControlPanel/Diagnostics.pm index 79dd1ad71e2..fc3c3828d9f 100644 --- a/Slim/GUI/ControlPanel/Diagnostics.pm +++ b/Slim/GUI/ControlPanel/Diagnostics.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::Diagnostics; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel/InitialSettings.pm b/Slim/GUI/ControlPanel/InitialSettings.pm index 6d94ba8585f..1f786f6f6b4 100644 --- a/Slim/GUI/ControlPanel/InitialSettings.pm +++ b/Slim/GUI/ControlPanel/InitialSettings.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::InitialSettings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel/Music.pm b/Slim/GUI/ControlPanel/Music.pm index df36b2376f4..8770341f950 100644 --- a/Slim/GUI/ControlPanel/Music.pm +++ b/Slim/GUI/ControlPanel/Music.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::Music; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -26,17 +26,62 @@ sub new { $mainSizer->Add($self->getLibraryName($parent), 0, wxALL | wxGROW, 10); my $settingsSizer = Wx::StaticBoxSizer->new( - Wx::StaticBox->new($self, -1, string('MUSICSOURCE')), + Wx::StaticBox->new($self, -1, string('MEDIASOURCE')), wxVERTICAL ); # folder selectors - $settingsSizer->Add(Wx::StaticText->new($self, -1, string('SETUP_AUDIODIR')), 0, wxLEFT | wxTOP, 10); + $settingsSizer->Add(Wx::StaticText->new($self, -1, string('SETUP_MEDIADIRS')), 0, wxLEFT | wxTOP, 10); + + my $mediaDirsSizer = Wx::BoxSizer->new(wxVERTICAL); + my $dirsBtnSizer = Wx::BoxSizer->new(wxHORIZONTAL); + + my $dirsList = Wx::ListBox->new($self, -1, wxDefaultPosition, wxDefaultSize, [], wxLB_EXTENDED); + my $mediadirs = Slim::GUI::ControlPanel->getPref('mediadirs'); + if ($mediadirs && ref $mediadirs eq 'ARRAY') { + $dirsList->InsertItems($mediadirs, 0); + } + $mediaDirsSizer->Add($dirsList, 0, wxGROW, 10); + + my $btnAdd = Wx::Button->new($self, -1, string('ADD')); + $parent->addStatusListener($btnAdd); + $dirsBtnSizer->Add($btnAdd, 0); + $dirsBtnSizer->AddSpacer(5); + + my $btnRemove = Wx::Button->new($self, -1, string('DELETE')); + $parent->addStatusListener($btnRemove); + $dirsBtnSizer->Add($btnRemove, 0); + + $mediaDirsSizer->Add($dirsBtnSizer, 0, wxTOP, 5); $settingsSizer->AddSpacer(5); - $settingsSizer->Add( - Slim::GUI::ControlPanel::DirPicker->new($self, $parent, 'audiodir', 'SETUP_AUDIODIR'), - 0, wxEXPAND | wxLEFT | wxRIGHT, 10 - ); + $settingsSizer->Add($mediaDirsSizer, 0, wxGROW | wxLEFT | wxRIGHT, 10); + + EVT_BUTTON($self, $btnAdd, sub { + my $dirsSelector = Wx::DirDialog->new($self); + if ($dirsSelector->ShowModal() == wxID_OK) { + if (my $path = $dirsSelector->GetPath()) { + $dirsList->Append($path); + } + } + }); + + EVT_BUTTON($self, $btnRemove, sub { + my @selected = $dirsList->GetSelections(); + foreach (reverse sort @selected) { + $dirsList->Delete($_); + } + }); + + $parent->addApplyHandler($self, sub { + my $running = (shift == SC_STATE_RUNNING); + + my @mediaDirs = $dirsList->GetStrings(); + + if ($running && scalar @mediaDirs) { + Slim::GUI::ControlPanel->setPref('mediadirs', \@mediaDirs); + } + }); + $settingsSizer->Add(Wx::StaticText->new($self, -1, string('SETUP_PLAYLISTDIR')), 0, wxLEFT | wxTOP, 10); $settingsSizer->AddSpacer(5); @@ -44,7 +89,7 @@ sub new { Slim::GUI::ControlPanel::DirPicker->new($self, $parent, 'playlistdir', 'SETUP_PLAYLISTDIR'), 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 10 ); - + my $iTunes = getPref('iTunes', 'state.prefs'); my $useItunesStr = ($svcMgr->checkServiceState() == SC_STATE_RUNNING) ? Slim::GUI::ControlPanel->serverRequest('getstring', 'USE_ITUNES') @@ -65,7 +110,7 @@ sub new { }); } - $mainSizer->Add($settingsSizer, 0, wxALL | wxGROW, 10); + $mainSizer->Add($settingsSizer, 0, wxALL | wxEXPAND, 10); $self->SetSizer($mainSizer); diff --git a/Slim/GUI/ControlPanel/Settings.pm b/Slim/GUI/ControlPanel/Settings.pm index 86ed4b9809b..48bd2545c0c 100644 --- a/Slim/GUI/ControlPanel/Settings.pm +++ b/Slim/GUI/ControlPanel/Settings.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/GUI/ControlPanel/Status.pm b/Slim/GUI/ControlPanel/Status.pm index 3c072490c49..f5d68dda1d5 100644 --- a/Slim/GUI/ControlPanel/Status.pm +++ b/Slim/GUI/ControlPanel/Status.pm @@ -1,6 +1,6 @@ package Slim::GUI::ControlPanel::Status; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Hardware/BacklightLED.pm b/Slim/Hardware/BacklightLED.pm index dc527753a8d..6dc0338a894 100644 --- a/Slim/Hardware/BacklightLED.pm +++ b/Slim/Hardware/BacklightLED.pm @@ -1,6 +1,6 @@ package Slim::Hardware::BacklightLED; -# Squeezebox Server Copyright (c) 2001-2009 Logitech. +# Logitech Media Server Copyright (c) 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Hardware/IR.pm b/Slim/Hardware/IR.pm index ba1095287b5..6aec4188032 100644 --- a/Slim/Hardware/IR.pm +++ b/Slim/Hardware/IR.pm @@ -2,7 +2,7 @@ package Slim::Hardware::IR; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Hardware/TriLED.pm b/Slim/Hardware/TriLED.pm index ccabae4d7f8..20370652d14 100644 --- a/Slim/Hardware/TriLED.pm +++ b/Slim/Hardware/TriLED.pm @@ -1,6 +1,6 @@ package Slim::Hardware::TriLED; -# Squeezebox Server Copyright (c) 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Hardware/mas3507d.pm b/Slim/Hardware/mas3507d.pm index 2f3013b9c48..cb50789e810 100644 --- a/Slim/Hardware/mas3507d.pm +++ b/Slim/Hardware/mas3507d.pm @@ -2,7 +2,7 @@ package Slim::Hardware::mas3507d; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Hardware/mas35x9.pm b/Slim/Hardware/mas35x9.pm index 73ec1b35203..f712011b97d 100644 --- a/Slim/Hardware/mas35x9.pm +++ b/Slim/Hardware/mas35x9.pm @@ -2,7 +2,7 @@ package Slim::Hardware::mas35x9; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Media/MediaFolderScan.pm b/Slim/Media/MediaFolderScan.pm new file mode 100644 index 00000000000..ffb5fdaa604 --- /dev/null +++ b/Slim/Media/MediaFolderScan.pm @@ -0,0 +1,107 @@ +package Slim::Media::MediaFolderScan; + +# $Id +# +# Logitech Media Server Copyright 2001-2011 Logitech. +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License, +# version 2. + +=head1 NAME + +Slim::Media::MediaFolderScan + +=head1 DESCRIPTION + +=cut + +use strict; +use base qw(Class::Data::Inheritable); + +use Slim::Music::Info; +use Slim::Utils::Log; +use Slim::Utils::Scanner::Local; +use Slim::Utils::Scanner::LMS; +use Slim::Utils::Prefs; + +{ + __PACKAGE__->mk_classdata('stillScanning'); +} + +my $log = logger('scan.import'); + +my $prefs = preferences('server'); + +sub init { + my $class = shift; + + Slim::Music::Import->addImporter( $class, { + type => 'file', + weight => 1, + } ); + + Slim::Music::Import->useImporter($class, 1); +} + +sub startScan { + my $class = shift; + my $dirs = shift || Slim::Utils::Misc::getMediaDirs(); + + if (ref $dirs ne 'ARRAY' || scalar @{$dirs} == 0) { + main::INFOLOG && $log->info("Skipping media folder scan - no folders defined."); + $class->stillScanning(0); + Slim::Music::Import->endImporter($class); + return 0; + } + + $class->stillScanning(1); + + my $changes = 0; + + # get media folders without audio dirs + $dirs = [ keys %{{ map { $_, 1 } @{ Slim::Utils::Misc::getVideoDirs() }, @{ Slim::Utils::Misc::getImageDirs() } }} ]; + + for my $dir ( @{$dirs} ) { + main::INFOLOG && $log->info("Starting media folder scan in: $dir" ); + my $c = Slim::Utils::Scanner::LMS->rescan( $dir, { + scanName => 'directory', + wipe => main::SCANNER && $main::wipe ? 1 : 0, # XXX ugly + no_async => 1, + progress => 1, + } ); + + $changes += $c; + } + + main::INFOLOG && $log->info("Finished scan of media folder (changes: $changes)."); + + # XXX until libmediascan supports audio, run the audio scanner now + if ( ($dirs = Slim::Utils::Misc::getAudioDirs()) && scalar @{$dirs} ) { + main::INFOLOG && $log->info("Starting audio-only scan in: " . Data::Dump::dump($dirs)); + + my $c = Slim::Utils::Scanner::Local->rescan( $dirs, { + types => 'audio', + scanName => 'directory', + no_async => 1, + progress => 1, + } ); + + $changes += $c; + } + + $class->stillScanning(0); + + Slim::Music::Import->endImporter($class); + + return $changes; +} + +=head1 SEE ALSO + +L + +=cut + +1; + +__END__ diff --git a/Slim/Menu/AlbumInfo.pm b/Slim/Menu/AlbumInfo.pm index 7689df58eb7..3a85302c31d 100644 --- a/Slim/Menu/AlbumInfo.pm +++ b/Slim/Menu/AlbumInfo.pm @@ -1,6 +1,6 @@ package Slim::Menu::AlbumInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/ArtistInfo.pm b/Slim/Menu/ArtistInfo.pm index 8f94c932046..f8dd31f9b96 100644 --- a/Slim/Menu/ArtistInfo.pm +++ b/Slim/Menu/ArtistInfo.pm @@ -1,6 +1,6 @@ package Slim::Menu::ArtistInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/Base.pm b/Slim/Menu/Base.pm index 031b2925c10..7647a3ddeda 100644 --- a/Slim/Menu/Base.pm +++ b/Slim/Menu/Base.pm @@ -2,7 +2,7 @@ package Slim::Menu::Base; # $Id: $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/BrowseLibrary.pm b/Slim/Menu/BrowseLibrary.pm index 8e4094054dc..524ea7c460c 100644 --- a/Slim/Menu/BrowseLibrary.pm +++ b/Slim/Menu/BrowseLibrary.pm @@ -565,7 +565,7 @@ sub _registerBaseNodes { feed => \&_bmf, icon => 'html/images/musicfolder.png', homeMenuText => 'BROWSE_MUSIC_FOLDER', - condition => sub {return Slim::Schema::hasLibrary && Slim::Utils::Misc::getAudioDir();}, + condition => sub {return Slim::Schema::hasLibrary && scalar @{ Slim::Utils::Misc::getAudioDirs() };}, id => 'myMusicMusicFolder', weight => 70, }, diff --git a/Slim/Menu/FolderInfo.pm b/Slim/Menu/FolderInfo.pm index 9a994f3a15e..0600915ab30 100644 --- a/Slim/Menu/FolderInfo.pm +++ b/Slim/Menu/FolderInfo.pm @@ -1,6 +1,6 @@ package Slim::Menu::FolderInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/GenreInfo.pm b/Slim/Menu/GenreInfo.pm index d53bd694c85..f859805673c 100644 --- a/Slim/Menu/GenreInfo.pm +++ b/Slim/Menu/GenreInfo.pm @@ -1,6 +1,6 @@ package Slim::Menu::GenreInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/GlobalSearch.pm b/Slim/Menu/GlobalSearch.pm index f69d5f4912e..a7483c59406 100644 --- a/Slim/Menu/GlobalSearch.pm +++ b/Slim/Menu/GlobalSearch.pm @@ -1,6 +1,6 @@ package Slim::Menu::GlobalSearch; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/PlaylistInfo.pm b/Slim/Menu/PlaylistInfo.pm index dae52e7ba0e..4d9493cd1c5 100644 --- a/Slim/Menu/PlaylistInfo.pm +++ b/Slim/Menu/PlaylistInfo.pm @@ -1,6 +1,6 @@ package Slim::Menu::PlaylistInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/SystemInfo.pm b/Slim/Menu/SystemInfo.pm index dfc7de0edca..2fa0a270190 100644 --- a/Slim/Menu/SystemInfo.pm +++ b/Slim/Menu/SystemInfo.pm @@ -2,7 +2,7 @@ package Slim::Menu::SystemInfo; # $Id: $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -218,15 +218,17 @@ sub infoLibrary { }; } - return Slim::Music::Import->stillScanning - ? { - name => cstring($client, 'RESCANNING_SHORT'), - - web => { - hide => 1, - }, - } - : { + elsif (Slim::Music::Import->stillScanning) { + return { + name => cstring($client, 'RESCANNING_SHORT'), + + web => { + hide => 1, + }, + } + } + + my $items = { name => cstring($client, 'INFORMATION_MENU_LIBRARY'), items => [ @@ -265,8 +267,29 @@ sub infoLibrary { group => 'library', unfold => 1, }, + }; + + # XXX - no simple access to result sets for images/videos yet? + + my $request = Slim::Control::Request::executeRequest( $client, ['video_titles', 0, 0] ); + my $results = $request->getResults(); + unshift @{ $items->{items} }, { + type => 'text', + name => cstring($client, 'INFORMATION_VIDEOS') . cstring($client, 'COLON') . ' ' + . ($results && $results->{count} ? Slim::Utils::Misc::delimitThousands($results->{count}) : 0), }; + + $request = Slim::Control::Request::executeRequest( $client, ['image_titles', 0, 0] ); + $results = $request->getResults(); + + unshift @{ $items->{items} }, { + type => 'text', + name => cstring($client, 'INFORMATION_IMAGES') . cstring($client, 'COLON') . ' ' + . ($results && $results->{count} ? Slim::Utils::Misc::delimitThousands($results->{count}) : 0), + }; + + return $items } sub infoServer { @@ -280,7 +303,7 @@ sub infoServer { my $items = [ { type => 'text', - name => sprintf("%s%s %s - %s @ %s", + name => sprintf("Logitech Media Server %s%s %s - %s @ %s", cstring($client, 'INFORMATION_VERSION'), cstring($client, 'COLON'), $::VERSION, diff --git a/Slim/Menu/TrackInfo.pm b/Slim/Menu/TrackInfo.pm index 67f1cd5ae4e..8085ee66afe 100644 --- a/Slim/Menu/TrackInfo.pm +++ b/Slim/Menu/TrackInfo.pm @@ -2,7 +2,7 @@ package Slim::Menu::TrackInfo; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Menu/YearInfo.pm b/Slim/Menu/YearInfo.pm index 93a7596c4b5..38a1c0f0756 100644 --- a/Slim/Menu/YearInfo.pm +++ b/Slim/Menu/YearInfo.pm @@ -1,6 +1,6 @@ package Slim::Menu::YearInfo; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Music/Artwork.pm b/Slim/Music/Artwork.pm index e31657325c4..eddda6d01a9 100644 --- a/Slim/Music/Artwork.pm +++ b/Slim/Music/Artwork.pm @@ -2,7 +2,7 @@ package Slim::Music::Artwork; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -622,7 +622,7 @@ sub downloadArtwork { if ( main::SCANNER ) { $ua = LWP::UserAgent->new( - agent => 'Squeezebox Server/' . $::VERSION, + agent => 'Logitech Media Server/' . $::VERSION, timeout => 10, ); $ua->default_header($authHeader->[0] => $authHeader->[1]); diff --git a/Slim/Music/Import.pm b/Slim/Music/Import.pm index 69e6a2d61a2..21bd4942e27 100644 --- a/Slim/Music/Import.pm +++ b/Slim/Music/Import.pm @@ -1,6 +1,6 @@ package Slim::Music::Import; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -300,7 +300,10 @@ sub runScan { next; } - $changes += $class->runImporter($importer); + # XXX tmp var is to avoid a strange "Can't coerce CODE to integer in addition (+)" error/bug + # even though there is no way this returns a coderef... + my $tmp = $class->runImporter($importer); + $changes += $tmp; } $class->scanPlaylistsOnly(0); @@ -649,7 +652,7 @@ sub _checkLibraryStatus { =head1 SEE ALSO -L +L L diff --git a/Slim/Music/Info.pm b/Slim/Music/Info.pm index a45e7648cff..4dcb4ab46d3 100644 --- a/Slim/Music/Info.pm +++ b/Slim/Music/Info.pm @@ -2,7 +2,7 @@ package Slim::Music::Info; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -1306,21 +1306,31 @@ sub validTypeExtensions { my @extensions = (); my $disabled = disabledExtensions($findTypes); - while (my ($ext, $type) = each %slimTypes) { - - next unless $type; - next unless $type =~ /$findTypes/; - - while (my ($suffix, $value) = each %suffixes) { - - # Don't add extensions that are disabled. - if ($disabled->{$suffix}) { - next; - } - - # Don't return values for 'internal' or iTunes type playlists. - if ($ext eq $value && $suffix !~ /:/) { - push @extensions, $suffix; + # XXX - these should be read from a shared source with Media::Scan + if ($findTypes eq 'image') { + @extensions = grep { !$disabled->{$_} } qw(jpg png gif bmp jpeg); + } + elsif ($findTypes eq 'video') { + @extensions = grep { !$disabled->{$_} } qw(asf avi divx flv hdmov m1v m2p m2t m2ts m2v m4v mkv mov mpg mpeg mpe mp2p mp2t mp4 mts pes ps ts vob webm wmv xvid 3gp 3g2 3gp2 3gpp mjpg); + } + # audio files, playlists + else { + while (my ($ext, $type) = each %slimTypes) { + + next unless $type; + next unless $type =~ /$findTypes/; + + while (my ($suffix, $value) = each %suffixes) { + + # Don't add extensions that are disabled. + if ($disabled->{$suffix}) { + next; + } + + # Don't return values for 'internal' or iTunes type playlists. + if ($ext eq $value && $suffix !~ /:/) { + push @extensions, $suffix; + } } } } @@ -1360,6 +1370,14 @@ sub disabledExtensions { @disabled = @playlist; + } elsif ($findTypes eq 'video') { + + @disabled = split(/\s*,\s*/, $prefs->get('disabledextensionsvideo')); + + } elsif ($findTypes eq 'image') { + + @disabled = split(/\s*,\s*/, $prefs->get('disabledextensionsimages')); + } else { @disabled = (@audio, @playlist); diff --git a/Slim/Music/PlaylistFolderScan.pm b/Slim/Music/PlaylistFolderScan.pm index e082ff53f01..3bc96ad2caf 100644 --- a/Slim/Music/PlaylistFolderScan.pm +++ b/Slim/Music/PlaylistFolderScan.pm @@ -2,7 +2,7 @@ package Slim::Music::PlaylistFolderScan; # $Id # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Music/TitleFormatter.pm b/Slim/Music/TitleFormatter.pm index 8a5ca2e0dbd..8f299228463 100644 --- a/Slim/Music/TitleFormatter.pm +++ b/Slim/Music/TitleFormatter.pm @@ -2,7 +2,7 @@ package Slim::Music::TitleFormatter; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -377,7 +377,7 @@ sub init { return 1; } -# This does not currently have any callers in the Squeezebox Server tree. +# This does not currently have any callers in the Logitech Media Server tree. sub addFormat { my $format = shift; my $formatSubRef = shift; diff --git a/Slim/Networking/Async.pm b/Slim/Networking/Async.pm index 9081c6b6ebe..94efd7046f4 100644 --- a/Slim/Networking/Async.pm +++ b/Slim/Networking/Async.pm @@ -2,13 +2,13 @@ package Slim::Networking::Async; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. # This is a base class for all asynchronous network operations performed -# by Squeezebox Server. +# by Logitech Media Server. use strict; diff --git a/Slim/Networking/Async/DNS.pm b/Slim/Networking/Async/DNS.pm index a88b17f624f..9abf694cec2 100644 --- a/Slim/Networking/Async/DNS.pm +++ b/Slim/Networking/Async/DNS.pm @@ -2,7 +2,7 @@ package Slim::Networking::Async::DNS; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Async/HTTP.pm b/Slim/Networking/Async/HTTP.pm index ccf1237c1e4..3d17419b499 100644 --- a/Slim/Networking/Async/HTTP.pm +++ b/Slim/Networking/Async/HTTP.pm @@ -2,7 +2,7 @@ package Slim::Networking::Async::HTTP; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Async/Socket.pm b/Slim/Networking/Async/Socket.pm index fff82c7520b..1d78608e58a 100644 --- a/Slim/Networking/Async/Socket.pm +++ b/Slim/Networking/Async/Socket.pm @@ -2,7 +2,7 @@ package Slim::Networking::Async::Socket; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Async/Socket/HTTP.pm b/Slim/Networking/Async/Socket/HTTP.pm index f6ea2f82343..6811af0e75b 100644 --- a/Slim/Networking/Async/Socket/HTTP.pm +++ b/Slim/Networking/Async/Socket/HTTP.pm @@ -2,7 +2,7 @@ package Slim::Networking::Async::Socket::HTTP; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Async/Socket/HTTPS.pm b/Slim/Networking/Async/Socket/HTTPS.pm index 3f03f7b1d88..00504af509d 100644 --- a/Slim/Networking/Async/Socket/HTTPS.pm +++ b/Slim/Networking/Async/Socket/HTTPS.pm @@ -2,7 +2,7 @@ package Slim::Networking::Async::Socket::HTTPS; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Async/Socket/UDP.pm b/Slim/Networking/Async/Socket/UDP.pm index 34503a82070..27b436cb95e 100644 --- a/Slim/Networking/Async/Socket/UDP.pm +++ b/Slim/Networking/Async/Socket/UDP.pm @@ -2,7 +2,7 @@ package Slim::Networking::Async::Socket::UDP; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Discovery.pm b/Slim/Networking/Discovery.pm index bde16e7c595..231f957f714 100644 --- a/Slim/Networking/Discovery.pm +++ b/Slim/Networking/Discovery.pm @@ -2,7 +2,7 @@ package Slim::Networking::Discovery; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Discovery/Players.pm b/Slim/Networking/Discovery/Players.pm index a91ec384e75..b501822c129 100644 --- a/Slim/Networking/Discovery/Players.pm +++ b/Slim/Networking/Discovery/Players.pm @@ -2,7 +2,7 @@ package Slim::Networking::Discovery::Players; # $Id: Players.pm 18532 2008-04-07 23:10:43Z andy $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -76,7 +76,7 @@ sub getPlayerList { =head2 fetch_players() -Poll the Squeezebox Server/SlimServers in our network for lists of connected players +Poll the servers in our network for lists of connected players =cut diff --git a/Slim/Networking/Discovery/Server.pm b/Slim/Networking/Discovery/Server.pm index b060b24393f..1f97b228bde 100644 --- a/Slim/Networking/Discovery/Server.pm +++ b/Slim/Networking/Discovery/Server.pm @@ -2,7 +2,7 @@ package Slim::Networking::Discovery::Server; # $Id: Server.pm 15258 2007-12-13 15:29:14Z mherger $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -33,7 +33,7 @@ Slim::Networking::Discovery::Server =head1 DESCRIPTION -This module implements a UDP discovery protocol, used by Squeezebox Server to discover other servers in the network. +This module implements a UDP discovery protocol, used by Logitech Media Server to discover other servers in the network. =head1 FUNCTIONS @@ -51,7 +51,7 @@ sub init { =head2 fetch_servers() -Poll the Squeezebox Server/SlimServers in our network +Poll the servers in our network =cut diff --git a/Slim/Networking/IO/Select.pm b/Slim/Networking/IO/Select.pm index efec70cc3ae..25dce927eec 100644 --- a/Slim/Networking/IO/Select.pm +++ b/Slim/Networking/IO/Select.pm @@ -2,7 +2,7 @@ package Slim::Networking::IO::Select; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -34,7 +34,7 @@ Slim::Utils::Select::addRead( $socket, \&callback ) =head1 DESCRIPTION -This module encapsulates all select() related code, handled by Squeezebox Server's main loop. +This module encapsulates all select() related code, handled by Logitech Media Server's main loop. Usually, you'll want to use higher such as L. diff --git a/Slim/Networking/Select.pm b/Slim/Networking/Select.pm index ff824e7facb..97a12ddfc7f 100644 --- a/Slim/Networking/Select.pm +++ b/Slim/Networking/Select.pm @@ -2,7 +2,7 @@ package Slim::Networking::Select; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -24,7 +24,7 @@ Slim::Utils::Select::addRead( $socket, \&callback ) =head1 DESCRIPTION -This module encapsulates all select() related code, handled by Squeezebox Server's main loop. +This module encapsulates all select() related code, handled by Logitech Media Server's main loop. Usually, you'll want to use higher such as L. diff --git a/Slim/Networking/SimpleAsyncHTTP.pm b/Slim/Networking/SimpleAsyncHTTP.pm index 0f1df7bddeb..b526dd181a6 100644 --- a/Slim/Networking/SimpleAsyncHTTP.pm +++ b/Slim/Networking/SimpleAsyncHTTP.pm @@ -2,14 +2,14 @@ package Slim::Networking::SimpleAsyncHTTP; # $Id$ -# Squeezebox Server Copyright 2003-2009 Logitech. +# Logitech Media Server Copyright 2003-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. -# this class provides non-blocking http requests from Squeezebox Server. +# this class provides non-blocking http requests from Logitech Media Server. # That is, use this class for your http requests to ensure that -# Squeezebox Server does not become unresponsive, or allow music to pause, +# Logitech Media Server does not become unresponsive, or allow music to pause, # while your code waits for a response # This class is intended for plugins and other code needing simply to @@ -674,7 +674,7 @@ $http->get("http://www.slimdevices.com"); =head1 DESCRIPTION -This class provides a way within the Squeezebox Server to make an http +This class provides a way within the Logitech Media Server to make an http request in an asynchronous, non-blocking way. This is important because the server will remain responsive and continue streaming audio while your code waits for the response. diff --git a/Slim/Networking/SliMP3/Protocol.pm b/Slim/Networking/SliMP3/Protocol.pm index caf4411abb1..cd787709cd3 100644 --- a/Slim/Networking/SliMP3/Protocol.pm +++ b/Slim/Networking/SliMP3/Protocol.pm @@ -1,6 +1,6 @@ package Slim::Networking::SliMP3::Protocol; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/SliMP3/Stream.pm b/Slim/Networking/SliMP3/Stream.pm index 3e15c7b8f73..11f382fa9d1 100644 --- a/Slim/Networking/SliMP3/Stream.pm +++ b/Slim/Networking/SliMP3/Stream.pm @@ -2,7 +2,7 @@ package Slim::Networking::SliMP3::Stream; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/Slimproto.pm b/Slim/Networking/Slimproto.pm index a08b5898771..1444708e431 100644 --- a/Slim/Networking/Slimproto.pm +++ b/Slim/Networking/Slimproto.pm @@ -2,7 +2,7 @@ package Slim::Networking::Slimproto; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Networking/UDP.pm b/Slim/Networking/UDP.pm index 6c39ae47efa..238d45eaa5f 100644 --- a/Slim/Networking/UDP.pm +++ b/Slim/Networking/UDP.pm @@ -2,7 +2,7 @@ package Slim::Networking::UDP; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -39,7 +39,7 @@ sub init { ) or do { # XXX - exiting in a deep sub is kinda bad. should propagate up. - logger('')->logdie("FATAL: There is already another copy of the Squeezebox Server running on this machine. ($!)"); + logger('')->logdie("FATAL: There is already another copy of the Logitech Media Server running on this machine. ($!)"); }; defined(Slim::Utils::Network::blocking($udpsock, 0)) || do { diff --git a/Slim/Networking/UPnP/ControlPoint.pm b/Slim/Networking/UPnP/ControlPoint.pm index c0d2d3b6992..c74a544010b 100644 --- a/Slim/Networking/UPnP/ControlPoint.pm +++ b/Slim/Networking/UPnP/ControlPoint.pm @@ -1,6 +1,6 @@ package Slim::Networking::UPnP::ControlPoint; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -79,7 +79,7 @@ MX: $mx $sock->set( args => $args ); # This socket will continue to live and receive events as - # long as Squeezebox Server is running + # long as the server is running Slim::Networking::Select::addRead( $sock, \&_readResult ); # send the search query diff --git a/Slim/Player/Boom.pm b/Slim/Player/Boom.pm index 076b5b3598b..aa2cc3c878e 100644 --- a/Slim/Player/Boom.pm +++ b/Slim/Player/Boom.pm @@ -1,6 +1,6 @@ package Slim::Player::Boom; -# Squeezebox Server Copyright (c) 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/CapabilitiesHelper.pm b/Slim/Player/CapabilitiesHelper.pm index 32b84bd3aea..c825ba4f48a 100644 --- a/Slim/Player/CapabilitiesHelper.pm +++ b/Slim/Player/CapabilitiesHelper.pm @@ -2,7 +2,7 @@ package Slim::Player::CapabilitiesHelper; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Client.pm b/Slim/Player/Client.pm index 24ce04208de..12bd48e3c30 100644 --- a/Slim/Player/Client.pm +++ b/Slim/Player/Client.pm @@ -2,7 +2,7 @@ package Slim::Player::Client; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Disconnected.pm b/Slim/Player/Disconnected.pm index 097bae118d0..eb0ffff9cf0 100644 --- a/Slim/Player/Disconnected.pm +++ b/Slim/Player/Disconnected.pm @@ -1,4 +1,4 @@ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/HTTP.pm b/Slim/Player/HTTP.pm index 2aeb4e54884..c63b214b133 100644 --- a/Slim/Player/HTTP.pm +++ b/Slim/Player/HTTP.pm @@ -1,4 +1,4 @@ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Pipeline.pm b/Slim/Player/Pipeline.pm index 2a364939f1e..b880c8786ae 100644 --- a/Slim/Player/Pipeline.pm +++ b/Slim/Player/Pipeline.pm @@ -2,7 +2,7 @@ package Slim::Player::Pipeline; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Player.pm b/Slim/Player/Player.pm index 0a25fad137c..231c8014c1a 100644 --- a/Slim/Player/Player.pm +++ b/Slim/Player/Player.pm @@ -1,6 +1,6 @@ package Slim::Player::Player; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Playlist.pm b/Slim/Player/Playlist.pm index 857269f400a..3fe0174eee2 100644 --- a/Slim/Player/Playlist.pm +++ b/Slim/Player/Playlist.pm @@ -1,6 +1,6 @@ package Slim::Player::Playlist; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/ProtocolHandlers.pm b/Slim/Player/ProtocolHandlers.pm index 00e4356c053..bd8ac828cdc 100644 --- a/Slim/Player/ProtocolHandlers.pm +++ b/Slim/Player/ProtocolHandlers.pm @@ -2,7 +2,7 @@ package Slim::Player::ProtocolHandlers; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Protocols/File.pm b/Slim/Player/Protocols/File.pm index 1effa53574f..be5d599c211 100644 --- a/Slim/Player/Protocols/File.pm +++ b/Slim/Player/Protocols/File.pm @@ -2,7 +2,7 @@ package Slim::Player::Protocols::File; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech, Vidur Apparao. +# Logitech Media Server Copyright 2001-2011 Logitech, Vidur Apparao. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Protocols/HTTP.pm b/Slim/Player/Protocols/HTTP.pm index 86b21486ec3..2ff92a1ac31 100644 --- a/Slim/Player/Protocols/HTTP.pm +++ b/Slim/Player/Protocols/HTTP.pm @@ -2,7 +2,7 @@ package Slim::Player::Protocols::HTTP; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech, Vidur Apparao. +# Logitech Media Server Copyright 2001-2011 Logitech, Vidur Apparao. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Protocols/MMS.pm b/Slim/Player/Protocols/MMS.pm index 1a924bd9bc5..5e0ae9eab32 100644 --- a/Slim/Player/Protocols/MMS.pm +++ b/Slim/Player/Protocols/MMS.pm @@ -2,7 +2,7 @@ package Slim::Player::Protocols::MMS; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech, Vidur Apparao. +# Logitech Media Server Copyright 2001-2011 Logitech, Vidur Apparao. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Receiver.pm b/Slim/Player/Receiver.pm index dde8c94d8d2..40528b1e45a 100644 --- a/Slim/Player/Receiver.pm +++ b/Slim/Player/Receiver.pm @@ -1,6 +1,6 @@ package Slim::Player::Receiver; -# Squeezebox Server Copyright (c) 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/ReplayGain.pm b/Slim/Player/ReplayGain.pm index 0a6cbe0402b..5fe5710dd71 100644 --- a/Slim/Player/ReplayGain.pm +++ b/Slim/Player/ReplayGain.pm @@ -2,7 +2,7 @@ package Slim::Player::ReplayGain; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/SB1SliMP3Sync.pm b/Slim/Player/SB1SliMP3Sync.pm index ef1207a011e..97bd26dd269 100644 --- a/Slim/Player/SB1SliMP3Sync.pm +++ b/Slim/Player/SB1SliMP3Sync.pm @@ -1,6 +1,6 @@ package Slim::Player::SB1SliMP3Sync; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/SLIMP3.pm b/Slim/Player/SLIMP3.pm index e7ddd9c5542..79d7134bdf3 100644 --- a/Slim/Player/SLIMP3.pm +++ b/Slim/Player/SLIMP3.pm @@ -1,4 +1,4 @@ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/SoftSqueeze.pm b/Slim/Player/SoftSqueeze.pm index e17266845e6..6b2a6df347f 100644 --- a/Slim/Player/SoftSqueeze.pm +++ b/Slim/Player/SoftSqueeze.pm @@ -1,6 +1,6 @@ package Slim::Player::SoftSqueeze; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Song.pm b/Slim/Player/Song.pm index 2ed1eda7ccd..62e58e43760 100644 --- a/Slim/Player/Song.pm +++ b/Slim/Player/Song.pm @@ -2,7 +2,7 @@ package Slim::Player::Song; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/SongStreamController.pm b/Slim/Player/SongStreamController.pm index 62f055914f6..85be8a2fe86 100644 --- a/Slim/Player/SongStreamController.pm +++ b/Slim/Player/SongStreamController.pm @@ -2,7 +2,7 @@ package Slim::Player::SongStreamController; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Source.pm b/Slim/Player/Source.pm index 1e1a7a0b76e..039298ef151 100644 --- a/Slim/Player/Source.pm +++ b/Slim/Player/Source.pm @@ -2,7 +2,7 @@ package Slim::Player::Source; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/SqueezePlay.pm b/Slim/Player/SqueezePlay.pm index f2131320d39..100e8a143b7 100644 --- a/Slim/Player/SqueezePlay.pm +++ b/Slim/Player/SqueezePlay.pm @@ -1,6 +1,6 @@ package Slim::Player::SqueezePlay; -# Squeezebox Server Copyright (c) 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/SqueezeSlave.pm b/Slim/Player/SqueezeSlave.pm index fe5de0ef00e..af029b54058 100644 --- a/Slim/Player/SqueezeSlave.pm +++ b/Slim/Player/SqueezeSlave.pm @@ -2,7 +2,7 @@ package Slim::Player::SqueezeSlave; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Squeezebox.pm b/Slim/Player/Squeezebox.pm index 89d7a56bae0..126c7484f21 100644 --- a/Slim/Player/Squeezebox.pm +++ b/Slim/Player/Squeezebox.pm @@ -1,6 +1,6 @@ package Slim::Player::Squeezebox; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Squeezebox1.pm b/Slim/Player/Squeezebox1.pm index 5f12acdc55b..8da02545fd7 100644 --- a/Slim/Player/Squeezebox1.pm +++ b/Slim/Player/Squeezebox1.pm @@ -2,7 +2,7 @@ package Slim::Player::Squeezebox1; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Squeezebox2.pm b/Slim/Player/Squeezebox2.pm index 6a6a1bb6a0c..42a4bc8b42d 100644 --- a/Slim/Player/Squeezebox2.pm +++ b/Slim/Player/Squeezebox2.pm @@ -2,7 +2,7 @@ package Slim::Player::Squeezebox2; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -862,7 +862,7 @@ sub audio_outputs_enable { } -# The following settings are sync'd between the player firmware and Squeezebox Server +# The following settings are sync'd between the player firmware and Logitech Media Server our $pref_settings = { 'playername' => { firmwareid => 0, @@ -949,7 +949,7 @@ sub setPlayerSetting { } } -# Allow the firmware to update a pref in Squeezebox Server +# Allow the firmware to update a pref in Logitech Media Server sub playerSettingsFrame { my $client = shift; my $data_ref = shift; diff --git a/Slim/Player/StreamingController.pm b/Slim/Player/StreamingController.pm index 80a1cf0d42f..a7041bc2494 100644 --- a/Slim/Player/StreamingController.pm +++ b/Slim/Player/StreamingController.pm @@ -2,7 +2,7 @@ package Slim::Player::StreamingController; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Sync.pm b/Slim/Player/Sync.pm index 91725560852..0ab62ec72f1 100644 --- a/Slim/Player/Sync.pm +++ b/Slim/Player/Sync.pm @@ -2,7 +2,7 @@ package Slim::Player::Sync; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/TranscodingHelper.pm b/Slim/Player/TranscodingHelper.pm index 943abf15170..10da2ed7c28 100644 --- a/Slim/Player/TranscodingHelper.pm +++ b/Slim/Player/TranscodingHelper.pm @@ -2,7 +2,7 @@ package Slim::Player::TranscodingHelper; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Player/Transporter.pm b/Slim/Player/Transporter.pm index 350206a4d1c..1b03d4e8e7f 100644 --- a/Slim/Player/Transporter.pm +++ b/Slim/Player/Transporter.pm @@ -1,8 +1,8 @@ package Slim::Player::Transporter; -# $Id$ +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Player/Transporter.pm 78224 2011-06-22T16:26:39.511256Z mherger $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Amazon/install.xml b/Slim/Plugin/Amazon/install.xml index d09963ed5e4..59a4771978d 100644 --- a/Slim/Plugin/Amazon/install.xml +++ b/Slim/Plugin/Amazon/install.xml @@ -11,7 +11,7 @@ plugins/Amazon/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/AppGallery/install.xml b/Slim/Plugin/AppGallery/install.xml index b39d9739a26..a7313e20ef5 100644 --- a/Slim/Plugin/AppGallery/install.xml +++ b/Slim/Plugin/AppGallery/install.xml @@ -12,7 +12,7 @@ 2 1 - Squeezebox Server + Logitech Media Server 7.4 * diff --git a/Slim/Plugin/AudioScrobbler/PlayerSettings.pm b/Slim/Plugin/AudioScrobbler/PlayerSettings.pm index f8db8d08c65..28af2c31e51 100644 --- a/Slim/Plugin/AudioScrobbler/PlayerSettings.pm +++ b/Slim/Plugin/AudioScrobbler/PlayerSettings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::AudioScrobbler::PlayerSettings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/AudioScrobbler/Plugin.pm b/Slim/Plugin/AudioScrobbler/Plugin.pm index 9ae5c48e21c..a549a8268be 100644 --- a/Slim/Plugin/AudioScrobbler/Plugin.pm +++ b/Slim/Plugin/AudioScrobbler/Plugin.pm @@ -5,7 +5,7 @@ package Slim::Plugin::AudioScrobbler::Plugin; # This plugin handles submission of tracks to Last.fm's # Audioscrobbler service. -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/AudioScrobbler/Settings.pm b/Slim/Plugin/AudioScrobbler/Settings.pm index 6174bfddcfc..8be7e05687a 100644 --- a/Slim/Plugin/AudioScrobbler/Settings.pm +++ b/Slim/Plugin/AudioScrobbler/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::AudioScrobbler::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/AudioScrobbler/install.xml b/Slim/Plugin/AudioScrobbler/install.xml index c92e96d69ec..1e28d7a2cf0 100644 --- a/Slim/Plugin/AudioScrobbler/install.xml +++ b/Slim/Plugin/AudioScrobbler/install.xml @@ -12,7 +12,7 @@ plugins/AudioScrobbler/settings/basic.html 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/AudioScrobbler/strings.txt b/Slim/Plugin/AudioScrobbler/strings.txt index 24755985222..d637df5e151 100644 --- a/Slim/Plugin/AudioScrobbler/strings.txt +++ b/Slim/Plugin/AudioScrobbler/strings.txt @@ -134,19 +134,19 @@ SETUP_PLUGIN_AUDIOSCROBBLER_ENABLE_SCROBBLE_NO SV Nej, rapportera inte spelade spår till Last.fm. PLUGIN_AUDIOSCROBBLER_BANNED - CS Tato verze Squeezebox Server byla zakázána prostřednictvím Last.fm, aktualizujte laskavě na novější verzi. - DA Denne version af Squeezebox Server ser ud til at være udelukket af Last.fm. Du bør opgradere til en nyere version. - DE Last.fm scheint diese Version von Squeezebox Server nicht zuzulassen. Aktualisieren Sie auf eine neuere Version. - EN This version of Squeezebox Server appears to have been banned by Last.fm, please upgrade to a newer version. - ES Parece que Last.fm ha prohibido esta versión de Squeezebox Server. Actualícela a una versión más reciente. - FI Last.fm tuntuu kieltäneen Squeezebox Serverin tämän version. Päivitä uudempaan versioon. - FR Cette version du Squeezebox Server semble avoir été bannie par Last.fm. Veuillez effectuer une mise à niveau vers une version plus récente. - IT È possibile che questa versione di Squeezebox Server non sia supportata in Last.fm. Eseguire l'aggiornamento a una versione successiva. - NL Deze versie van Squeezebox Server wordt blijkbaar niet meer door Last.fm ondersteund. Upgrade naar een nieuwere versie. - NO Det ser ut til at Last.fm har blokkert denne versjonen av Squeezebox Server. Du bør oppgradere til en nyere versjon. - PL Ta wersja programu Squeezebox Server jest blokowana przez usługę Last.fm; uaktualnij go do nowszej wersji. - RU По-видимому, эта версия Squeezebox Server запрещена на Last.fm. Обновите версию. - SV Den här versionen av Squeezebox Server verkar ha spärrats av Last.fm. Uppgradera till senare version. + CS Tato verze Logitech Media Server byla zakázána prostřednictvím Last.fm, aktualizujte laskavě na novější verzi. + DA Denne version af Logitech Media Server ser ud til at være udelukket af Last.fm. Du bør opgradere til en nyere version. + DE Last.fm scheint diese Version von Logitech Media Server nicht zuzulassen. Aktualisieren Sie auf eine neuere Version. + EN This version of Logitech Media Server appears to have been banned by Last.fm, please upgrade to a newer version. + ES Parece que Last.fm ha prohibido esta versión de Logitech Media Server. Actualícela a una versión más reciente. + FI Last.fm tuntuu kieltäneen Logitech Media Serverin tämän version. Päivitä uudempaan versioon. + FR Cette version du Logitech Media Server semble avoir été bannie par Last.fm. Veuillez effectuer une mise à niveau vers une version plus récente. + IT È possibile che questa versione di Logitech Media Server non sia supportata in Last.fm. Eseguire l'aggiornamento a una versione successiva. + NL Deze versie van Logitech Media Server wordt blijkbaar niet meer door Last.fm ondersteund. Upgrade naar een nieuwere versie. + NO Det ser ut til at Last.fm har blokkert denne versjonen av Logitech Media Server. Du bør oppgradere til en nyere versjon. + PL Ta wersja programu Logitech Media Server jest blokowana przez usługę Last.fm; uaktualnij go do nowszej wersji. + RU По-видимому, эта версия Logitech Media Server запрещена на Last.fm. Обновите версию. + SV Den här versionen av Logitech Media Server verkar ha spärrats av Last.fm. Uppgradera till senare version. PLUGIN_AUDIOSCROBBLER_BADAUTH CS Neplatné přihlašovací jméno nebo heslo k Last.fm diff --git a/Slim/Plugin/CLI/Plugin.pm b/Slim/Plugin/CLI/Plugin.pm index 10da6abb3a9..b1153ce94ca 100644 --- a/Slim/Plugin/CLI/Plugin.pm +++ b/Slim/Plugin/CLI/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::CLI::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/CLI/Settings.pm b/Slim/Plugin/CLI/Settings.pm index 67768c1bfc5..ea18fbaa648 100644 --- a/Slim/Plugin/CLI/Settings.pm +++ b/Slim/Plugin/CLI/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::CLI::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/CLI/install.xml b/Slim/Plugin/CLI/install.xml index 8f78eda96ef..f06c7bf2a2a 100644 --- a/Slim/Plugin/CLI/install.xml +++ b/Slim/Plugin/CLI/install.xml @@ -16,7 +16,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/CLI/strings.txt b/Slim/Plugin/CLI/strings.txt index d3acc485a48..ea328cff5dc 100644 --- a/Slim/Plugin/CLI/strings.txt +++ b/Slim/Plugin/CLI/strings.txt @@ -26,7 +26,7 @@ PLUGIN_CLI_DESC ES El complemento de interfaz de línea de comandos permite el control remoto del software y de los reproductores Squeezebox a través de una conexión TCP/IP mediante, por ejemplo, un sistema de domótica de otro fabricante como AMX o Crestron. FI Komentorivikäyttöliittymälaajennuksen avulla Squeezeboxin ohjelmistoa ja soittimia voidaan kauko-ohjata TCP/IP-yhteyden välityksellä, esimerkiksi AMX:n, Crestronin tai jonkin muun kolmannen osapuolen automaatiojärjestelmän avulla. FR Le plugin d'interface de ligne de commande permet de contrôler le logiciel Squeezebox et les platines à distance par le biais d'une connexion TCP/IP, par exemple par un système d'automatisation tiers, tel qu'AMX ou Crestron. - HE יישום ה-Plugin‏ 'ממשק שורת פקודה' מאפשר שליטה מרחוק ב-Squeezebox Server וב-Squeezebox באמצעות קישור TCP/IP, לדוגמה, על-ידי מערכת אוטומציה של צד שלישי כגון AMX או Crestron. + HE יישום ה-Plugin‏ 'ממשק שורת פקודה' מאפשר שליטה מרחוק ב-Logitech Media Server וב-Squeezebox באמצעות קישור TCP/IP, לדוגמה, על-ידי מערכת אוטומציה של צד שלישי כגון AMX או Crestron. IT Il plugin dell'interfaccia della riga di comando consente di controllare Squeezebox e i lettori in remoto su una connessione TCP/IP mediante, ad esempio, un sistema di automatizzazione di terze parti, quale AMX o Crestron. NL Dankzij de plug-in van de opdrachtregelinterface is het mogelijk om de Squeezebox-software en systemen op afstand te bedienen via een TCP/IP-verbinding, bijvoorbeeld door een automatiseringssysteem van een derde partij zoals AMX of Creston. NO Med kommandolinjegrensesnittet kan Squeezebox-programvaren og spillerne kontrolleres eksternt via en TCP/IP-tilkopling, for eksempel av et tredjeparts automatiseringssystem som AMX eller Crestron. diff --git a/Slim/Plugin/Classical/install.xml b/Slim/Plugin/Classical/install.xml index 24efb78a39a..593980e0c40 100644 --- a/Slim/Plugin/Classical/install.xml +++ b/Slim/Plugin/Classical/install.xml @@ -11,7 +11,7 @@ plugins/Classical/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/DateTime/Plugin.pm b/Slim/Plugin/DateTime/Plugin.pm index 3879d612493..35430215c27 100644 --- a/Slim/Plugin/DateTime/Plugin.pm +++ b/Slim/Plugin/DateTime/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::DateTime::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/DateTime/Settings.pm b/Slim/Plugin/DateTime/Settings.pm index 1de78620af4..6608ae23f30 100644 --- a/Slim/Plugin/DateTime/Settings.pm +++ b/Slim/Plugin/DateTime/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::DateTime::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/DateTime/install.xml b/Slim/Plugin/DateTime/install.xml index 253da508c93..a1847c52d16 100644 --- a/Slim/Plugin/DateTime/install.xml +++ b/Slim/Plugin/DateTime/install.xml @@ -15,7 +15,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/DateTime/strings.txt b/Slim/Plugin/DateTime/strings.txt index 6d2bbc11a1c..21151eb7820 100644 --- a/Slim/Plugin/DateTime/strings.txt +++ b/Slim/Plugin/DateTime/strings.txt @@ -51,34 +51,34 @@ SETUP_GROUP_DATETIME_DESC SV De här inställningar styr hur skärmsläckaren med datum och tid fungerar SETUP_GROUP_DATETIME_DEFAULTTIME - CS Výchozí nastavení Squeezebox Server - DA Squeezebox Server standard - DE Squeezebox Server-Standard - EN Squeezebox Server Default - ES Predeterminado de Squeezebox Server - FI Squeezebox Server -oletus + CS Výchozí nastavení server + DA Server standard + DE Server-Standard + EN Server Default + ES Predeterminado de Logitech Media Server + FI Server -oletus FR Défaut serveur - HE ברירת המחדל של Squeezebox Server - IT Impostazioni predefinite di Squeezebox Server - NL Standaardinstellingen van Squeezebox Server - NO Squeezebox Server-standard - PL Domyślny program Squeezebox Server - RU Squeezebox Server по умолчанию - SV Squeezebox Server-standard + HE ברירת המחדל של Logitech Media Server + IT Impostazioni predefinite di server + NL Standaardinstellingen van Logitech Media Server + NO Server-standard + PL Domyślny program Logitech Media Server + RU Server по умолчанию + SV Server-standard SETUP_GROUP_DATETIME_DEFAULTDATE - CS Výchozí nastavení Squeezebox Server - DA Squeezebox Server standard - DE Squeezebox Server-Standard - EN Squeezebox Server Default - ES Predeterminado de Squeezebox Server - FI Squeezebox Server -oletus + CS Výchozí nastavení server + DA Server standard + DE Server-Standard + EN Server Default + ES Predeterminado de Logitech Media Server + FI Server -oletus FR Défaut serveur - HE ברירת המחדל של Squeezebox Server - IT Impostazioni predefinite di Squeezebox Server - NL Standaardinstellingen van Squeezebox Server - NO Squeezebox Server-standard - PL Domyślny program Squeezebox Server - RU Squeezebox Server по умолчанию - SV Squeezebox Server-standard + HE ברירת המחדל של Logitech Media Server + IT Impostazioni predefinite di server + NL Standaardinstellingen van Logitech Media Server + NO Server-standard + PL Domyślny program Logitech Media Server + RU Server по умолчанию + SV Server-standard diff --git a/Slim/Plugin/Deezer/install.xml b/Slim/Plugin/Deezer/install.xml index d61f356da3f..0b269524a22 100644 --- a/Slim/Plugin/Deezer/install.xml +++ b/Slim/Plugin/Deezer/install.xml @@ -11,7 +11,7 @@ plugins/Deezer/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/DigitalInput/Plugin.pm b/Slim/Plugin/DigitalInput/Plugin.pm index dd88248dfd5..1b08123dc2a 100644 --- a/Slim/Plugin/DigitalInput/Plugin.pm +++ b/Slim/Plugin/DigitalInput/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::DigitalInput::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/DigitalInput/ProtocolHandler.pm b/Slim/Plugin/DigitalInput/ProtocolHandler.pm index fc39f8a8a5b..89974600256 100644 --- a/Slim/Plugin/DigitalInput/ProtocolHandler.pm +++ b/Slim/Plugin/DigitalInput/ProtocolHandler.pm @@ -2,7 +2,7 @@ package Slim::Plugin::DigitalInput::ProtocolHandler; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/DigitalInput/install.xml b/Slim/Plugin/DigitalInput/install.xml index a2fec16f80c..3de73211f1d 100644 --- a/Slim/Plugin/DigitalInput/install.xml +++ b/Slim/Plugin/DigitalInput/install.xml @@ -14,7 +14,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Extensions/install.xml b/Slim/Plugin/Extensions/install.xml index 2cb448bee93..c5243b5adb7 100644 --- a/Slim/Plugin/Extensions/install.xml +++ b/Slim/Plugin/Extensions/install.xml @@ -10,7 +10,7 @@ http://www.mysqueezebox.com/support plugins/Extensions/settings/basic.html - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/Extensions/strings.txt b/Slim/Plugin/Extensions/strings.txt index e73dea98e7e..24cf4238225 100644 --- a/Slim/Plugin/Extensions/strings.txt +++ b/Slim/Plugin/Extensions/strings.txt @@ -16,17 +16,17 @@ PLUGIN_EXTENSIONS PLUGIN_EXTENSIONS_DESC CS Stahovač doplňků umožňuje automatické stahování a instalaci volitelných vlastností Squezebox server. DA Du kan vælge om der automatisk skal hentes og installeres en række udvidelser til Squeezebox-serveren. - DE Mit dem Erweiterungs-Downloader werden optionale Funktionen für Squeezebox Server automatisch heruntergeladen und installiert. - EN Extension downloader allows automated download and installation of optional features for Squeezebox server. + DE Mit dem Erweiterungs-Downloader werden optionale Funktionen für Logitech Media Server automatisch heruntergeladen und installiert. + EN Extension downloader allows automated download and installation of optional features for Logitech Media Server. ES El Descargador de extensiones permite descargar e instalar automáticamente funciones opcionales para el servidor Squeezebox. FI Laajennusten latausjärjestelmä saattaa ladata ja asentaa automaattisesti erilaisia lisäosia Squeezebox-palvelimelle. - FR L'outil de téléchargement d'extensions permet le téléchargement et l'installation automatisés de fonctionnalités optionnelles pour Squeezebox Server. - IT L'utilità di download delle estensioni consente il download e l'installazione automatici di funzionalità facoltative per Squeezebox Server. - NL Met de extensiedownloader kunnen optionele functies voor Squeezebox Server automatisch worden gedownload en geïnstalleerd. - NO Med Nedlasting av utvidelser kan du laste ned en rekke valgfrie funksjoner for Squeezebox Server helt gratis og helt automatisk. + FR L'outil de téléchargement d'extensions permet le téléchargement et l'installation automatisés de fonctionnalités optionnelles pour Logitech Media Server. + IT L'utilità di download delle estensioni consente il download e l'installazione automatici di funzionalità facoltative per Logitech Media Server. + NL Met de extensiedownloader kunnen optionele functies voor Logitech Media Server automatisch worden gedownload en geïnstalleerd. + NO Med Nedlasting av utvidelser kan du laste ned en rekke valgfrie funksjoner for Logitech Media Server helt gratis og helt automatisk. PL Moduł pobierania dodatków umożliwia automatyczne pobieranie i instalację opcjonalnych funkcji serwera Squeezebox. RU Загрузчик расширений позволяет автоматически загружать и устанавливать дополнительные средства для сервера Squeezebox. - SV Med hjälp av nedladdningsprogrammet kan du ladda ned olika tillägg till Squeezebox Server. + SV Med hjälp av nedladdningsprogrammet kan du ladda ned olika tillägg till Logitech Media Server. PLUGIN_EXTENSIONS_REPOS CS Doplňkové archívy @@ -74,19 +74,19 @@ PLUGIN_EXTENSIONS_REPOS_WARNING SV Obs! Eftersom servern laddar ned program automatiskt från den servern du anger är det viktigt att du litar på databasens ägare. PLUGIN_EXTENSIONS_PLUGINS - CS Pluginy Squeezebox Server - DA Udvidelsesmoduler til Squeezebox Server - DE Squeezebox Server-Plugins - EN Squeezebox Server Plugins - ES Complementos de Squeezebox Server - FI Squeezebox Serverin laajennukset - FR Plugins Squeezebox Server - IT Plugin di Squeezebox Server - NL Invoegtoepassingen voor Squeezebox Server - NO Plugin-moduler for Squeezebox Server - PL Dodatki programu Squeezebox Server - RU Плагины Squeezebox Server - SV Plugin-program till Squeezebox Server + CS Pluginy Logitech Media Server + DA Udvidelsesmoduler til Logitech Media Server + DE Logitech Media Server-Plugins + EN Logitech Media Server Plugins + ES Complementos de Logitech Media Server + FI Logitech Media Serverin laajennukset + FR Plugins Logitech Media Server + IT Plugin di Logitech Media Server + NL Invoegtoepassingen voor Logitech Media Server + NO Plugin-moduler for Logitech Media Server + PL Dodatki programu Logitech Media Server + RU Плагины Logitech Media Server + SV Plugin-program till Logitech Media Server PLUGIN_EXTENSIONS_PLUGINS_UPGRADE CS Upgradovat Plugin na novou verzi @@ -164,19 +164,19 @@ PLUGIN_EXTENSIONS_PLUGIN_MANUAL_UNINSTALL SV (%s) har redan installerats manuellt – ta bort först PLUGIN_EXTENSIONS_RESTART_MSG - CS Restartujte prosím Squeezebox Server k uskutečnění změn. - DA Du skal genstarte Squeezebox Server for at ændringerne kan træde i kraft. - DE Squeezebox Server muss neu gestartet werden, damit die Änderungen in Kraft treten. - EN Please restart Squeezebox Server for the changes to take effect. - ES Reinicie Squeezebox Server para que los cambios entren en vigor. - FI Käynnistä Squeezebox Server uudelleen, jotta muutokset tulevat voimaan. - FR Redémarrez le Squeezebox Server pour appliquer les modifications. - IT Per applicare le modifiche, è necessario riavviare Squeezebox Server. - NL Start Squeezebox Server opnieuw om de wijzigingen door te voeren. - NO Du må starte Squeezebox Server på nytt for at endringene skal tre i kraft. - PL Aby wprowadzić zmiany, należy ponownie uruchomić program Squeezebox Server. - RU Перезапустите Squeezebox Server, чтобы изменения вступили в силу. - SV Ändringarna träder i kraft när du startar om Squeezebox Server. + CS Restartujte prosím Logitech Media Server k uskutečnění změn. + DA Du skal genstarte Logitech Media Server for at ændringerne kan træde i kraft. + DE Logitech Media Server muss neu gestartet werden, damit die Änderungen in Kraft treten. + EN Please restart Logitech Media Server for the changes to take effect. + ES Reinicie Logitech Media Server para que los cambios entren en vigor. + FI Käynnistä Logitech Media Server uudelleen, jotta muutokset tulevat voimaan. + FR Redémarrez le Logitech Media Server pour appliquer les modifications. + IT Per applicare le modifiche, è necessario riavviare Logitech Media Server. + NL Start Logitech Media Server opnieuw om de wijzigingen door te voeren. + NO Du må starte Logitech Media Server på nytt for at endringene skal tre i kraft. + PL Aby wprowadzić zmiany, należy ponownie uruchomić program Logitech Media Server. + RU Перезапустите Logitech Media Server, чтобы изменения вступили в силу. + SV Ändringarna träder i kraft när du startar om Logitech Media Server. PLUGIN_EXTENSIONS_REPO_ERROR CS Špatný archív @@ -299,16 +299,16 @@ PLUGIN_EXTENSIONS_AUTO SV Uppdatera plugin-program automatiskt PLUGIN_EXTENSIONS_AUTO_DESC - CS Umožnit, aby Squeezebox Server automaticky kontroloval aktualizace nainstalovaných zásuvných modulů a stahoval je tak, aby byly připraveny k použití při příštím spuštění serveru. Pokud tato možnost není vybrána, můžete zásuvné moduly aktualizovat ručně prostřednictvím této stránky nastavení. + CS Umožnit, aby Logitech Media Server automaticky kontroloval aktualizace nainstalovaných zásuvných modulů a stahoval je tak, aby byly připraveny k použití při příštím spuštění serveru. Pokud tato možnost není vybrána, můžete zásuvné moduly aktualizovat ručně prostřednictvím této stránky nastavení. DA Du kan indstille Squeezebox-serveren til automatisk at søge efter opdateringer til de installerede udvidelsesmoduler og hente dem, så de er klar til at blive brugt næste gang serveren startes. Hvis du ikke vælger denne mulighed, kan du opdatere udvidelsesmodulerne manuelt via denne side. - DE Aktivieren Sie die Option für die automatische Suche nach Updates für installierte Plugins und das Herunterladen dieser Updates durch den Squeezebox Server, sodass sie beim nächsten Start des Servers zur Verfügung stehen. Wenn diese Option nicht aktiviert ist, können Sie die Plugins über diese Seite für Einstellungen manuell aktualisieren. - EN Allow the Squeezebox server to automatically check for updates to installed plugins and download them ready to be used when the server is next restarted. If this option is not selected you may manually update plugins through this settings page. - ES Permite a Squeezebox Server buscar actualizaciones para los complementos instalados y descargarlas automáticamente para que estén listas la próxima vez que se reinicie el servidor. Si no selecciona esta opción, podrá actualizar los complementos manualmente a través de la página de configuración. - FI Salli Squeezebox Serverin hakea asennettujen laajennusten päivitykset automaattisesti ja ladata ne, jotta ne ovat käyttövalmiita seuraavalla palvelimen käynnistyskerralla. Jos tämä asetus ei ole valittuna, voit päivittää laajennukset manuaalisesti Asetukset-sivun kautta. - FR Autoriser le Squeezebox Server à rechercher automatiquement les mises à jour des plugins installés et à les télécharger de manière à être appliqués au redémarrage du serveur. Si cette option n'est pas sélectionnée, vous pouvez mettre à jour les plugins manuellement en accédant à cette page de paramètres. - IT Consente a Squeezebox Server di verificare automaticamente la disponibilità di aggiornamenti ai plugin installati e di scaricarli ed utilizzarli la prossima volta che si riavvia il server. Se questa opzione non è selezionata, è possibile aggiornare i plugin manualmente tramite questa pagina di impostazioni. - NL Squeezebox Server toestaan automatisch op updates voor geïnstalleerde plug-ins te controleren en deze te downloaden voor gebruik wanneer de server opnieuw wordt opgestart. Als deze optie niet is geselecteerd, kun je plug-ins handmatig bijwerken via deze instellingenpagina. - NO La Squeezebox Server se etter oppdateringer for installerte plugin-moduler automatisk, og laste dem ned så de kan brukes neste gang serveren startes på nytt. Hvis du ikke merker av for dette, kan du oppdatere plugin-modulene manuelt på denne siden. + DE Aktivieren Sie die Option für die automatische Suche nach Updates für installierte Plugins und das Herunterladen dieser Updates durch den Logitech Media Server, sodass sie beim nächsten Start des Servers zur Verfügung stehen. Wenn diese Option nicht aktiviert ist, können Sie die Plugins über diese Seite für Einstellungen manuell aktualisieren. + EN Allow the Logitech Media Server to automatically check for updates to installed plugins and download them ready to be used when the server is next restarted. If this option is not selected you may manually update plugins through this settings page. + ES Permite a Logitech Media Server buscar actualizaciones para los complementos instalados y descargarlas automáticamente para que estén listas la próxima vez que se reinicie el servidor. Si no selecciona esta opción, podrá actualizar los complementos manualmente a través de la página de configuración. + FI Salli Logitech Media Serverin hakea asennettujen laajennusten päivitykset automaattisesti ja ladata ne, jotta ne ovat käyttövalmiita seuraavalla palvelimen käynnistyskerralla. Jos tämä asetus ei ole valittuna, voit päivittää laajennukset manuaalisesti Asetukset-sivun kautta. + FR Autoriser le Logitech Media Server à rechercher automatiquement les mises à jour des plugins installés et à les télécharger de manière à être appliqués au redémarrage du serveur. Si cette option n'est pas sélectionnée, vous pouvez mettre à jour les plugins manuellement en accédant à cette page de paramètres. + IT Consente a Logitech Media Server di verificare automaticamente la disponibilità di aggiornamenti ai plugin installati e di scaricarli ed utilizzarli la prossima volta che si riavvia il server. Se questa opzione non è selezionata, è possibile aggiornare i plugin manualmente tramite questa pagina di impostazioni. + NL Logitech Media Server toestaan automatisch op updates voor geïnstalleerde plug-ins te controleren en deze te downloaden voor gebruik wanneer de server opnieuw wordt opgestart. Als deze optie niet is geselecteerd, kun je plug-ins handmatig bijwerken via deze instellingenpagina. + NO La Logitech Media Server se etter oppdateringer for installerte plugin-moduler automatisk, og laste dem ned så de kan brukes neste gang serveren startes på nytt. Hvis du ikke merker av for dette, kan du oppdatere plugin-modulene manuelt på denne siden. PL Zezwala serwerowi Squeezebox na automatyczne wyszukiwanie aktualizacji zainstalowanych dodatków oraz ich pobieranie i instalowanie. Jeśli ta opcja nie zostanie zaznaczona, na tej stronie ustawień dodatki można zaktualizować ręcznie. RU Разрешить серверу Squeezebox автоматически проверять наличие обновлений для установленных подключаемых модулей и загружать их для использования при следующем запуске сервера. Если этот параметр не выбран, можно загружать подключаемые модули вручную с этой страницы настройки. SV Tillåt Squeezebox-servern att automatiskt söka efter uppdateringar till installerade plugin-program och ladda ned den som är redo att användas när servern startas om nästa gång. Om det här alternativet inte väljs kan du uppdatera plugin-programmen manuellt via den här inställningssidan. diff --git a/Slim/Plugin/Facebook/install.xml b/Slim/Plugin/Facebook/install.xml index a7253ebad8e..2e208e91f25 100644 --- a/Slim/Plugin/Facebook/install.xml +++ b/Slim/Plugin/Facebook/install.xml @@ -11,7 +11,7 @@ plugins/Facebook/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.4 * diff --git a/Slim/Plugin/Favorites/Playlist.pm b/Slim/Plugin/Favorites/Playlist.pm index b47c2d8a56b..f09b849d531 100644 --- a/Slim/Plugin/Favorites/Playlist.pm +++ b/Slim/Plugin/Favorites/Playlist.pm @@ -2,7 +2,7 @@ package Slim::Plugin::Favorites::Playlist; # $Id$ -# Class to allow importing of playlist formats understood by Squeezebox Server into opml files +# Class to allow importing of playlist formats understood by Logitech Media Server into opml files use File::Basename qw(dirname); use File::Spec::Functions qw(catdir); diff --git a/Slim/Plugin/Favorites/Plugin.pm b/Slim/Plugin/Favorites/Plugin.pm index 84670d8161f..0ef5fa104b5 100755 --- a/Slim/Plugin/Favorites/Plugin.pm +++ b/Slim/Plugin/Favorites/Plugin.pm @@ -9,7 +9,7 @@ package Slim::Plugin::Favorites::Plugin; # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2005-2009 Logitech. +# Logitech Media Server Copyright 2005-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Favorites/Settings.pm b/Slim/Plugin/Favorites/Settings.pm index 6132e553e7d..247e0c8c912 100644 --- a/Slim/Plugin/Favorites/Settings.pm +++ b/Slim/Plugin/Favorites/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::Favorites::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Favorites/install.xml b/Slim/Plugin/Favorites/install.xml index 74f1bbc8575..35134492abe 100644 --- a/Slim/Plugin/Favorites/install.xml +++ b/Slim/Plugin/Favorites/install.xml @@ -17,7 +17,7 @@ 1 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Flickr/install.xml b/Slim/Plugin/Flickr/install.xml index d372fddfb96..5b46c216be1 100644 --- a/Slim/Plugin/Flickr/install.xml +++ b/Slim/Plugin/Flickr/install.xml @@ -11,7 +11,7 @@ plugins/Flickr/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.4 * diff --git a/Slim/Plugin/InfoBrowser/Plugin.pm b/Slim/Plugin/InfoBrowser/Plugin.pm index 8b7752acb47..ac2ae0849cc 100644 --- a/Slim/Plugin/InfoBrowser/Plugin.pm +++ b/Slim/Plugin/InfoBrowser/Plugin.pm @@ -1,11 +1,11 @@ package Slim::Plugin::InfoBrowser::Plugin; -# InfoBrowser - an extensible information parser for Squeezebox Server 7.0 +# InfoBrowser - an extensible information parser for Logitech Media Server 7.0 # # $Id$ # # InfoBrowser provides a framework to use Squeezebox Server's xmlbrowser to fetch remote content and convert it into a format -# which can be displayed via the Squeezebox Server web interface, cli for jive or another cli client or via the player display. +# which can be displayed via the server web interface, cli for jive or another cli client or via the player display. # # The top level menu is defined by an opml file stored in playlistdir or cachedir. It is created dynamically from any opml # files found in the plugin dir (Slim/Plugin/InfoBrowser) and the Addon dir (Plugins/InfoBrowserAddons) and any of their subdirs. diff --git a/Slim/Plugin/InfoBrowser/install.xml b/Slim/Plugin/InfoBrowser/install.xml index 06ad8536e6f..d3ed60463a7 100644 --- a/Slim/Plugin/InfoBrowser/install.xml +++ b/Slim/Plugin/InfoBrowser/install.xml @@ -13,7 +13,7 @@ plugins/InfoBrowser/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/InternetRadio/install.xml b/Slim/Plugin/InternetRadio/install.xml index a31f9a81d84..c33ca47ab32 100644 --- a/Slim/Plugin/InternetRadio/install.xml +++ b/Slim/Plugin/InternetRadio/install.xml @@ -12,7 +12,7 @@ http://www.mysqueezebox.com/support 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/JiveExtras/install.xml b/Slim/Plugin/JiveExtras/install.xml index 6d3cb89aeb7..f1593268553 100644 --- a/Slim/Plugin/JiveExtras/install.xml +++ b/Slim/Plugin/JiveExtras/install.xml @@ -10,7 +10,7 @@ http://www.mysqueezebox.com/support plugins/JiveExtras/settings/basic.html - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/LMA/install.xml b/Slim/Plugin/LMA/install.xml index 494f4f3e284..570701b59af 100644 --- a/Slim/Plugin/LMA/install.xml +++ b/Slim/Plugin/LMA/install.xml @@ -15,7 +15,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/LastFM/install.xml b/Slim/Plugin/LastFM/install.xml index 1ee262060e9..5cb08c08320 100644 --- a/Slim/Plugin/LastFM/install.xml +++ b/Slim/Plugin/LastFM/install.xml @@ -11,7 +11,7 @@ plugins/LastFM/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0 * diff --git a/Slim/Plugin/LineIn/Plugin.pm b/Slim/Plugin/LineIn/Plugin.pm index 16f8b15fc77..f2811e79f7d 100644 --- a/Slim/Plugin/LineIn/Plugin.pm +++ b/Slim/Plugin/LineIn/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::LineIn::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/LineIn/ProtocolHandler.pm b/Slim/Plugin/LineIn/ProtocolHandler.pm index d9ac7cb890f..c6060ff2217 100644 --- a/Slim/Plugin/LineIn/ProtocolHandler.pm +++ b/Slim/Plugin/LineIn/ProtocolHandler.pm @@ -2,7 +2,7 @@ package Slim::Plugin::LineIn::ProtocolHandler; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/LineIn/install.xml b/Slim/Plugin/LineIn/install.xml index aa8d3f030bd..3537a602e44 100644 --- a/Slim/Plugin/LineIn/install.xml +++ b/Slim/Plugin/LineIn/install.xml @@ -14,7 +14,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/LineOut/Plugin.pm b/Slim/Plugin/LineOut/Plugin.pm index 22679ed810a..14a3b169d29 100644 --- a/Slim/Plugin/LineOut/Plugin.pm +++ b/Slim/Plugin/LineOut/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::LineOut::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/LineOut/install.xml b/Slim/Plugin/LineOut/install.xml index 9a03ea328ab..c418eae15a7 100644 --- a/Slim/Plugin/LineOut/install.xml +++ b/Slim/Plugin/LineOut/install.xml @@ -13,7 +13,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/Live365/install.xml b/Slim/Plugin/Live365/install.xml index cab3b13ca5e..46da9ee09a7 100644 --- a/Slim/Plugin/Live365/install.xml +++ b/Slim/Plugin/Live365/install.xml @@ -11,7 +11,7 @@ http://www.mysqueezebox.com/appgallery/Live365 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/MP3tunes/install.xml b/Slim/Plugin/MP3tunes/install.xml index 504a1e4ac3e..020813b8121 100644 --- a/Slim/Plugin/MP3tunes/install.xml +++ b/Slim/Plugin/MP3tunes/install.xml @@ -11,7 +11,7 @@ plugins/MP3tunes/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Mediafly/install.xml b/Slim/Plugin/Mediafly/install.xml index 9030b71d3b9..9a477343e3c 100644 --- a/Slim/Plugin/Mediafly/install.xml +++ b/Slim/Plugin/Mediafly/install.xml @@ -11,7 +11,7 @@ plugins/Mediafly/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/MusicMagic/ClientSettings.pm b/Slim/Plugin/MusicMagic/ClientSettings.pm index 43f11f17053..17f288f4b97 100644 --- a/Slim/Plugin/MusicMagic/ClientSettings.pm +++ b/Slim/Plugin/MusicMagic/ClientSettings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::MusicMagic::ClientSettings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/MusicMagic/Common.pm b/Slim/Plugin/MusicMagic/Common.pm index 07eb16de0e5..fab95f52080 100644 --- a/Slim/Plugin/MusicMagic/Common.pm +++ b/Slim/Plugin/MusicMagic/Common.pm @@ -2,7 +2,7 @@ package Slim::Plugin::MusicMagic::Common; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech +# Logitech Media Server Copyright 2001-2011 Logitech # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/MusicMagic/Importer.pm b/Slim/Plugin/MusicMagic/Importer.pm index b2226ca8d60..52d8d4a8e83 100644 --- a/Slim/Plugin/MusicMagic/Importer.pm +++ b/Slim/Plugin/MusicMagic/Importer.pm @@ -2,7 +2,7 @@ package Slim::Plugin::MusicMagic::Importer; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech +# Logitech Media Server Copyright 2001-2011 Logitech # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/MusicMagic/PlayerSettings.pm b/Slim/Plugin/MusicMagic/PlayerSettings.pm index 856ff7ead9f..99b364883dd 100644 --- a/Slim/Plugin/MusicMagic/PlayerSettings.pm +++ b/Slim/Plugin/MusicMagic/PlayerSettings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::MusicMagic::PlayerSettings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/MusicMagic/Plugin.pm b/Slim/Plugin/MusicMagic/Plugin.pm index 18c6595be24..7d66b684502 100644 --- a/Slim/Plugin/MusicMagic/Plugin.pm +++ b/Slim/Plugin/MusicMagic/Plugin.pm @@ -2,7 +2,7 @@ package Slim::Plugin::MusicMagic::Plugin; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech +# Logitech Media Server Copyright 2001-2011 Logitech # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -276,7 +276,7 @@ sub initPlugin { # if this is the first time MIP is initialized, have it use # - faster mixable status only scan (2) if a music folder is defined # - slower full metadata import (1) if no music folder is defined - $prefs->set('musicip', Slim::Utils::Misc::getAudioDir() ? 2 : 1) if !defined $enabled; + $prefs->set('musicip', scalar @{ Slim::Utils::Misc::getAudioDirs() } ? 2 : 1) if !defined $enabled; # this query should return an API error if Power Search is not available $response = _syncHTTPRequest("/api/mix?filter=?length>120&length=1"); diff --git a/Slim/Plugin/MusicMagic/ProtocolHandler.pm b/Slim/Plugin/MusicMagic/ProtocolHandler.pm index 44ae77a4428..465e0f65a0d 100644 --- a/Slim/Plugin/MusicMagic/ProtocolHandler.pm +++ b/Slim/Plugin/MusicMagic/ProtocolHandler.pm @@ -2,7 +2,7 @@ package Slim::Plugin::MusicMagic::ProtocolHandler; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/MusicMagic/Settings.pm b/Slim/Plugin/MusicMagic/Settings.pm index 7abf3736383..4f0d2434402 100644 --- a/Slim/Plugin/MusicMagic/Settings.pm +++ b/Slim/Plugin/MusicMagic/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::MusicMagic::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/MusicMagic/install.xml b/Slim/Plugin/MusicMagic/install.xml index 5153e84e4e1..f701e620d3d 100644 --- a/Slim/Plugin/MusicMagic/install.xml +++ b/Slim/Plugin/MusicMagic/install.xml @@ -21,7 +21,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/MusicMagic/strings.txt b/Slim/Plugin/MusicMagic/strings.txt index 6b19665b266..3f73bf02957 100644 --- a/Slim/Plugin/MusicMagic/strings.txt +++ b/Slim/Plugin/MusicMagic/strings.txt @@ -135,21 +135,21 @@ SETUP_MIX_FILTER ZH_CN 混音过滤器 SETUP_MIX_FILTER_DESC - CS Můžete vytvořit pojmenované sady filtrovacích podmínek v MusicIP a zvolit ze zde uvedeného seznamu aplikaci filtrů na Mixy MusicIP ve Squeezebox Server. - DA Du kan definere navngivne filterbetingelser i MusicIP og vælge at anvende disse filtre på miks fra MusicIP i Squeezebox Server. - DE In MusicIP können Sie Filtersätze unter einem Namen speichern. Wählen Sie hier einen dieser Sätze, der auf die MusicIP-Mixes im Squeezebox Server angewendet werden soll. - EN You can create named sets of filter conditions in MusicIP and choose from the list here to apply those filters to MusicIP Mixes in Squeezebox Server. - ES Se pueden crear conjuntos con nombre de condiciones de filtro creadas en MusicIP y se puede elegir de esta lista para aplicar esos filtros a las mezclas de MusicIP en Squeezebox Server. - FI Voit luoda nimettyjä suodatinehtojoukkoja MusicIP:ssä, valita haluamasi suodattimet tässä olevasta luettelosta ja ottaa nämä suodattimet käyttöön MusicIP-mikseissä Squeezebox Serverissä. - FR Vous pouvez créer des jeux de conditions de filtres nommés dans MusicIP et spécifier dans la liste ici si vous souhaitez appliquer ces filtres aux mix MusicIP dans le Squeezebox Server. - HE באפשרותך ליצור ערכות בעלות שם של תנאי סינון ב-MusicIP ולבחור מהרשימה שמופיעה כאן להחיל את המסננים על מיקסים של MusicIP ב-Squeezebox Server. - IT È possibile creare in MusicIP gruppi di condizioni di filtro con nome e scegliere da questo elenco le raccolte MusicIP a cui applicare tali filtri in Squeezebox Server. - NL Je kunt benoemde sets met filtercondities maken in MusicIP. Maak vervolgens een keuze uit de lijst hier om de filtersets op MusicIP-mixes in Squeezebox Server toe te passen. - NO Du kan lage og gi navn til dine egne sett med filterbetingelser i MusicIP, og velge fra denne listen for å bruke disse filtrene på MusicIP-mikser i Squeezebox Server. - PL W usłudze MusicIP można utworzyć zestawy filtrów warunków oraz nadać im nazwy, a następnie wybrać je z listy w tym miejscu w celu zastosowania filtrów do składanek usługi MusicIP w programie Squeezebox Server. - RU В MusicIP можно создавать именованные наборы фильтров и, выбирая из списка, применять эти фильтры к миксам MusicIP в Squeezebox Server. - SV Du kan skapa olika uppsättningar filtervilkor i MusicIP och sedan använda dem med MusicIP Mix i Squeezebox Server. Välj filter i listan. - ZH_CN 您可以利用MusicIP设立过滤器,并且从这表中选择应用在Squeezebox Server内MusicIP混音的那些过滤器。 + CS Můžete vytvořit pojmenované sady filtrovacích podmínek v MusicIP a zvolit ze zde uvedeného seznamu aplikaci filtrů na Mixy MusicIP ve Logitech Media Server. + DA Du kan definere navngivne filterbetingelser i MusicIP og vælge at anvende disse filtre på miks fra MusicIP i Logitech Media Server. + DE In MusicIP können Sie Filtersätze unter einem Namen speichern. Wählen Sie hier einen dieser Sätze, der auf die MusicIP-Mixes im Logitech Media Server angewendet werden soll. + EN You can create named sets of filter conditions in MusicIP and choose from the list here to apply those filters to MusicIP Mixes in Logitech Media Server. + ES Se pueden crear conjuntos con nombre de condiciones de filtro creadas en MusicIP y se puede elegir de esta lista para aplicar esos filtros a las mezclas de MusicIP en Logitech Media Server. + FI Voit luoda nimettyjä suodatinehtojoukkoja MusicIP:ssä, valita haluamasi suodattimet tässä olevasta luettelosta ja ottaa nämä suodattimet käyttöön MusicIP-mikseissä Logitech Media Serverissä. + FR Vous pouvez créer des jeux de conditions de filtres nommés dans MusicIP et spécifier dans la liste ici si vous souhaitez appliquer ces filtres aux mix MusicIP dans le Logitech Media Server. + HE באפשרותך ליצור ערכות בעלות שם של תנאי סינון ב-MusicIP ולבחור מהרשימה שמופיעה כאן להחיל את המסננים על מיקסים של MusicIP ב-Logitech Media Server. + IT È possibile creare in MusicIP gruppi di condizioni di filtro con nome e scegliere da questo elenco le raccolte MusicIP a cui applicare tali filtri in Logitech Media Server. + NL Je kunt benoemde sets met filtercondities maken in MusicIP. Maak vervolgens een keuze uit de lijst hier om de filtersets op MusicIP-mixes in Logitech Media Server toe te passen. + NO Du kan lage og gi navn til dine egne sett med filterbetingelser i MusicIP, og velge fra denne listen for å bruke disse filtrene på MusicIP-mikser i Logitech Media Server. + PL W usłudze MusicIP można utworzyć zestawy filtrów warunków oraz nadać im nazwy, a następnie wybrać je z listy w tym miejscu w celu zastosowania filtrów do składanek usługi MusicIP w programie Logitech Media Server. + RU В MusicIP можно создавать именованные наборы фильтров и, выбирая из списка, применять эти фильтры к миксам MusicIP в Logitech Media Server. + SV Du kan skapa olika uppsättningar filtervilkor i MusicIP och sedan använda dem med MusicIP Mix i Logitech Media Server. Välj filter i listan. + ZH_CN 您可以利用MusicIP设立过滤器,并且从这表中选择应用在Logitech Media Server内MusicIP混音的那些过滤器。 SETUP_MIX_GENRE CS Žánr Mixu @@ -443,19 +443,19 @@ SETUP_MUSICMAGIC ZH_CN MusicIP SETUP_MUSICMAGIC_DESC - CS Squeezebox Server může použít váš program MusicIP jako zdroj informací o titulech a žánrech. Nebo jej můžete použít pouze k vytvoření okamžitých mixů na úrovni žánrů, umělců a skladeb. Načtení informací o titulech a žánrech je daleko pomalejší než pouze načtení mixovatelného statusu, obzvláště při prohledávání pouze nových a změněných skladeb. - DA Squeezebox Server kan bruge MusicIP som kilde til at hente oplysninger om titel og genre. Du kan også fremstille lynmiks baseret på en genre, en kunstner eller et nummer. Det tager længere tid at læse oplysninger om titel og genre end kun at læse oplysninger om miksets status, navnlig når der kun søges efter nye eller ændrede numre. - DE Squeezebox Server kann MusicIP als Quelle für Titel- und Stilrichtungsangaben verwenden. Sie können es auch dazu nutzen, um nur Instant Mixes auf Stilrichtungs-, Interpreten und Titelebene zu erstellen. Es dauert viel länger, die Titel- und Stilrichtungsangaben zu lesen als nur den mischbaren Status, vor allem wenn Sie nur nach neuen und geänderten Titeln suchen. - EN Squeezebox Server can use your MusicIP program as source for title and genre information. Or you can use it to only generate instant mixes on genre, artist and song level. Reading title and genre information is much slower than reading the mixable status only, especially when scanning for new and changed songs only. - ES Squeezebox Server puede usar el programa MusicIP como origen para la información de título y de género. O se puede usar sólo para generar mezclas instantáneas por género, artista y canción. Leer la información de título y género es mucho más lento que leer sólo el estado mezclable, especialmente cuando se examina sólo en busca de canciones nuevas y cambiadas. - FI Squeezebox Server voi käyttää MusicIP-ohjelmaa nimi- ja genretietojen lähteenä. Voit myös käyttää sitä ainoastaan välittömien miksien luomiseen genre-, artisti- ja kappaletasolla. Nimi- ja genretietojen lukeminen on paljon hitaampaa kuin ainoastaan miksattavien tietojen lukeminen, erityisesti, kun etsitään vain uusia ja muutettuja kappaleita. - FR Squeezebox Server peut utiliser le logiciel MusicIP comme source pour les titres et les genres. Vous pouvez également générer uniquement des mix instantanés par genre, par artiste ou par morceau. La lecture des informations de titre et de genre est plus lente que la lecture de l'état mixable uniquement, en particulier lors de la recherche des nouveaux morceaux ou des morceaux modifiés. - IT In Squeezebox Server il programma MusicIP può essere utilizzato come origine delle informazioni relative al titolo e al genere musicale. In alternativa è possibile utilizzarlo solo per generare raccolte rapide in base al genere, all'artista e ai brani. La lettura di informazioni relative a titolo e genere risulta molto più lenta della lettura limitata allo stato della raccolta, in particolare durante la ricerca dei soli brani nuovi e modificati. - NL Squeezebox Server kan je MusicIP-programma gebruiken als bron voor titel- en genre-informatie. Je kunt het ook gebruiken om alleen instantmixen te maken op genre, artiest en liedje. Het lezen van titel- en genre-informatie is veel langzamer dan het lezen van alleen de mixbaarheidsstatus, vooral wanneer er alleen op nieuwe en gewijzigde liedjes wordt gescand. - NO Squeezebox Server kan bruke MusicIP-programmet som kilde for tittel- og sjangerinformasjon, eller du kan bruke det til å lage mikser på et øyeblikk ut fra sjanger, artist og sang. Det går mye saktere å lese tittel- og sjangerinformasjon enn miksstatusen, særlig når du kun søker etter nye og endrede sanger. - PL Program Squeezebox Server może użyć usługi MusicIP jako źródła informacji o tytułach i gatunkach. Można też użyć go tylko do szybkiego wygenerowania składanek na poziomie gatunku, wykonawcy i utworu. Odczytywanie informacji o tytule i gatunku trwa znacznie dłużej niż odczytywanie tylko stanu możliwości utworzenia składanki, szczególnie w przypadku wyszukiwania nowej i zmienionej muzyki. - RU Squeezebox Server может получать от программы MusicIP информацию о названии и жанре. Можно также создавать мгновенные миксы по жанрам, исполнителям и песням. Считывание информации о названии и жанре происходит намного дольше, чем просто считывание состояния микшируемости (особенно при поиске только новых и измененных песен). - SV Squeezebox Server kan använda MusicIP som källa till titel- och genreinformation. Dessutom kan du snabbt skapa mixer på genre-, artist- eller låtnivå. Det tar mycket längre tid att läsa in titel- och genreinformation än mixstatus, i synnerhet när programmet endast söker efter nya och ändrade låtar. + CS Logitech Media Server může použít váš program MusicIP jako zdroj informací o titulech a žánrech. Nebo jej můžete použít pouze k vytvoření okamžitých mixů na úrovni žánrů, umělců a skladeb. Načtení informací o titulech a žánrech je daleko pomalejší než pouze načtení mixovatelného statusu, obzvláště při prohledávání pouze nových a změněných skladeb. + DA Logitech Media Server kan bruge MusicIP som kilde til at hente oplysninger om titel og genre. Du kan også fremstille lynmiks baseret på en genre, en kunstner eller et nummer. Det tager længere tid at læse oplysninger om titel og genre end kun at læse oplysninger om miksets status, navnlig når der kun søges efter nye eller ændrede numre. + DE Logitech Media Server kann MusicIP als Quelle für Titel- und Stilrichtungsangaben verwenden. Sie können es auch dazu nutzen, um nur Instant Mixes auf Stilrichtungs-, Interpreten und Titelebene zu erstellen. Es dauert viel länger, die Titel- und Stilrichtungsangaben zu lesen als nur den mischbaren Status, vor allem wenn Sie nur nach neuen und geänderten Titeln suchen. + EN Logitech Media Server can use your MusicIP program as source for title and genre information. Or you can use it to only generate instant mixes on genre, artist and song level. Reading title and genre information is much slower than reading the mixable status only, especially when scanning for new and changed songs only. + ES Logitech Media Server puede usar el programa MusicIP como origen para la información de título y de género. O se puede usar sólo para generar mezclas instantáneas por género, artista y canción. Leer la información de título y género es mucho más lento que leer sólo el estado mezclable, especialmente cuando se examina sólo en busca de canciones nuevas y cambiadas. + FI Logitech Media Server voi käyttää MusicIP-ohjelmaa nimi- ja genretietojen lähteenä. Voit myös käyttää sitä ainoastaan välittömien miksien luomiseen genre-, artisti- ja kappaletasolla. Nimi- ja genretietojen lukeminen on paljon hitaampaa kuin ainoastaan miksattavien tietojen lukeminen, erityisesti, kun etsitään vain uusia ja muutettuja kappaleita. + FR Logitech Media Server peut utiliser le logiciel MusicIP comme source pour les titres et les genres. Vous pouvez également générer uniquement des mix instantanés par genre, par artiste ou par morceau. La lecture des informations de titre et de genre est plus lente que la lecture de l'état mixable uniquement, en particulier lors de la recherche des nouveaux morceaux ou des morceaux modifiés. + IT In Logitech Media Server il programma MusicIP può essere utilizzato come origine delle informazioni relative al titolo e al genere musicale. In alternativa è possibile utilizzarlo solo per generare raccolte rapide in base al genere, all'artista e ai brani. La lettura di informazioni relative a titolo e genere risulta molto più lenta della lettura limitata allo stato della raccolta, in particolare durante la ricerca dei soli brani nuovi e modificati. + NL Logitech Media Server kan je MusicIP-programma gebruiken als bron voor titel- en genre-informatie. Je kunt het ook gebruiken om alleen instantmixen te maken op genre, artiest en liedje. Het lezen van titel- en genre-informatie is veel langzamer dan het lezen van alleen de mixbaarheidsstatus, vooral wanneer er alleen op nieuwe en gewijzigde liedjes wordt gescand. + NO Logitech Media Server kan bruke MusicIP-programmet som kilde for tittel- og sjangerinformasjon, eller du kan bruke det til å lage mikser på et øyeblikk ut fra sjanger, artist og sang. Det går mye saktere å lese tittel- og sjangerinformasjon enn miksstatusen, særlig når du kun søker etter nye og endrede sanger. + PL Program Logitech Media Server może użyć usługi MusicIP jako źródła informacji o tytułach i gatunkach. Można też użyć go tylko do szybkiego wygenerowania składanek na poziomie gatunku, wykonawcy i utworu. Odczytywanie informacji o tytule i gatunku trwa znacznie dłużej niż odczytywanie tylko stanu możliwości utworzenia składanki, szczególnie w przypadku wyszukiwania nowej i zmienionej muzyki. + RU Logitech Media Server может получать от программы MusicIP информацию о названии и жанре. Можно также создавать мгновенные миксы по жанрам, исполнителям и песням. Считывание информации о названии и жанре происходит намного дольше, чем просто считывание состояния микшируемости (особенно при поиске только новых и измененных песен). + SV Logitech Media Server kan använda MusicIP som källa till titel- och genreinformation. Dessutom kan du snabbt skapa mixer på genre-, artist- eller låtnivå. Det tar mycket längre tid att läsa in titel- och genreinformation än mixstatus, i synnerhet när programmet endast söker efter nya och ändrade låtar. MMMMIXTYPE_TRACKS CS Počet stop @@ -526,21 +526,21 @@ SETUP_MUSICMAGICSCANINTERVAL ZH_CN MusicIP刷新间隔时间 SETUP_MUSICMAGICSCANINTERVAL_DESC - CS Když se změní databáze vašeho MusicIP Database, Squeezebox Server automaticky importuje informace o knihovně. Můžete specifikovat minimální dobu (v sekundách), po kterou bude Squeezebox Server čekat před znovunačtením vaší databáze MusicIP. Nulová hodnota zakáže znovunačítání. - DA Når noget i MusicIP-databasen ændres, importeres disse oplysninger automatisk i Squeezebox Server. Du kan angive hvor lang tid (i sekunder) der mindst skal gå før MusicIP-databasen genindlæses i Squeezebox Server. Hvis værdien er 0, genindlæses den ikke. - DE Wenn sich die MusicIP-Datenbank ändert, importiert Squeezebox Server die Daten automatisch erneut. Sie können die Zeit (in Sekunden) angeben, die Squeezebox Server mindestens warten soll, bevor die MusicIP-Datenbank erneut importiert wird. Wenn Sie 0 eingeben, wird diese Option deaktiviert. - EN When your MusicIP Database changes, Squeezebox Server will automatically import the library information. You can specify the minimum amount of time (in seconds) that Squeezebox Server will wait before reloading your MusicIP Database again. A value of zero disables the reload. - ES Cuando cambie la base de datos de MusicIP, Squeezebox Server importará automáticamente la información de la biblioteca. Se puede especificar la cantidad de tiempo mínima (en segundos) que Squeezebox Server esperará antes de volver a cargar la base de datos de MusicIP. Un valor de cero desactiva la recarga. - FI Jos MusicIP-tietokanta muuttuu, Squeezebox Server tuo kirjaston tiedot automaattisesti. Voit määrittää minimiajan (sekunteina), jonka Squeezebox Server odottaa, ennen kuin se lataa MusicIP-tietokannan uudelleen. Jos arvo on nolla, lataaminen on poistettu käytöstä. - FR Le Squeezebox Server importe automatiquement les informations de la base de données MusicIP lorsque vous la modifiez. Vous pouvez spécifier le délai minimal en secondes au bout duquel le Squeezebox Server actualise la base de données MusicIP. La valeur 0 désactive cette fonctionnalité. - HE כאשר מסד הנתונים של MusicIP משתנה, Squeezebox Server מייבא את מידע הספרייה באופן אוטומטי. באפשרותך לציין כמות זמן מינימלית (בשניות) שבמהלכה על Squeezebox Server להמתין לפני טעינה חוזרת של מסד הנתונים של MusicIP. ערך אפס משבית את אפשרות הטעינה מחדש. - IT Se si modifica il database di MusicIP, Squeezebox Server importa automaticamente i dati della libreria. È possibile specificare per Squeezebox Server il periodo minimo di attesa (in secondi) precedente al ricaricamento del database di MusicIP. Se si imposta il valore zero, la funzionalità viene disattivata. - NL Wanneer je MusicIP-database verandert, worden de collectiegegevens automatisch door Squeezebox Server geïmporteerd. Je kunt opgeven (in seconden) hoe lang Squeezebox Server minimaal moet wachten alvorens je MusicIP-database te herladen. Een waarde van 0 seconden schakelt herladen uit. - NO Når databasen til MusicIP endres, importerer Squeezebox Server automatisk bibliotekinformasjonen. Du kan angi en minimumstid (i sekunder) for hvor lenge Squeezebox Server skal vente med å laste inn databasen til MusicIP igjen. Hvis verdien er null, deaktiveres innlasting. - PL Po zmianie informacji w bazie danych usługi MusicIP program Squeezebox Server automatycznie zaimportuje informacje o bibliotece. Możliwe jest określenie minimalnego czasu (w sekundach) po jakim program Squeezebox Server ponownie załaduje bazę danych usługi MusicIP. Ustawienie wartości zero powoduje wyłączenie ponownego ładowania. - RU При изменении базы данных MusicIP данные медиатеки автоматически импортируются в Squeezebox Server. Для Squeezebox Server можно задать минимальный интервал времени (в секундах) перед повторной загрузкой базы данных MusicIP. Значение 0 означает отмену повторной загрузки. - SV När din MusicIP-databas ändras importeras biblioteksinformationen automatiskt till Squeezebox Server. Du kan ange en minimitid (i sekunder) som Squeezebox Server ska vänta mellan varje gång informationen från MusicIP-databasen uppdateras. Om värdet 0 anges avaktiveras uppdateringsfunktionen. - ZH_CN 当您的MusicIP数据库改变时,Squeezebox Server将自动地导入最新音乐库信息。您可以指定Squeezebox Server再装您的MusicIP数据库之前极小等候时间(以秒为单位)。以零为值意味着关闭再装功能。 + CS Když se změní databáze vašeho MusicIP Database, Logitech Media Server automaticky importuje informace o knihovně. Můžete specifikovat minimální dobu (v sekundách), po kterou bude Logitech Media Server čekat před znovunačtením vaší databáze MusicIP. Nulová hodnota zakáže znovunačítání. + DA Når noget i MusicIP-databasen ændres, importeres disse oplysninger automatisk i Logitech Media Server. Du kan angive hvor lang tid (i sekunder) der mindst skal gå før MusicIP-databasen genindlæses i Logitech Media Server. Hvis værdien er 0, genindlæses den ikke. + DE Wenn sich die MusicIP-Datenbank ändert, importiert Logitech Media Server die Daten automatisch erneut. Sie können die Zeit (in Sekunden) angeben, die Logitech Media Server mindestens warten soll, bevor die MusicIP-Datenbank erneut importiert wird. Wenn Sie 0 eingeben, wird diese Option deaktiviert. + EN When your MusicIP Database changes, Logitech Media Server will automatically import the library information. You can specify the minimum amount of time (in seconds) that Logitech Media Server will wait before reloading your MusicIP Database again. A value of zero disables the reload. + ES Cuando cambie la base de datos de MusicIP, Logitech Media Server importará automáticamente la información de la biblioteca. Se puede especificar la cantidad de tiempo mínima (en segundos) que Logitech Media Server esperará antes de volver a cargar la base de datos de MusicIP. Un valor de cero desactiva la recarga. + FI Jos MusicIP-tietokanta muuttuu, Logitech Media Server tuo kirjaston tiedot automaattisesti. Voit määrittää minimiajan (sekunteina), jonka Logitech Media Server odottaa, ennen kuin se lataa MusicIP-tietokannan uudelleen. Jos arvo on nolla, lataaminen on poistettu käytöstä. + FR Le Logitech Media Server importe automatiquement les informations de la base de données MusicIP lorsque vous la modifiez. Vous pouvez spécifier le délai minimal en secondes au bout duquel le Logitech Media Server actualise la base de données MusicIP. La valeur 0 désactive cette fonctionnalité. + HE כאשר מסד הנתונים של MusicIP משתנה, Logitech Media Server מייבא את מידע הספרייה באופן אוטומטי. באפשרותך לציין כמות זמן מינימלית (בשניות) שבמהלכה על Logitech Media Server להמתין לפני טעינה חוזרת של מסד הנתונים של MusicIP. ערך אפס משבית את אפשרות הטעינה מחדש. + IT Se si modifica il database di MusicIP, Logitech Media Server importa automaticamente i dati della libreria. È possibile specificare per Logitech Media Server il periodo minimo di attesa (in secondi) precedente al ricaricamento del database di MusicIP. Se si imposta il valore zero, la funzionalità viene disattivata. + NL Wanneer je MusicIP-database verandert, worden de collectiegegevens automatisch door Logitech Media Server geïmporteerd. Je kunt opgeven (in seconden) hoe lang Logitech Media Server minimaal moet wachten alvorens je MusicIP-database te herladen. Een waarde van 0 seconden schakelt herladen uit. + NO Når databasen til MusicIP endres, importerer Logitech Media Server automatisk bibliotekinformasjonen. Du kan angi en minimumstid (i sekunder) for hvor lenge Logitech Media Server skal vente med å laste inn databasen til MusicIP igjen. Hvis verdien er null, deaktiveres innlasting. + PL Po zmianie informacji w bazie danych usługi MusicIP program Logitech Media Server automatycznie zaimportuje informacje o bibliotece. Możliwe jest określenie minimalnego czasu (w sekundach) po jakim program Logitech Media Server ponownie załaduje bazę danych usługi MusicIP. Ustawienie wartości zero powoduje wyłączenie ponownego ładowania. + RU При изменении базы данных MusicIP данные медиатеки автоматически импортируются в Logitech Media Server. Для Logitech Media Server можно задать минимальный интервал времени (в секундах) перед повторной загрузкой базы данных MusicIP. Значение 0 означает отмену повторной загрузки. + SV När din MusicIP-databas ändras importeras biblioteksinformationen automatiskt till Logitech Media Server. Du kan ange en minimitid (i sekunder) som Logitech Media Server ska vänta mellan varje gång informationen från MusicIP-databasen uppdateras. Om värdet 0 anges avaktiveras uppdateringsfunktionen. + ZH_CN 当您的MusicIP数据库改变时,Logitech Media Server将自动地导入最新音乐库信息。您可以指定Logitech Media Server再装您的MusicIP数据库之前极小等候时间(以秒为单位)。以零为值意味着关闭再装功能。 SETUP_MMSPORT CS HTTP port MusicIP diff --git a/Slim/Plugin/MyApps/install.xml b/Slim/Plugin/MyApps/install.xml index f57bdb48391..61be367c404 100644 --- a/Slim/Plugin/MyApps/install.xml +++ b/Slim/Plugin/MyApps/install.xml @@ -12,7 +12,7 @@ 2 1 - Squeezebox Server + Logitech Media Server 7.4 * diff --git a/Slim/Plugin/Napster/install.xml b/Slim/Plugin/Napster/install.xml index 9ab82a35da8..8ede68b706d 100644 --- a/Slim/Plugin/Napster/install.xml +++ b/Slim/Plugin/Napster/install.xml @@ -11,7 +11,7 @@ plugins/Napster/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.3 * diff --git a/Slim/Plugin/NetTest/Plugin.pm b/Slim/Plugin/NetTest/Plugin.pm index a56861e72ad..c0c6dad3b9b 100644 --- a/Slim/Plugin/NetTest/Plugin.pm +++ b/Slim/Plugin/NetTest/Plugin.pm @@ -1,10 +1,10 @@ -# Plugin for Squeezebox Server to test network bandwidth +# Plugin for Logitech Media Server to test network bandwidth # # $Id$ # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2005-2009 Logitech. +# Logitech Media Server Copyright 2005-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/NetTest/install.xml b/Slim/Plugin/NetTest/install.xml index 657139b037f..3fc895a47d2 100644 --- a/Slim/Plugin/NetTest/install.xml +++ b/Slim/Plugin/NetTest/install.xml @@ -13,7 +13,7 @@ http://www.mysqueezebox.com/support 2 - Squeezebox Server + Logitech Media Server 7.4 * diff --git a/Slim/Plugin/OPMLGeneric/install.xml b/Slim/Plugin/OPMLGeneric/install.xml index ec9a08faecb..d63e5727f08 100644 --- a/Slim/Plugin/OPMLGeneric/install.xml +++ b/Slim/Plugin/OPMLGeneric/install.xml @@ -10,7 +10,7 @@ http://www.mysqueezebox.com/support 2 - Squeezebox Server + Logitech Media Server 7.4 * diff --git a/Slim/Plugin/Pandora/install.xml b/Slim/Plugin/Pandora/install.xml index 70ca9a53017..5c34b455445 100644 --- a/Slim/Plugin/Pandora/install.xml +++ b/Slim/Plugin/Pandora/install.xml @@ -11,7 +11,7 @@ plugins/Pandora/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Podcast/Settings.pm b/Slim/Plugin/Podcast/Settings.pm index e87c0e6e903..fd9567969f2 100644 --- a/Slim/Plugin/Podcast/Settings.pm +++ b/Slim/Plugin/Podcast/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::Podcast::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Podcast/install.xml b/Slim/Plugin/Podcast/install.xml index d039cb1c842..2e2f5eef75f 100644 --- a/Slim/Plugin/Podcast/install.xml +++ b/Slim/Plugin/Podcast/install.xml @@ -16,7 +16,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/PreventStandby/Settings.pm b/Slim/Plugin/PreventStandby/Settings.pm index f48ceaeb609..7ec9847452e 100644 --- a/Slim/Plugin/PreventStandby/Settings.pm +++ b/Slim/Plugin/PreventStandby/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::PreventStandby::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/PreventStandby/install.xml b/Slim/Plugin/PreventStandby/install.xml index 648b8946b71..babec33ed49 100644 --- a/Slim/Plugin/PreventStandby/install.xml +++ b/Slim/Plugin/PreventStandby/install.xml @@ -15,7 +15,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/PreventStandby/strings.txt b/Slim/Plugin/PreventStandby/strings.txt index 45d605a78f1..52e928aa8be 100644 --- a/Slim/Plugin/PreventStandby/strings.txt +++ b/Slim/Plugin/PreventStandby/strings.txt @@ -16,18 +16,18 @@ PLUGIN_PREVENTSTANDBY SV Windows: Förhindra viloläge PLUGIN_PREVENTSTANDBY_DESC - CS Tento plugin monitoruje vaše přehrávače Squeezebox a zabrání systému v přechodu do úsporného pohotovostního režimu při přehrávání hudby, v průběhu prohledávání Squeezebox Server, při aktualizaci přehrávačů atd. Zabrání také systému v přechodu do pohotovostního režimu po dvou minutách od dálkového spuštění počítače přes LAN. - DA Dette udvidelsesmodul bruges til at overvåge Squeezebox-afspillere og forhindre at systemet går på standby mens der spilles musik, søges after musikfiler i Squeezebox Server, afspillerne opdateres osv. Det forhindrer også at systemet går på standby blot to minutter efter at det er vækket via lokalnetværket. - DE Dieses Plugin überwacht die Squeezebox-Player und verhindert, dass das System in den Standbymodus geschaltet wird während Squeezebox Server die Musiksammlung durchsucht, Player aktualisiert werden usw. Außerdem wird verhindert, dass das System zwei Minuten nach 'Wake on LAN' vorzeitig in den Standbymodus schaltet. - EN This plugin monitors your SqueezeBox players and prevents the system from going into power saving standby mode while music is playing, Squeezebox Server is scanning, players are updating, etc. It will also prevent the system from prematurely going into standby two minutes after wake-on-lan. - ES Este complemento supervisa los reproductores SqueezeBox e impide que el sistema pase al modo de espera para ahorro de energía mientras se está reproduciendo música, Squeezebox Server está explorando, los reproductores se están actualizando, etc. También impedirá que el sistema pase prematuramente al modo de espera dos minutos después de Wake On LAN. - FI Tämä laajennus valvoo SqueezeBox-soittimia ja estää järjestelmää siirtymästä virtaa säästävään valmiustilaan, kun musiikkia soitetaan, kun Squeezebox Server suorittaa tarkistusta, kun soittimia päivitetään jne. Laajennus estää myös järjestelmää siirtymästä ennenaikaisesti valmiustilaan kaksi minuuttia lähiverkon herätyksen jälkeen. - FR Ce plugin surveille les platines SqueezeBox et empêche le système de passer en mode veille (d'économie d'énergie) lorsqu'un morceau est en cours de lecture, le Squeezebox Server est en cours d'analyse, les platines sont mises à jour, ainsi que deux minutes après l'activation de la fonction de réveil par LAN. + CS Tento plugin monitoruje vaše přehrávače Squeezebox a zabrání systému v přechodu do úsporného pohotovostního režimu při přehrávání hudby, v průběhu prohledávání Logitech Media Server, při aktualizaci přehrávačů atd. Zabrání také systému v přechodu do pohotovostního režimu po dvou minutách od dálkového spuštění počítače přes LAN. + DA Dette udvidelsesmodul bruges til at overvåge Squeezebox-afspillere og forhindre at systemet går på standby mens der spilles musik, søges after musikfiler i Logitech Media Server, afspillerne opdateres osv. Det forhindrer også at systemet går på standby blot to minutter efter at det er vækket via lokalnetværket. + DE Dieses Plugin überwacht die Squeezebox-Player und verhindert, dass das System in den Standbymodus geschaltet wird während Logitech Media Server die Musiksammlung durchsucht, Player aktualisiert werden usw. Außerdem wird verhindert, dass das System zwei Minuten nach 'Wake on LAN' vorzeitig in den Standbymodus schaltet. + EN This plugin monitors your SqueezeBox players and prevents the system from going into power saving standby mode while music is playing, Logitech Media Server is scanning, players are updating, etc. It will also prevent the system from prematurely going into standby two minutes after wake-on-lan. + ES Este complemento supervisa los reproductores SqueezeBox e impide que el sistema pase al modo de espera para ahorro de energía mientras se está reproduciendo música, Logitech Media Server está explorando, los reproductores se están actualizando, etc. También impedirá que el sistema pase prematuramente al modo de espera dos minutos después de Wake On LAN. + FI Tämä laajennus valvoo SqueezeBox-soittimia ja estää järjestelmää siirtymästä virtaa säästävään valmiustilaan, kun musiikkia soitetaan, kun Logitech Media Server suorittaa tarkistusta, kun soittimia päivitetään jne. Laajennus estää myös järjestelmää siirtymästä ennenaikaisesti valmiustilaan kaksi minuuttia lähiverkon herätyksen jälkeen. + FR Ce plugin surveille les platines SqueezeBox et empêche le système de passer en mode veille (d'économie d'énergie) lorsqu'un morceau est en cours de lecture, le Logitech Media Server est en cours d'analyse, les platines sont mises à jour, ainsi que deux minutes après l'activation de la fonction de réveil par LAN. IT Questo plugin tiene sotto controllo i lettori SqueezeBox e impedisce che nel sistema venga attivata la modalità standby durante la riproduzione della musica, l'analisi di Squeezebox, l'aggiornamento dei lettori e così via. Impedisce inoltre che il sistema entri prematuramente in modalità standby due minuti dopo l'attivazione LAN. - NL Deze plug-in houd je Squeezebox-systemen in de gaten en voorkomt dat het systeem naar energiebesparende stand-bymodus gaat terwijl er bijvoorbeeld muziek speelt, Squeezebox Server een scan uitvoert of systemen worden bijgewerkt. De plug-in voorkomt ook dat het systeem vroegtijdig naar stand-bymodus gaat twee minuten na wake-on-lan. - NO Denne plugin-modulen overvåker SqueezeBox-spillerne og forhindrer systemet fra å gå i hvilemodus mens det spilles musikk, mens Squeezebox Server søker, mens spillere oppdateres osv. Den forhindrer også at systemet går i for tidlig hvilemodus to minutter etter at det har blitt startet opp via et LAN. - PL Ten dodatek monitoruje odtwarzacze SqueezeBox i zapobiega przejściu systemu do trybu wstrzymania w celu oszczędzania energii, kiedy odtwarzana jest muzyka, program Squeezebox Server wykonuje przeszukiwanie, trwa aktualizacja odtwarzaczy itp. Dodatek uniemożliwi także przedwczesne przejście do trybu wstrzymania po upływie dwóch minut od zadziałania funkcji wake-on-lan. - RU Этот подключаемый модуль выполняет мониторинг плееров SqueezeBox и предотвращает переход в энергосберегающий режим ожидания во время воспроизведения музыки, сканирования Squeezebox Server, обновления плееров и др. Он также не позволяет преждевременно переходить в режим ожидания через две минуты после пробуждения по сети. + NL Deze plug-in houd je Squeezebox-systemen in de gaten en voorkomt dat het systeem naar energiebesparende stand-bymodus gaat terwijl er bijvoorbeeld muziek speelt, Logitech Media Server een scan uitvoert of systemen worden bijgewerkt. De plug-in voorkomt ook dat het systeem vroegtijdig naar stand-bymodus gaat twee minuten na wake-on-lan. + NO Denne plugin-modulen overvåker SqueezeBox-spillerne og forhindrer systemet fra å gå i hvilemodus mens det spilles musikk, mens Logitech Media Server søker, mens spillere oppdateres osv. Den forhindrer også at systemet går i for tidlig hvilemodus to minutter etter at det har blitt startet opp via et LAN. + PL Ten dodatek monitoruje odtwarzacze SqueezeBox i zapobiega przejściu systemu do trybu wstrzymania w celu oszczędzania energii, kiedy odtwarzana jest muzyka, program Logitech Media Server wykonuje przeszukiwanie, trwa aktualizacja odtwarzaczy itp. Dodatek uniemożliwi także przedwczesne przejście do trybu wstrzymania po upływie dwóch minut od zadziałania funkcji wake-on-lan. + RU Этот подключаемый модуль выполняет мониторинг плееров SqueezeBox и предотвращает переход в энергосберегающий режим ожидания во время воспроизведения музыки, сканирования Logitech Media Server, обновления плееров и др. Он также не позволяет преждевременно переходить в режим ожидания через две минуты после пробуждения по сети. SV Detta plugin-program övervakar SqueezeBox-spelarna och förhindrar att systemet försätts i viloläge när du spelar musik, när sökning sker, spelare uppdateras o.s.v. Det förhindrar även att systemet automatiskt försätts i viloläge två minuter efter wake-on-lan. PLUGIN_PREVENTSTANDBY_IDLETIME diff --git a/Slim/Plugin/RS232/Plugin.pm b/Slim/Plugin/RS232/Plugin.pm index c26e4d4d8a6..ee105199f39 100644 --- a/Slim/Plugin/RS232/Plugin.pm +++ b/Slim/Plugin/RS232/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::RS232::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/RS232/Settings.pm b/Slim/Plugin/RS232/Settings.pm index de410f45dcd..77b65229201 100755 --- a/Slim/Plugin/RS232/Settings.pm +++ b/Slim/Plugin/RS232/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::RS232::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/RS232/install.xml b/Slim/Plugin/RS232/install.xml index 001712fcf7d..f569fa45145 100644 --- a/Slim/Plugin/RS232/install.xml +++ b/Slim/Plugin/RS232/install.xml @@ -15,7 +15,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/RSSNews/Settings.pm b/Slim/Plugin/RSSNews/Settings.pm index 4f3420133b5..236aae6fa94 100644 --- a/Slim/Plugin/RSSNews/Settings.pm +++ b/Slim/Plugin/RSSNews/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::RSSNews::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/RSSNews/install.xml b/Slim/Plugin/RSSNews/install.xml index 5fd5419242e..258fd007833 100644 --- a/Slim/Plugin/RSSNews/install.xml +++ b/Slim/Plugin/RSSNews/install.xml @@ -15,7 +15,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/RadioTime/Plugin.pm b/Slim/Plugin/RadioTime/Plugin.pm index 3930cb2c55c..6204ce54455 100644 --- a/Slim/Plugin/RadioTime/Plugin.pm +++ b/Slim/Plugin/RadioTime/Plugin.pm @@ -2,7 +2,7 @@ package Slim::Plugin::RadioTime::Plugin; # $Id: Plugin.pm 11021 2006-12-21 22:28:39Z dsully $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/RadioTime/install.xml b/Slim/Plugin/RadioTime/install.xml index 56f2cb8ebde..1814528c336 100644 --- a/Slim/Plugin/RadioTime/install.xml +++ b/Slim/Plugin/RadioTime/install.xml @@ -13,7 +13,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/RandomPlay/Plugin.pm b/Slim/Plugin/RandomPlay/Plugin.pm index 7a62e16260a..96b82ebe353 100644 --- a/Slim/Plugin/RandomPlay/Plugin.pm +++ b/Slim/Plugin/RandomPlay/Plugin.pm @@ -9,7 +9,7 @@ package Slim::Plugin::RandomPlay::Plugin; # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2005-2009 Logitech. +# Logitech Media Server Copyright 2005-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/RandomPlay/ProtocolHandler.pm b/Slim/Plugin/RandomPlay/ProtocolHandler.pm index dfdfef1e803..71ed130e09a 100644 --- a/Slim/Plugin/RandomPlay/ProtocolHandler.pm +++ b/Slim/Plugin/RandomPlay/ProtocolHandler.pm @@ -2,7 +2,7 @@ package Slim::Plugin::RandomPlay::ProtocolHandler; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/RandomPlay/install.xml b/Slim/Plugin/RandomPlay/install.xml index 40e43cd74e5..9aa623f29c2 100644 --- a/Slim/Plugin/RandomPlay/install.xml +++ b/Slim/Plugin/RandomPlay/install.xml @@ -16,7 +16,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Rescan/Plugin.pm b/Slim/Plugin/Rescan/Plugin.pm index 65f38ae293d..024ecbb0058 100644 --- a/Slim/Plugin/Rescan/Plugin.pm +++ b/Slim/Plugin/Rescan/Plugin.pm @@ -6,7 +6,7 @@ package Slim::Plugin::Rescan::Plugin; # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -201,8 +201,10 @@ sub progressHeader { my $p = $progress[$index]; if (blessed($p) && $p->name) { - - my $line = $client->string($p->name.'_PROGRESS'); + + my $line = $p->name =~ /(.*)\|(.*)/ + ? ($client->string($2 . '_PROGRESS') . $client->string('COLON') . ' ' . $1) + : $client->string($p->name . '_PROGRESS'); if ($p->active) { diff --git a/Slim/Plugin/Rescan/Settings.pm b/Slim/Plugin/Rescan/Settings.pm index c8396b5bb45..ceaebf774d2 100644 --- a/Slim/Plugin/Rescan/Settings.pm +++ b/Slim/Plugin/Rescan/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::Rescan::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Rescan/install.xml b/Slim/Plugin/Rescan/install.xml index fe4bc8b4242..ecd88d2668d 100644 --- a/Slim/Plugin/Rescan/install.xml +++ b/Slim/Plugin/Rescan/install.xml @@ -16,7 +16,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Rescan/strings.txt b/Slim/Plugin/Rescan/strings.txt index 7830a154a76..fba93ab5908 100644 --- a/Slim/Plugin/Rescan/strings.txt +++ b/Slim/Plugin/Rescan/strings.txt @@ -167,7 +167,7 @@ PLUGIN_RESCAN_TIMER_DESC EN You can choose to allow a scheduled rescan of your music library every 24 hours. Set the time, and set the Rescan Timer to ON to use this feature. ES Se puede optar por permitir que se vuelva a examinar la biblioteca de música de forma programada cada 24 horas. Establezca la hora y el Temporizador para volver a examinar en ACTIVADO para utilizar esta característica. FI Voit sallia musiikkikirjastosi ajoitetun uudelleentarkistuksen 24 tunnin välein. Voit ottaa toiminnon käyttöön määrittämällä ajan ja asettamalla uudelleentarkistuksen ajastimen päälle. - FR Vous pouvez faire en sorte que le Squeezebox Server analyse à nouveau le contenu de votre bibliothèque toutes les 24 heures. Définissez l'heure et activez Programmation de l'analyse pour utiliser cette fonctionnalité. + FR Vous pouvez faire en sorte que le serveur analyse à nouveau le contenu de votre bibliothèque toutes les 24 heures. Définissez l'heure et activez Programmation de l'analyse pour utiliser cette fonctionnalité. HE באפשרותך לבחור לאפשר סריקה חוזרת מתוזמנת של ספריית המוסיקה שלך מדי 24 שעות. קבע את השעה והגדר את 'קוצב-זמן לסריקה חוזרת' ל'מופעל' כדי להשתמש במאפיין זה. IT È possibile impostare la pianificazione dell'analisi della libreria musicale ogni 24 ore. Per utilizzare questa funzione, è sufficiente impostare l'ora di esecuzione e attivare il timer dell'analisi. NL Je kunt je muziekcollectie elke 24 uur opnieuw laten scannen. Stel de tijd in en zet de 'Timer voor opnieuw scannen' op AAN om deze functie te gebruiken. diff --git a/Slim/Plugin/RhapsodyDirect/install.xml b/Slim/Plugin/RhapsodyDirect/install.xml index b5087b1013f..103f0a11a0f 100644 --- a/Slim/Plugin/RhapsodyDirect/install.xml +++ b/Slim/Plugin/RhapsodyDirect/install.xml @@ -11,7 +11,7 @@ plugins/RhapsodyDirect/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/SN/Plugin.pm b/Slim/Plugin/SN/Plugin.pm index 46f5b8cc312..02ec17b13e4 100644 --- a/Slim/Plugin/SN/Plugin.pm +++ b/Slim/Plugin/SN/Plugin.pm @@ -2,7 +2,7 @@ package Slim::Plugin::SN::Plugin; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech +# Logitech Media Server Copyright 2001-2011 Logitech # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/SN/ProtocolHandler.pm b/Slim/Plugin/SN/ProtocolHandler.pm index 8fa1990f914..e522a423f8f 100644 --- a/Slim/Plugin/SN/ProtocolHandler.pm +++ b/Slim/Plugin/SN/ProtocolHandler.pm @@ -2,7 +2,7 @@ package Slim::Plugin::SN::ProtocolHandler; # $Id -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/SN/install.xml b/Slim/Plugin/SN/install.xml index f8e676ec120..d9f2a24b598 100644 --- a/Slim/Plugin/SN/install.xml +++ b/Slim/Plugin/SN/install.xml @@ -14,7 +14,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.5 * diff --git a/Slim/Plugin/SN/strings.txt b/Slim/Plugin/SN/strings.txt index d7c3982742a..945b9f90c2b 100644 --- a/Slim/Plugin/SN/strings.txt +++ b/Slim/Plugin/SN/strings.txt @@ -18,17 +18,17 @@ PLUGIN_SN SV tjänsthanteraren mysqueezebox.com PLUGIN_SN_DESC - CS Pro služby, které nejsou podporovány na vašem Squeezebox Server přepněte na mysqueezebox.com. - DA Skift til mysqueezebox.com for tjenester som ikke er understøttet af Squeezebox Server. - DE Wechseln Sie zu mysqueezebox.com für eine Auswahl an Diensten, die nicht von Squeezebox Server unterstützt werden. - EN Switch to mysqueezebox.com for services which are not supported on your Squeezebox Server. - ES Cambie a mysqueezebox.com para acceder a los servicios no admitidos en Squeezebox Server. - FI Vaihtamalla mysqueezebox.comiin pääset nauttimaan palveluista, joita Squeezebox Server ei tue. - FR Utilisez mysqueezebox.com pour accéder aux services non pris en charge par votre Squeezebox Server. - IT Passare a mysqueezebox.com per i servizi che non sono supportati dal proprio Squeezebox Server. - NL Ga naar mysqueezebox.com voor services die niet worden ondersteund op je Squeezebox Server. - NO Bytt til mysqueezebox.com for tjenester som ikke støttes av Squeezebox Server. - PL Przełącz się na serwis mysqueezebox.com, aby uzyskać usługi, które nie są obsługiwane w programie Squeezebox Server. - RU Чтобы получить службы, которые не поддерживаются в Squeezebox Server, перейдите к использованию mysqueezebox.com. - SV Gå till mysqueezebox.com för tjänster som inte stöds av Squeezebox Server. + CS Pro služby, které nejsou podporovány na vašem Logitech Media Server přepněte na mysqueezebox.com. + DA Skift til mysqueezebox.com for tjenester som ikke er understøttet af Logitech Media Server. + DE Wechseln Sie zu mysqueezebox.com für eine Auswahl an Diensten, die nicht von Logitech Media Server unterstützt werden. + EN Switch to mysqueezebox.com for services which are not supported on your Logitech Media Server. + ES Cambie a mysqueezebox.com para acceder a los servicios no admitidos en Logitech Media Server. + FI Vaihtamalla mysqueezebox.comiin pääset nauttimaan palveluista, joita Logitech Media Server ei tue. + FR Utilisez mysqueezebox.com pour accéder aux services non pris en charge par votre Logitech Media Server. + IT Passare a mysqueezebox.com per i servizi che non sono supportati dal proprio Logitech Media Server. + NL Ga naar mysqueezebox.com voor services die niet worden ondersteund op je Logitech Media Server. + NO Bytt til mysqueezebox.com for tjenester som ikke støttes av Logitech Media Server. + PL Przełącz się na serwis mysqueezebox.com, aby uzyskać usługi, które nie są obsługiwane w programie Logitech Media Server. + RU Чтобы получить службы, которые не поддерживаются в Logitech Media Server, перейдите к использованию mysqueezebox.com. + SV Gå till mysqueezebox.com för tjänster som inte stöds av Logitech Media Server. diff --git a/Slim/Plugin/SavePlaylist/Plugin.pm b/Slim/Plugin/SavePlaylist/Plugin.pm index de11bb00f74..834957fcce1 100644 --- a/Slim/Plugin/SavePlaylist/Plugin.pm +++ b/Slim/Plugin/SavePlaylist/Plugin.pm @@ -3,7 +3,7 @@ package Slim::Plugin::SavePlaylist::Plugin; # $Id: Plugin.pm 11071 2007-01-01 15:47:59Z adrian $ # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/SavePlaylist/install.xml b/Slim/Plugin/SavePlaylist/install.xml index 3e390100130..95eef0458de 100644 --- a/Slim/Plugin/SavePlaylist/install.xml +++ b/Slim/Plugin/SavePlaylist/install.xml @@ -14,7 +14,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Sirius/install.xml b/Slim/Plugin/Sirius/install.xml index 4c93bbac84e..d605f1a4ecd 100644 --- a/Slim/Plugin/Sirius/install.xml +++ b/Slim/Plugin/Sirius/install.xml @@ -11,7 +11,7 @@ plugins/Sirius/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Slacker/ProtocolHandler.pm b/Slim/Plugin/Slacker/ProtocolHandler.pm index 3992a97c44d..e9571e91a67 100644 --- a/Slim/Plugin/Slacker/ProtocolHandler.pm +++ b/Slim/Plugin/Slacker/ProtocolHandler.pm @@ -23,7 +23,6 @@ my $fav_off = main::SLIM_SERVICE ? 'static/images/playerControl/slacker_fav_but # XXX: Port to new streaming # To support remote streaming (synced players, slimp3/SB1), we need to subclass Protocols::HTTP -# XXX: needs testing in Squeezebox Server sub new { my $class = shift; my $args = shift; diff --git a/Slim/Plugin/Slacker/install.xml b/Slim/Plugin/Slacker/install.xml index 6aa78024762..cb800a08cf2 100644 --- a/Slim/Plugin/Slacker/install.xml +++ b/Slim/Plugin/Slacker/install.xml @@ -11,7 +11,7 @@ plugins/Slacker/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/SlimTris/Plugin.pm b/Slim/Plugin/SlimTris/Plugin.pm index 4b6e7ba3dbb..c4b2e814ad6 100644 --- a/Slim/Plugin/SlimTris/Plugin.pm +++ b/Slim/Plugin/SlimTris/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::SlimTris::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/SlimTris/install.xml b/Slim/Plugin/SlimTris/install.xml index dba74faa221..d6878ff6a46 100644 --- a/Slim/Plugin/SlimTris/install.xml +++ b/Slim/Plugin/SlimTris/install.xml @@ -12,7 +12,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/Snow/Plugin.pm b/Slim/Plugin/Snow/Plugin.pm index 3f9a2682dd9..bcaa4be67fa 100644 --- a/Slim/Plugin/Snow/Plugin.pm +++ b/Slim/Plugin/Snow/Plugin.pm @@ -7,7 +7,7 @@ package Slim::Plugin::Snow::Plugin; # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Snow/install.xml b/Slim/Plugin/Snow/install.xml index b359cef9fd1..63bc6814906 100644 --- a/Slim/Plugin/Snow/install.xml +++ b/Slim/Plugin/Snow/install.xml @@ -14,7 +14,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/SongScanner/Plugin.pm b/Slim/Plugin/SongScanner/Plugin.pm index cefb9ba2d98..4971d85a377 100644 --- a/Slim/Plugin/SongScanner/Plugin.pm +++ b/Slim/Plugin/SongScanner/Plugin.pm @@ -15,7 +15,7 @@ use base qw(Slim::Plugin::Base); # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright (c) 2001-2009 Logitech +# Logitech Media Server Copyright 2001-2011 Logitech # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/SongScanner/install.xml b/Slim/Plugin/SongScanner/install.xml index 09e63896339..a1756368014 100644 --- a/Slim/Plugin/SongScanner/install.xml +++ b/Slim/Plugin/SongScanner/install.xml @@ -8,7 +8,7 @@ e490c2fe-1d5b-4ecc-ba90-d15747a82589 Slim::Plugin::SongScanner::Plugin - Squeezebox Server + Logitech Media Server * 7.0a diff --git a/Slim/Plugin/Sounds/install.xml b/Slim/Plugin/Sounds/install.xml index ea51f400dd6..74f36448a37 100644 --- a/Slim/Plugin/Sounds/install.xml +++ b/Slim/Plugin/Sounds/install.xml @@ -12,7 +12,7 @@ 2 1 - Squeezebox Server + Logitech Media Server 7.0 * diff --git a/Slim/Plugin/SpotifyLogi/install.xml b/Slim/Plugin/SpotifyLogi/install.xml index 6849c782f7b..46d915f1edf 100644 --- a/Slim/Plugin/SpotifyLogi/install.xml +++ b/Slim/Plugin/SpotifyLogi/install.xml @@ -11,7 +11,7 @@ plugins/SpotifyLogi/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.5 * diff --git a/Slim/Plugin/TT/Clients.pm b/Slim/Plugin/TT/Clients.pm index d34b4dfd9c3..7b085f85785 100644 --- a/Slim/Plugin/TT/Clients.pm +++ b/Slim/Plugin/TT/Clients.pm @@ -1,7 +1,7 @@ package Slim::Plugin::TT::Clients; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/TT/Prefs.pm b/Slim/Plugin/TT/Prefs.pm index cfe832f34dc..64bf5d47fae 100644 --- a/Slim/Plugin/TT/Prefs.pm +++ b/Slim/Plugin/TT/Prefs.pm @@ -1,7 +1,7 @@ package Slim::Plugin::TT::Prefs; # $Id: Prefs.pm 1757 2005-01-18 21:22:50Z dsully $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/UPnP/Common/Utils.pm b/Slim/Plugin/UPnP/Common/Utils.pm new file mode 100644 index 00000000000..db75c58602b --- /dev/null +++ b/Slim/Plugin/UPnP/Common/Utils.pm @@ -0,0 +1,406 @@ +package Slim::Plugin::UPnP::Common::Utils; + +### TODO +# +# Add pv namespace to trackDetails, xmlns:pv="http://www.pv.com/pvns/", for example: +# 2 +# 2016 +# 2010-02-10T16:02:37 +# 1261090276 +# 1250180640 + +use strict; + +use Scalar::Util qw(blessed); +use POSIX qw(strftime); +use List::Util qw(min); + +use Slim::Utils::Log; +use Slim::Utils::Prefs; + +use Exporter::Lite; +our @EXPORT_OK = qw(xmlEscape xmlUnescape secsToHMS hmsToSecs absURL trackDetails videoDetails imageDetails); + +my $log = logger('plugin.upnp'); +my $prefs = preferences('server'); + +sub xmlEscape { + my $text = shift; + + if ( $text =~ /[\&\<\>'"]/) { + $text =~ s/&/&/go; + $text =~ s//>/go; + $text =~ s/'/'/go; + $text =~ s/"/"/go; + } + + return $text; +} + +sub xmlUnescape { + my $text = shift; + + if ( $text =~ /[\&]/) { + $text =~ s/&/&/go; + $text =~ s/<//go; + $text =~ s/'/'/go; + $text =~ s/"/"/go; + } + + return $text; +} + +# seconds to H:MM:SS[.F+] +sub secsToHMS { + my $secs = shift; + + my $elapsed = sprintf '%d:%02d:%02d', int($secs / 3600), int($secs / 60), $secs % 60; + + if ( $secs =~ /(\.\d+)$/ ) { + my $frac = sprintf( '%.3f', $1 ); + $frac =~ s/^0//; + $elapsed .= $frac; + } + + return $elapsed; +} + +# H:MM:SS[.F+] to seconds +sub hmsToSecs { + my $hms = shift; + + my ($h, $m, $s) = split /:/, $hms; + + return ($h * 3600) + ($m * 60) + $s; +} + +sub absURL { + my $path = shift; + + my $hostport = Slim::Utils::Network::serverAddr() . ':' . $prefs->get('httpport'); + + return xmlEscape("http://${hostport}${path}"); +} + +sub trackDetails { + my ( $track, $filter ) = @_; + + my $filterall = ($filter eq '*'); + + if ( blessed($track) ) { + # Convert from a Track object + # Going through a titles query request will be the fastest way, to avoid slow DBIC joins and such. + my $request = Slim::Control::Request->new( undef, [ 'titles', 0, 1, 'track_id:' . $track->id, 'tags:AGldyorfTIct' ] ); + $request->execute(); + if ( $request->isStatusError ) { + $log->error('Cannot convert Track object to hashref: ' . $request->getStatusText); + return ''; + } + + my $results = $request->getResults; + if ( $results->{count} != 1 ) { + $log->error('Cannot convert Track object to hashref: no track found'); + return ''; + } + + $track = $results->{titles_loop}->[0]; + } + + my $xml; + + my @albumartists = split /, /, $track->{albumartist}; + my @artists = split /, /, $track->{artist}; + + my $primary_artist = $albumartists[0] ? $albumartists[0] : $artists[0]; + + # This supports either track data from CLI results or _getTagDataForTracks, thus + # the checks for alternate hash keys + + $xml .= 'object.item.audioItem.musicTrack' + . '' . xmlEscape($track->{title} || $track->{'tracks.title'}) . ''; + + if ( $filterall || $filter =~ /dc:creator/ ) { + $xml .= '' . xmlEscape($primary_artist) . ''; + } + + if ( $filterall || $filter =~ /upnp:album/ ) { + $xml .= '' . xmlEscape($track->{album} || $track->{'albums.title'}) . ''; + } + + my %roles; + map { push @{$roles{albumartist}}, $_ } @albumartists; + map { push @{$roles{artist}}, $_ } @artists; + map { push @{$roles{composer}}, $_ } split /, /, $track->{composer}; + map { push @{$roles{conductor}}, $_ } split /, /, $track->{conductor}; + map { push @{$roles{band}}, $_ } split /, /, $track->{band}; + map { push @{$roles{trackartist}}, $_ } split /, /, $track->{trackartist}; + + my $artistfilter = ( $filterall || $filter =~ /upnp:artist/ ); + my $contribfilter = ( $filterall || $filter =~ /dc:contributor/ ); + while ( my ($role, $names) = each %roles ) { + for my $artist ( @{$names} ) { + my $x = xmlEscape($artist); + if ( $artistfilter ) { $xml .= "${x}"; } + if ( $contribfilter ) { $xml .= "${x}"; } + } + } + + if ( my $tracknum = ($track->{tracknum} || $track->{'tracks.tracknum'}) ) { + if ( $filterall || $filter =~ /upnp:originalTrackNumber/ ) { + $xml .= "${tracknum}"; + } + } + + if ( my $date = ($track->{year} || $track->{'tracks.year'}) ) { + if ( $filterall || $filter =~ /dc:date/ ) { + $xml .= "${date}-01-01"; # DLNA requires MM-DD values + } + } + + if ( my @genres = split /, /, $track->{genres} ) { + if ( $filterall || $filter =~ /upnp:genre/ ) { + for my $genre ( @genres ) { + $xml .= '' . xmlEscape($genre) . ''; + } + } + } + + if ( my $coverid = ($track->{coverid} || $track->{'tracks.coverid'}) ) { + if ( $filterall || $filter =~ /upnp:albumArtURI/ ) { + $xml .= '' . absURL("/music/$coverid/cover") . ''; + } + + if ( $filterall || $filter =~ /upnp:icon/ ) { + my $thumbSize = $prefs->get('thumbSize') || 100; + $xml .= '' . absURL("/music/$coverid/cover_${thumbSize}x${thumbSize}_o") . ''; + } + } + + # mtime is used for all values as fallback + my $mtime = $track->{modificationTime} || $track->{'tracks.timestamp'}; + + if ( $filterall || $filter =~ /pv:modificationTime/ ) { + $xml .= "${mtime}"; + } + + if ( $filterall || $filter =~ /pv:addedTime/ ) { + my $added_time = $track->{addedTime} || $track->{'tracks.added_time'} || $mtime; + $xml .= "${added_time}"; + } + + if ( $filterall || $filter =~ /pv:lastUpdated/ ) { + my $updated = $track->{lastUpdated} || $track->{'tracks.updated_time'} || $mtime; + $xml .= "${updated}"; + } + + if ( $filterall || $filter =~ /res/ ) { + my ($bitrate) = $track->{bitrate} =~ /^(\d+)/; + if ( !$bitrate && $track->{'tracks.bitrate'} ) { + $bitrate = $track->{'tracks.bitrate'} / 1000; + } + + # We need to provide a for the native file, as well as compatability formats via transcoding + my $native_type = $Slim::Music::Info::types{ $track->{type} || $track->{'tracks.content_type'} }; + my @other_types; + if ( $native_type ne 'audio/mpeg' ) { + push @other_types, 'audio/mpeg'; + # XXX audio/L16 + } + + for my $type ( $native_type, @other_types ) { + $xml .= '{filesize} || $track->{'tracks.filesize'}) . '"'; + } + if ( $filterall || $filter =~ /res\@duration/ ) { + $xml .= ' duration="' . secsToHMS($track->{duration} || $track->{'tracks.secs'}) . '"'; + } + if ( ($filterall || $filter =~ /res\@bitrate/) && $type eq $native_type ) { + # Bitrate only available for native type + $xml .= ' bitrate="' . (($bitrate * 1000) / 8) . '"'; # yes, it's bytes/second for some reason + } + + if ( my $bps = ($track->{samplesize} || $track->{'tracks.samplesize'}) ) { + if ( $filterall || $filter =~ /res\@bitsPerSample/ ) { + $xml .= " bitsPerSample=\"${bps}\""; + } + } + + if ( $filterall || $filter =~ /res\@sampleFrequency/ ) { + $xml .= ' sampleFrequency="' . ($track->{samplerate} || $track->{'tracks.samplerate'}) . '"'; + } + + my $ext = Slim::Music::Info::mimeToType($type); + + if ( $ext eq 'mp3' ) { + $ext = 'mp3?bitrate=320'; + } + + $xml .= '>' . absURL('/music/' . ($track->{id} || $track->{'tracks.id'}) . '/download.' . $ext) . ''; + } + } + + return $xml; +} + +sub videoDetails { + my ( $video, $filter ) = @_; + + my $filterall = ($filter eq '*'); + + my $xml; + + # This supports either track data from CLI results or _getTagDataForTracks, thus + # the checks for alternate hash keys + + my $hash = $video->{id} || $video->{'videos.id'}; # id is the hash column + + $xml .= 'object.item.videoItem' + . '' . xmlEscape($video->{title} || $video->{'videos.title'}) . ''; + + if ( $filterall || $filter =~ /upnp:album/ ) { + $xml .= '' . xmlEscape($video->{album} || $video->{'videos.album'}) . ''; + } + + if ( $filterall || $filter =~ /upnp:albumArtURI/ ) { + $xml .= '' . absURL("/music/${hash}/cover_300x300_o") . ''; + } + + if ( $filterall || $filter =~ /upnp:icon/ ) { + $xml .= '' . absURL("/music/${hash}/cover_300x300_o") . ''; + } + + # mtime is used for all values as fallback + my $mtime = $video->{mtime} || $video->{'videos.mtime'}; + + if ( $filterall || $filter =~ /pv:modificationTime/ ) { + $xml .= "${mtime}"; + } + + if ( $filterall || $filter =~ /pv:addedTime/ ) { + my $added_time = $video->{added_time} || $video->{'videos.added_time'} || $mtime; + $xml .= "${added_time}"; + } + + if ( $filterall || $filter =~ /pv:lastUpdated/ ) { + my $updated = $video->{updated_time} || $video->{'videos.updated_time'} || $mtime; + $xml .= "${updated}"; + } + + if ( $filterall || $filter =~ /res/ ) { + my ($bitrate) = $video->{bitrate} =~ /^(\d+)/; + if ( !$bitrate && $video->{'videos.bitrate'} ) { + $bitrate = $video->{'videos.bitrate'} / 1000; + } + + my $type = $video->{mime_type} || $video->{'videos.mime_type'}; + + $xml .= '{filesize} || $video->{'videos.filesize'}) . '"'; + } + if ( $filterall || $filter =~ /res\@duration/ ) { + $xml .= ' duration="' . secsToHMS($video->{duration} || $video->{'videos.secs'}) . '"'; + } + if ( ($filterall || $filter =~ /res\@bitrate/) ) { + $xml .= ' bitrate="' . (($bitrate * 1000) / 8) . '"'; # yes, it's bytes/second for some reason + } + if ( ($filterall || $filter =~ /res\@resolution/) ) { + $xml .= ' resolution="' . $video->{width} . 'x' . $video->{height} . '"'; + } + + $xml .= '>' . absURL("/video/${hash}/download") . ''; + } + + return $xml; +} + +sub imageDetails { + my ( $image, $filter ) = @_; + + my $filterall = ($filter eq '*'); + + my $xml; + + # This supports either track data from CLI results or _getTagDataForTracks, thus + # the checks for alternate hash keys + + my $hash = $image->{id} || $image->{'images.id'}; # id is the hash column + + $xml .= 'object.item.imageItem.photo' + . '' . xmlEscape($image->{title} || $image->{'images.title'}) . ''; + + if ( $image->{original_time} ) { + my @time = localtime($image->{original_time}); + + if (scalar @time > 5) { + $xml .= '' . xmlEscape( strftime('%Y-%m-%d', @time) ) . '' + } + } + + if ( $filterall || $filter =~ /upnp:album/ ) { + $xml .= '' . xmlEscape($image->{album} || $image->{'images.album'}) . ''; + } + + if ( $filterall || $filter =~ /upnp:albumArtURI/ ) { + $xml .= '' . absURL("/music/${hash}/cover_300x300_o") . ''; + } + + if ( $filterall || $filter =~ /upnp:icon/ ) { + $xml .= '' . absURL("/music/${hash}/cover_300x300_o") . ''; + } + + # mtime is used for all values as fallback + my $mtime = $image->{mtime} || $image->{'images.mtime'}; + + if ( $filterall || $filter =~ /pv:modificationTime/ ) { + $xml .= "${mtime}"; + } + + if ( $filterall || $filter =~ /pv:addedTime/ ) { + my $added_time = $image->{added_time} || $image->{'images.added_time'} || $mtime; + $xml .= "${added_time}"; + } + + if ( $filterall || $filter =~ /pv:lastUpdated/ ) { + my $updated = $image->{updated_time} || $image->{'images.updated_time'} || $mtime; + $xml .= "${updated}"; + } + + if ( $filterall || $filter =~ /res/ ) { + my $type = $image->{mime_type} || $image->{'images.mime_type'}; + + $xml .= '{filesize} || $image->{'images.filesize'}) . '"'; + } + if ( ($filterall || $filter =~ /res\@resolution/) ) { + $xml .= ' resolution="' . $image->{width} . 'x' . $image->{height} . '"'; + } + + my $maxSize = $prefs->get('maxUPnPImageSize'); + + # if the image isn't default landscape mode, send it through the resizer to fix the orientation + if ( $maxSize || ($image->{orientation} && ($image->{width} || $image->{height})) ) { + # XXX - PlugPlayer fails to display full size rotated images? + # limiting to full HD resolution for now, speeding up rendering considerably + # XXX - don't use image's exact width/height, as this would cause the resizer to short-circuit without rotating the image first... + my $maxSize = min($maxSize || 9999, ($image->{width} || 9999) - 1, ($image->{height} || 9999) - 1); + + $xml .= '>' . absURL("/image/${hash}/cover_${maxSize}x${maxSize}_o") . ''; + } + else { + $xml .= '>' . absURL("/image/${hash}/download") . ''; + } + } + + return $xml; +} + +1; diff --git a/Slim/Plugin/UPnP/Discovery.pm b/Slim/Plugin/UPnP/Discovery.pm new file mode 100644 index 00000000000..f95378c7dc4 --- /dev/null +++ b/Slim/Plugin/UPnP/Discovery.pm @@ -0,0 +1,484 @@ +package Slim::Plugin::UPnP::Discovery; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/Discovery.pm 78831 2011-07-25T16:48:09.710754Z andy $ + +# This module handles UPnP 1.0 discovery advertisements and responses to search requests +# Reference: http://www.upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf +# Section 1. pages 10-22 +# +# Note: Version 1.1 of UPnP is available, but is not implemented here. + +use strict; + +use Digest::MD5 qw(md5_hex); +use HTTP::Date; +use Socket; + +use Slim::Networking::Select; +use Slim::Networking::Async::Socket::UDP; +use Slim::Utils::Log; +use Slim::Utils::Timers; + +my $log = logger('plugin.upnp'); + +use constant SSDP_HOST => '239.255.255.250:1900'; +use constant SSDP_PORT => 1900; + +# socket for both multicasting and unicast replies +my $SOCK; + +my $SERVER; + +# All devices we're notifying about +my %UUIDS; + +sub init { + my $class = shift; + + # Construct Server header for later use + my $details = Slim::Utils::OSDetect::details(); + $SERVER = $details->{os} . '/' . $details->{osArch} . ' UPnP/1.0 SqueezeboxServer/' . $::VERSION . '/' . $::REVISION; + + # Test if we can use ReusePort + my $hasReusePort = eval { + my $s = IO::Socket::INET->new( + Proto => 'udp', + LocalPort => SSDP_PORT, + ReuseAddr => 1, + ReusePort => 1, + ); + $s->close; + return 1; + }; + + # Setup our multicast socket + $SOCK = Slim::Networking::Async::Socket::UDP->new( + LocalPort => SSDP_PORT, + ReuseAddr => 1, + ReusePort => $hasReusePort ? 1 : 0, + ); + + if ( !$SOCK ) { + $log->error("Unable to open UPnP multicast discovery socket: ($!) You may have other UPnP software running or a permissions problem."); + return; + } + + # listen for multicasts on this socket + $SOCK->mcast_add( SSDP_HOST ); + + # This socket will continue to live and receive events as + # long as SqueezeCenter is running + Slim::Networking::Select::addRead( $SOCK, \&_read ); + + $log->info('UPnP Discovery initialized'); + + return 1; +} + +# Stop listening for UPnP events +sub shutdown { + my $class = shift; + + # if anything still left in %UUIDS we need to send byebye's for them + for my $uuid ( keys %UUIDS ) { + $class->unregister($uuid); + } + + if ( defined $SOCK ) { + Slim::Networking::Select::removeRead( $SOCK ); + + $SOCK->close; + + $SOCK = undef; + } + + $log->info('UPnP Discovery shutdown'); +} + +sub server { $SERVER } + +sub _read { + my $sock = shift; + + my $addr = recv $sock, my $ssdp, 1024, 0; + + if ( !defined $addr ) { + $log->is_debug && $log->debug("Read search result failed: $!"); + return; + } + + my ($port, $iaddr) = sockaddr_in($addr); + $iaddr = inet_ntoa($iaddr); + + #main::DEBUGLOG && $log->is_debug && $log->debug( "UPnP Discovery packet from $iaddr:$port:\n$ssdp\n" ); + + if ( $ssdp =~ /^M-SEARCH/ ) { + my ($st) = $ssdp =~ /\sST:\s*([^\s]+)/i; + if ( $st ) { + # See if the search request matches any of our registered devices/services + my ($mx) = $ssdp =~ /MX:\s*([^\s]+)/i; + + # Ignore packets without MX + return unless defined $mx; + + $log->is_debug && $log->debug( "M-SEARCH for $st (mx: $mx)" ); + + # Most devices seem to ignore the mx value and reply quickly + if ( $mx > 3 ) { + $mx = 3; + } + + for my $uuid ( keys %UUIDS ) { + my $msgs = []; + + if ( $st eq 'ssdp:all' ) { + # Send a response for all devices and services + $msgs = __PACKAGE__->_construct_messages( + type => 'all', + %{ $UUIDS{$uuid} }, + ); + } + elsif ( $st eq 'upnp:rootdevice' ) { + # Just the root device + $msgs = __PACKAGE__->_construct_messages( + type => $st, + %{ $UUIDS{$uuid} }, + ); + } + elsif ( $st =~ /uuid:${uuid}/ ) { + # Just the device matching this UUID + $msgs = __PACKAGE__->_construct_messages( + type => 'uuid', + %{ $UUIDS{$uuid} }, + ); + } + elsif ( $st =~ /urn:(.+):(\d+)/ ) { + # A device or service matching this urn, or a prior version + my $search = $1; + my $sver = $2; + + if ( $UUIDS{$uuid}->{device} =~ /$search/ ) { + my ($dver) = $UUIDS{$uuid}->{device} =~ /(\d+)$/; + if ( $sver <= $dver ) { + $msgs = __PACKAGE__->_construct_messages( + type => "urn:$search", + ver => $sver, + %{ $UUIDS{$uuid} }, + ); + } + } + else { + for my $service ( @{ $UUIDS{$uuid}->{services} } ) { + if ( $service =~ /$search/ ) { + my ($servver) = $service =~ /(\d+)$/; + if ( $sver <= $servver ) { + my $new = __PACKAGE__->_construct_messages( + type => "urn:$search", + ver => $sver, + %{ $UUIDS{$uuid} }, + ); + + push @{$msgs}, @{$new}; + } + } + } + } + } + + if ( scalar @{$msgs} ) { + my $url = $UUIDS{$uuid}->{url}; + my $ttl = $UUIDS{$uuid}->{ttl}; + + __PACKAGE__->_advertise( + type => 'reply', + dest => { + addr => $iaddr, + port => $port, + }, + msgs => $msgs, + url => $url, + ttl => $ttl, + mx => $mx, + ); + } + } + } + } +} + +sub register { + my ( $class, %args ) = @_; + + # Remember everything about this UUID, used for replies to M-SEARCH + # and when the device disconnects or the server shuts down + $UUIDS{ $args{uuid} } = \%args; + + # Send a byebye message before any alive messages + $class->_advertise( + type => 'byebye', + msgs => [ { + NT => 'upnp:rootdevice', + USN => 'uuid:' . $args{uuid} . '::upnp:rootdevice', + } ], + ); + + my $msgs = $class->_construct_messages( + type => 'all', + %args, + ); + + $class->_advertise( + type => 'alive', + msgs => $msgs, + url => $args{url}, + ttl => $args{ttl}, + ); + + # Schedule resending of alive packets at random interval less than 1/2 the ttl + my $resend = int( rand( $args{ttl} / 2 ) ); + $log->is_debug && $log->debug( "Will resend notify packets in $resend sec" ); + Slim::Utils::Timers::setTimer( + $class, + time() + $resend, + \&reregister, + \%args, + ); +} + +sub reregister { + my ( $class, $args ) = @_; + + # Make sure UUID still exists, if not the device has disconnected + if ( exists $UUIDS{ $args->{uuid} } ) { + my $msgs = $class->_construct_messages( + type => 'all', + %{$args}, + ); + + $class->_advertise( + type => 'alive', + msgs => $msgs, + url => $args->{url}, + ttl => $args->{ttl}, + ); + + my $resend = int( rand( $args->{ttl}/ 2 ) ); + $log->is_debug && $log->debug( "Will resend notify packets in $resend sec" ); + Slim::Utils::Timers::setTimer( + $class, + time() + $resend, + \&reregister, + $args, + ); + } +} + +sub unregister { + my ( $class, $uuid ) = @_; + + my $msgs = $class->_construct_messages( + type => 'all', + %{ $UUIDS{$uuid} }, + ); + + delete $UUIDS{$uuid}; + + $class->_advertise( + type => 'byebye', + msgs => $msgs, + ); +} + +# Generate a static UUID for a client, using UUID or hash of MAC +sub uuid { + my ( $class, $client ) = @_; + + my @string = split //, $client->uuid || md5_hex( $client->id ); + + splice @string, 8, 0, '-'; + splice @string, 13, 0, '-'; + splice @string, 18, 0, '-'; + splice @string, 23, 0, '-'; + + return uc( join( '', @string ) ); +} + +sub _advertise { + my ( $class, %args ) = @_; + + my $type = $args{type}; + my $dest = $args{dest}; + my $msgs = $args{msgs}; + my $url = $args{url}; + my $ttl = $args{ttl}; + my $mx = $args{mx}; + + my @out; + + if ( $type eq 'byebye' ) { + for my $msg ( @{$msgs} ) { + push @out, join "\x0D\x0A", ( + 'NOTIFY * HTTP/1.1', + 'Host: ' . SSDP_HOST, + 'NT: ' . $msg->{NT}, + 'NTS: ssdp:byebye', + 'USN: ' . $msg->{USN}, + '', '', + ); + } + } + elsif ( $type eq 'alive' ) { + for my $msg ( @{$msgs} ) { + push @out, join "\x0D\x0A", ( + 'NOTIFY * HTTP/1.1', + 'Host: ' . SSDP_HOST, + 'NT: ' . $msg->{NT}, + 'NTS: ssdp:alive', + 'USN: ' . $msg->{USN}, + 'Location: ' . $url, + 'Cache-Control: max-age=' . $ttl, + 'Server: ' . $SERVER, + '', '', + ); + } + } + elsif ( $type eq 'reply' ) { + for my $msg ( @{$msgs} ) { + push @out, join "\x0D\x0A", ( + 'HTTP/1.1 200 OK', + 'Cache-Control: max-age=' . $ttl, + 'Date: ' . time2str(time), + 'Ext: ', + 'Location: ' . $url, + 'Server: ' . $SERVER, + 'ST: ' . ( $msg->{ST} || $msg->{NT} ), + 'USN: ' . $msg->{USN}, + '', '', + ); + } + } + + if ( $type eq 'byebye' ) { + # Send immediately, each packet twice + $log->is_debug && $log->debug( 'Sending ' . scalar(@out) . ' byebye packets' ); + + for my $pkt ( @out ) { + for ( 1..2 ) { + $SOCK->mcast_send( $pkt, SSDP_HOST ); + } + } + } + elsif ( $type eq 'alive') { + # Wait a random interval < 100ms and send the full set of requests + # Send them again 1/2 second later in case one gets lost + my $send = sub { + $log->is_debug && $log->debug( 'Sending ' . scalar(@out) . ' alive packets' ); + for my $pkt ( @out ) { + $SOCK->mcast_send( $pkt, SSDP_HOST ); + } + }; + + Slim::Utils::Timers::setTimer( undef, Time::HiRes::time() + rand(0.1), $send ); + Slim::Utils::Timers::setTimer( undef, Time::HiRes::time() + 0.5, $send ); + } + elsif ( $type eq 'reply' ) { + # send unicast UDP to source IP/port, delayed by random interval less than MX + my $send = sub { + $log->is_debug && $log->debug( + 'Replying to ' . $dest->{addr} . ':' . $dest->{port} + . ' with ' . scalar(@out) . ' packets' + . ': ' . Data::Dump::dump(\@out) + ); + + my $addr = sockaddr_in( $dest->{port}, inet_aton( $dest->{addr} ) ); + + for my $pkt ( @out ) { + $SOCK->send( $pkt, 0, $addr ) or die "Unable to send UDP reply packet: $!"; + } + }; + + Slim::Utils::Timers::setTimer( + undef, + Time::HiRes::time() + rand($mx), + $send, + ); + } +} + +sub _construct_messages { + my ( $class, %args ) = @_; + + my $type = delete $args{type}; + + my @msgs; + + if ( $type eq 'all' ) { + # 3 discovery messages for the root device + push @msgs, { + NT => 'upnp:rootdevice', + USN => 'uuid:' . $args{uuid} . '::upnp:rootdevice', + }; + + push @msgs, { + NT => 'uuid:' . $args{uuid}, + USN => 'uuid:' . $args{uuid}, + }; + + push @msgs, { + NT => $args{device}, + USN => 'uuid:' . $args{uuid} . '::' . $args{device}, + }; + + # No support for embedded devices + + # 1 discovery message per service + for my $service ( @{ $args{services} } ) { + push @msgs, { + NT => $service, + USN => 'uuid:' . $args{uuid} . '::' . $service, + }; + } + } + elsif ( $type eq 'upnp:rootdevice' ) { + # 1 message for the root device + push @msgs, { + NT => 'upnp:rootdevice', + USN => 'uuid:' . $args{uuid} . '::upnp:rootdevice', + }; + } + elsif ( $type eq 'uuid' ) { + # 1 message for this UUID + push @msgs, { + NT => 'uuid:' . $args{uuid}, + USN => 'uuid:' . $args{uuid}, + }; + } + elsif ( $type =~ /^urn:(.+)/ ) { + # 1 message for this device or service + my $search = $1; + my $ver = $args{ver}; + + if ( $args{device} =~ /$search/ ) { + my $nt = 'urn:' . $search . ':' . $ver; + push @msgs, { + NT => $nt, + USN => 'uuid:' . $args{uuid} . '::' . $nt, + }; + } + else { + for my $service ( @{ $args{services} } ) { + if ( $service =~ /$search/ ) { + my $nt = 'urn:' . $search . ':' . $ver; + push @msgs, { + NT => $nt, + USN => 'uuid:' . $args{uuid} . '::' . $nt, + }; + } + } + } + } + + return \@msgs; +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/Events.pm b/Slim/Plugin/UPnP/Events.pm new file mode 100644 index 00000000000..05b63aabe13 --- /dev/null +++ b/Slim/Plugin/UPnP/Events.pm @@ -0,0 +1,469 @@ +package Slim::Plugin::UPnP::Events; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/Events.pm 75368 2010-12-16T04:09:11.731914Z andy $ +# +# Eventing functions + +use strict; + +use HTTP::Daemon; +use HTTP::Date; +use URI; +use URI::QueryParam; + +use Slim::Networking::Async; +use Slim::Networking::Select; +use Slim::Utils::Errno; +use Slim::Utils::Log; +use Slim::Utils::Timers; + +use Slim::Plugin::UPnP::Common::Utils qw(xmlEscape); + +my $log = logger('plugin.upnp'); + +# Server socket +my $SERVER; + +# subscriptions +my %SUBS = (); + +sub init { + my $class = shift; + + # We can't use Slim::Web::HTTP for GENA requests because + # they aren't really HTTP. Open up a new socket for these requests + # on a random port number. + $SERVER = HTTP::Daemon->new( + Listen => SOMAXCONN, + ReuseAddr => 1, + Reuse => 1, + Timeout => 1, + ); + + if ( !$SERVER ) { + $log->error("Unable to open UPnP GENA server socket: $!"); + return; + } + + Slim::Networking::Select::addRead( $SERVER, \&accept ); + + return 1; +} + +sub port { $SERVER->sockport } + +sub shutdown { + my $class = shift; + + Slim::Networking::Select::removeRead($SERVER); + + $SERVER = undef; +} + +# Event subscription messages +sub accept { + my $sock = shift; + + my $httpClient = $sock->accept || return; + + if ( $httpClient->connected() ) { + Slim::Utils::Network::blocking( $httpClient, 0 ); + $httpClient->timeout(10); + Slim::Networking::Select::addRead( $httpClient, \&request ); + } +} + +sub request { + my $httpClient = shift; + + my $request = $httpClient->get_request; + + if ( !defined $request ) { + closeHTTP($httpClient); + return; + } + + my $response; + my $uuid; + + $log->is_debug && $log->debug( $request->method . ' ' . $request->uri ); + + if ( $request->method eq 'SUBSCRIBE' ) { + ($response, $uuid) = subscribe($request); + } + elsif ( $request->method eq 'UNSUBSCRIBE' ) { + $response = unsubscribe($request); + } + + ${*$httpClient}{passthrough} = [ $response, $uuid ]; + + Slim::Networking::Select::addWrite( $httpClient, \&sendResponse ); +} + +sub sendResponse { + my ( $httpClient, $response, $uuid, $len, $off ) = @_; + + if ( !$httpClient->connected ) { + closeHTTP($httpClient); + return; + } + + use bytes; + + my $sent = 0; + $off ||= 0; + + if ( !defined $len ) { + $len = length($response); + } + + $sent = syswrite $httpClient, $response, $len, $off; + + if ( $! == EWOULDBLOCK ) { + if ( !defined $sent ) { + $sent = 0; + } + } + + if ( !defined $sent ) { + $log->is_debug && $log->debug( "sendResponse failed: $!" ); + closeHTTP($httpClient); + return; + } + + if ( $sent < $len ) { + $len -= $sent; + $off += $sent; + + $log->is_debug && $log->debug( "sent partial response: $sent ($len left)" ); + + # Next time we're called, pass through new len/off values + ${*$httpClient}{passthrough} = [ $response, $uuid, $len, $off ]; + } + else { + # After we're done sending, if we have a uuid, flag it as an active subscription + if ( $uuid ) { + $log->is_debug && $log->debug( "Sub $uuid is now active" ); + $SUBS{ $uuid }->{active} = 1; + } + + closeHTTP($httpClient); + return; + } +} + +sub closeHTTP { + my $httpClient = shift; + + Slim::Networking::Select::removeRead($httpClient); + Slim::Networking::Select::removeWrite($httpClient); + + $httpClient->close; +} + +sub subscribe { + my $request = shift; + + my $uuid; + my $timeout; + + if ( my $sid = $request->header('Sid') ) { + # Renewal + ($uuid) = $sid =~ /uuid:([^\s]+)/; + ($timeout) = $request->header('Timeout') =~ /Second-(\d+)/i; + + if ( !defined $timeout ) { + $timeout = 300; + } + + if ( $request->header('NT') || $request->header('Callback') ) { + return error('400 Bad Request'); + } + + if ( !$uuid || !exists $SUBS{ $uuid } ) { + return error('412 Precondition Failed'); + } + + $log->is_debug && $log->debug( "Renewed: $uuid ($timeout sec)" ); + + # Refresh the timer + Slim::Utils::Timers::killTimers( $uuid, \&expire ); + Slim::Utils::Timers::setTimer( $uuid, time() + $timeout, \&expire ); + } + else { + # Subscribe + + # Verify request is correct + if ( !$request->header('NT') || $request->header('NT') ne 'upnp:event' ) { + return error('400 Bad Request'); + } + + # Verify player param + my $client; + my $id = $request->uri->query_param('player'); + + if ( $id ) { + $client = Slim::Player::Client::getClient($id); + if ( !$client ) { + return error('500 Invalid Player'); + } + } + + # Verify callback is present + if ( !$request->header('Callback') ) { + return error('412 Missing Callback'); + } + + my @callbacks = $request->header('Callback') =~ /<([^>]+)>/g; + ($timeout) = $request->header('Timeout') =~ /Second-(\d+)/i; + + if ( !scalar @callbacks ) { + return error('412 Missing Callback'); + } + + if ( !defined $timeout ) { + $timeout = 300; + } + + my ($service) = $request->uri->path =~ m{plugins/UPnP/(.+)/eventsub}; + $service =~ s{/}{::}g; + my $serviceClass = "Slim::Plugin::UPnP::$service"; + + $uuid = random_uuid(); + + $SUBS{ $uuid } = { + active => 0, # Sub is not active until we send it to the subscriber + client => $client ? $client->id : 0, + service => $serviceClass, + callbacks => \@callbacks, + expires => time() + $timeout, + key => -1, # will get increased to 0 when first sent + }; + + # Set a timer to expire this subscription + Slim::Utils::Timers::killTimers( $uuid, \&expire ); + Slim::Utils::Timers::setTimer( $uuid, time() + $timeout, \&expire ); + + main::INFOLOG && $log->is_info && $log->info( "Subscribe: $uuid ($serviceClass) ($timeout sec) -> " . join(', ', @callbacks) ); + + # Inform the service of the subscription for this client + # The service will send the initial event state by calling notify() + $serviceClass->subscribe( $client, $uuid ); + } + + my $response = join "\x0D\x0A", ( + 'HTTP/1.1 200 OK', + 'Date: ' . time2str( time() ), + 'Server: ' . Slim::Plugin::UPnP::Discovery->server, + 'Content-Length: 0', + 'SID: uuid:' . $uuid, + 'Timeout: Second-' . $timeout, + '', '', + ); + + return ($response, $uuid); +} + +sub unsubscribe { + my $request = shift; + + my $uuid; + + if ( $request->header('NT') || $request->header('Callback') ) { + return error('400 Bad Request'); + } + + if ( my $sid = $request->header('Sid') ) { + ($uuid) = $sid =~ /uuid:([^\s]+)/; + + if ( !$uuid || !exists $SUBS{ $uuid } ) { + return error('412 Precondition Failed'); + } + + # Verify player param + my $client; + my $id = $request->uri->query_param('player'); + + if ( $id ) { + $client = Slim::Player::Client::getClient($id); + if ( !$client ) { + return error('500 Invalid Player'); + } + } + + Slim::Utils::Timers::killTimers( $uuid, \&expire ); + + # Inform the service of the unsubscription for this client + my $serviceClass = $SUBS{ $uuid }->{service}; + + main::INFOLOG && $log->is_info && $log->info( "Unsubscribe: $uuid ($serviceClass)" ); + + $serviceClass->unsubscribe( $client ); + + delete $SUBS{ $uuid }; + + my $response = join "\x0D\x0A", ( + 'HTTP/1.1 200 OK', + '', '', + ); + + return $response; + } + else { + return error('400 Bad Request'); + } +} + +sub error { + my $error = shift; + + $log->error( 'Subscribe/unsubscribe error: ' . $error ); + + return join "\x0D\x0A", ( + 'HTTP/1.1 ' . $error, + 'Date: ' . time2str( time() ), + 'Server: ' . Slim::Plugin::UPnP::Discovery->server, + '', '', + ); +} + +# Notify for either a UUID or a clientid +sub notify { + my ( $class, %args ) = @_; + + my $service = $args{service}; + my $id = $args{id}; + my $data = $args{data}; + + # Construct notify XML + my $wrapper = qq{ + +}; + + while ( my ($k, $v) = each %{$data} ) { + $wrapper .= " <$k>" . xmlEscape($v) . "\n"; + } + + $wrapper .= "\n"; + + while ( my ($uuid, $sub) = each %SUBS ) { + # $id may be either a client id or a UUID + if ( $id eq $sub->{client} || $id eq $uuid ) { + if ( $service eq $sub->{service} ) { + # Increase send key + if ( $sub->{key} == 4294967295 ) { + $sub->{key} = 1; + } + else { + $sub->{key}++; + } + + sendNotify( $uuid, $sub, $wrapper ); + } + } + } +} + +sub sendNotify { + my ( $uuid, $sub, $xml ) = @_; + + # Has the subscription been unsubscribed? + if ( !exists $SUBS{ $uuid } ) { + return; + } + + # If this subscription is not yet active, + # i.e. it is new and the response to the initial + # subscribe request has not yet been sent, + # we must wait before sending anything + if ( !$SUBS{ $uuid }->{active} ) { + $log->is_debug && $log->debug( "Delaying notify for $uuid, not yet active" ); + Slim::Utils::Timers::setTimer( $uuid, Time::HiRes::time() + 0.2, \&sendNotify, $sub, $xml ); + return; + } + + use bytes; + + my $url = $sub->{callbacks}->[0]; + + my $uri = URI->new($url); + my $host = $uri->host; + my $port = $uri->port || 80; + + my $notify = join "\x0D\x0A", ( + 'NOTIFY ' . $uri->path_query . ' HTTP/1.1', + "Host: $host:$port", + 'Content-Type: text/xml; charset="utf-8"', + 'Content-Length: ' . length($xml), + 'NT: upnp:event', + 'NTS: upnp:propchange', + 'SID: uuid:' . $uuid, + 'SEQ: ' . $sub->{key}, + '', + $xml, + ); + + if ( main::INFOLOG && $log->is_info ) { + $log->info( "Notifying to $host:$port for " . $sub->{client} . " / " . $sub->{service} ); + $log->debug($notify); + } + + # XXX use AnyEvent::Socket instead? + + my $async = Slim::Networking::Async->new; + $async->write_async( { + host => $uri->host, + port => $uri->port, + content_ref => \$notify, + Timeout => 30, + onError => sub { + $log->warn( 'Event failed to notify to ' . $uri->host . ':' . $uri->port . ': ' . $_[1] ); + # XXX: try next callback URL, may not be required per DLNA + }, + onRead => sub { + my $a = shift; + + sysread $a->socket, my $res, 1024; + + Slim::Networking::Select::removeError( $a->socket ); + Slim::Networking::Select::removeRead( $a->socket ); + + $a->disconnect; + + main::DEBUGLOG && $log->is_debug && $log->debug( 'Event notified OK' ); + }, + } ); +} + +sub expire { + my $uuid = shift; + + if ( exists $SUBS{ $uuid } ) { + # Inform the service of the unsubscription for this client + my $serviceClass = $SUBS{ $uuid }->{service}; + my $clientid = $SUBS{ $uuid }->{client}; + + my $client = Slim::Player::Client::getClient($clientid); + $serviceClass->unsubscribe( $client ); + + delete $SUBS{ $uuid }; + + $log->is_debug && $log->debug( "Expired $uuid ($serviceClass)" ); + } +} + +sub random_uuid { + my @chars = ('A'..'F', 0..9); + + my @string; + push @string, $chars[ int( rand(16) ) ] for ( 1..32 ); + + splice @string, 8, 0, '-'; + splice @string, 13, 0, '-'; + splice @string, 18, 0, '-'; + splice @string, 23, 0, '-'; + + return join( '', @string ); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer.xml new file mode 100644 index 00000000000..d1fe0bf4747 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer.xml @@ -0,0 +1,52 @@ + + + + 1 + 0 + + + urn:schemas-upnp-org:device:MediaRenderer:1 + [% device.name %] + Logitech + http://www.mysqueezebox.com + Logitech Media Server UPnP/DLNA Plugin + [% device.model %] + 1 + [% device.url %] + [% device.serial %] + uuid:[% device.uuid %] + + + image/png + 250 + 250 + 24 + [% device.icon %] + + + + + urn:schemas-upnp-org:service:RenderingControl:1 + urn:upnp-org:serviceId:RenderingControl + /plugins/UPnP/MediaRenderer/RenderingControl.xml + /plugins/UPnP/MediaRenderer/RenderingControl/control?player=[% device.id_esc %] + http://[% eventAddr %]/plugins/UPnP/MediaRenderer/RenderingControl/eventsub?player=[% device.id_esc %] + + + urn:schemas-upnp-org:service:ConnectionManager:1 + urn:upnp-org:serviceId:ConnectionManager + /plugins/UPnP/MediaRenderer/ConnectionManager.xml + /plugins/UPnP/MediaRenderer/ConnectionManager/control?player=[% device.id_esc %] + http://[% eventAddr %]/plugins/UPnP/MediaRenderer/ConnectionManager/eventsub?player=[% device.id_esc %] + + + urn:schemas-upnp-org:service:AVTransport:1 + urn:upnp-org:serviceId:AVTransport + /plugins/UPnP/MediaRenderer/AVTransport.xml + /plugins/UPnP/MediaRenderer/AVTransport/control?player=[% device.id_esc %] + http://[% eventAddr %]/plugins/UPnP/MediaRenderer/AVTransport/eventsub?player=[% device.id_esc %] + + + [% serverURL %] + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/AVTransport.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/AVTransport.xml new file mode 100644 index 00000000000..347f49ac410 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/AVTransport.xml @@ -0,0 +1,500 @@ + + + + 1 + 0 + + + + SetAVTransportURI + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + CurrentURI + in + AVTransportURI + + + CurrentURIMetaData + in + AVTransportURIMetaData + + + + + SetNextAVTransportURI + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + NextURI + in + NextAVTransportURI + + + NextURIMetaData + in + NextAVTransportURIMetaData + + + + + GetMediaInfo + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + NrTracks + out + NumberOfTracks + + + MediaDuration + out + CurrentMediaDuration + + + CurrentURI + out + AVTransportURI + + + CurrentURIMetaData + out + AVTransportURIMetaData + + + NextURI + out + NextAVTransportURI + + + NextURIMetaData + out + NextAVTransportURIMetaData + + + PlayMedium + out + PlaybackStorageMedium + + + RecordMedium + out + RecordStorageMedium + + + WriteStatus + out + RecordMediumWriteStatus + + + + + GetTransportInfo + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + CurrentTransportState + out + TransportState + + + CurrentTransportStatus + out + TransportStatus + + + CurrentSpeed + out + TransportPlaySpeed + + + + + GetPositionInfo + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Track + out + CurrentTrack + + + TrackDuration + out + CurrentTrackDuration + + + TrackMetaData + out + CurrentTrackMetaData + + + TrackURI + out + CurrentTrackURI + + + RelTime + out + RelativeTimePosition + + + AbsTime + out + AbsoluteTimePosition + + + RelCount + out + RelativeCounterPosition + + + AbsCount + out + AbsoluteCounterPosition + + + + + GetDeviceCapabilities + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + PlayMedia + out + PossiblePlaybackStorageMedia + + + RecMedia + out + PossibleRecordStorageMedia + + + RecQualityMode + out + PossibleRecordQualityModes + + + + + GetTransportSettings + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + PlayMode + out + CurrentPlayMode + + + RecQualityMode + out + CurrentRecordQualityMode + + + + + Stop + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + + + Play + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Speed + in + TransportPlaySpeed + + + + + Pause + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + + + Seek + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Unit + in + A_ARG_TYPE_SeekMode + + + Target + in + A_ARG_TYPE_SeekTarget + + + + + Next + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + + + Previous + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + + + SetPlayMode + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + NewPlayMode + in + CurrentPlayMode + + + + + GetCurrentTransportActions + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Actions + out + CurrentTransportActions + + + + + + + TransportState + string + + STOPPED + PLAYING + TRANSITIONING + PAUSED_PLAYBACK + NO_MEDIA_PRESENT + + + + TransportStatus + string + + OK + ERROR_OCCURRED + + + + PlaybackStorageMedium + string + + HDD + NETWORK + NONE + SD + + + + RecordStorageMedium + string + + NOT_IMPLEMENTED + + + + PossiblePlaybackStorageMedia + string + + + PossibleRecordStorageMedia + string + + + CurrentPlayMode + string + + NORMAL + SHUFFLE + REPEAT_ONE + REPEAT_ALL + + NORMAL + + + TransportPlaySpeed + string + + 1 + + + + RecordMediumWriteStatus + string + + NOT_IMPLEMENTED + + + + CurrentRecordQualityMode + string + + NOT_IMPLEMENTED + + + + PossibleRecordQualityModes + string + + + NumberOfTracks + ui4 + + 0 + 65536 + + + + CurrentTrack + ui4 + + 0 + 65536 + 1 + + + + CurrentTrackDuration + string + + + CurrentMediaDuration + string + + + CurrentTrackMetaData + string + + + CurrentTrackURI + string + + + AVTransportURI + string + + + AVTransportURIMetaData + string + + + NextAVTransportURI + string + + + NextAVTransportURIMetaData + string + + + RelativeTimePosition + string + + + AbsoluteTimePosition + string + + + RelativeCounterPosition + i4 + + + AbsoluteCounterPosition + ui4 + + + CurrentTransportActions + string + + + LastChange + string + + + A_ARG_TYPE_SeekMode + string + + ABS_TIME + REL_TIME + + + + A_ARG_TYPE_SeekTarget + string + + + A_ARG_TYPE_InstanceID + ui4 + + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/ConnectionManager.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/ConnectionManager.xml new file mode 100644 index 00000000000..6a365329448 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/ConnectionManager.xml @@ -0,0 +1,132 @@ + + + + 1 + 0 + + + + GetProtocolInfo + + + Source + out + SourceProtocolInfo + + + Sink + out + SinkProtocolInfo + + + + + GetCurrentConnectionIDs + + + ConnectionIDs + out + CurrentConnectionIDs + + + + + GetCurrentConnectionInfo + + + ConnectionID + in + A_ARG_TYPE_ConnectionID + + + RcsID + out + A_ARG_TYPE_RcsID + + + AVTransportID + out + A_ARG_TYPE_AVTransportID + + + ProtocolInfo + out + A_ARG_TYPE_ProtocolInfo + + + PeerConnectionManager + out + A_ARG_TYPE_ConnectionManager + + + PeerConnectionID + out + A_ARG_TYPE_ConnectionID + + + Direction + out + A_ARG_TYPE_Direction + + + Status + out + A_ARG_TYPE_ConnectionStatus + + + + + + + SourceProtocolInfo + string + + + SinkProtocolInfo + string + + + CurrentConnectionIDs + string + + + A_ARG_TYPE_ConnectionStatus + string + + OK + ContentFormatMismatch + InsufficientBandwidth + UnreliableChannel + Unknown + + + + A_ARG_TYPE_ConnectionManager + string + + + A_ARG_TYPE_Direction + string + + Input + Output + + + + A_ARG_TYPE_ProtocolInfo + string + + + A_ARG_TYPE_ConnectionID + i4 + + + A_ARG_TYPE_AVTransportID + i4 + + + A_ARG_TYPE_RcsID + i4 + + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/RenderingControl.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/RenderingControl.xml new file mode 100644 index 00000000000..a0ea528c810 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaRenderer/RenderingControl.xml @@ -0,0 +1,199 @@ + + + + 1 + 0 + + + + ListPresets + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + CurrentPresetNameList + out + PresetNameList + + + + + SelectPreset + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + PresetName + in + A_ARG_TYPE_PresetName + + + + + GetBrightness + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + CurrentBrightness + out + Brightness + + + + + SetBrightness + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + DesiredBrightness + in + Brightness + + + + + GetMute + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Channel + in + A_ARG_TYPE_Channel + + + CurrentMute + out + Mute + + + + + SetMute + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Channel + in + A_ARG_TYPE_Channel + + + DesiredMute + in + Mute + + + + + GetVolume + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Channel + in + A_ARG_TYPE_Channel + + + CurrentVolume + out + Volume + + + + + SetVolume + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + Channel + in + A_ARG_TYPE_Channel + + + DesiredVolume + in + Volume + + + + + + + PresetNameList + string + + + LastChange + string + + + Brightness + ui2 + + 0 + 5 + 1 + + + + Mute + boolean + + + Volume + ui2 + + 0 + 100 + 1 + + + + A_ARG_TYPE_Channel + string + + Master + + + + A_ARG_TYPE_InstanceID + ui4 + + + A_ARG_TYPE_PresetName + string + + FactoryDefaults + + + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer.xml new file mode 100644 index 00000000000..89e3c2631a6 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer.xml @@ -0,0 +1,80 @@ + + + + 1 + 0 + + + urn:schemas-upnp-org:device:MediaServer:1 + [% device.name %] + Logitech + http://www.mysqueezebox.com + Logitech Media Server UPnP/DLNA Plugin + Logitech Media Server [% device.version %] + 1 + http://www.mysqueezebox.com/download + [% device.serial %] + uuid:[% device.uuid %] + + + image/png + 512 + 512 + 24 + /plugins/UPnP/logo_512x512.png + + + image/png + 250 + 250 + 24 + /plugins/UPnP/logo_250x250.png + + + image/png + 120 + 120 + 24 + /plugins/UPnP/logo_120x120.png + + + image/png + 48 + 48 + 24 + /plugins/UPnP/logo_48x48.png + + + image/png + 32 + 32 + 24 + /plugins/UPnP/logo_32x32.png + + + + + urn:schemas-upnp-org:service:ContentDirectory:1 + urn:upnp-org:serviceId:ContentDirectory + /plugins/UPnP/MediaServer/ContentDirectory.xml + /plugins/UPnP/MediaServer/ContentDirectory/control + http://[% eventAddr %]/plugins/UPnP/MediaServer/ContentDirectory/eventsub + + + urn:schemas-upnp-org:service:ConnectionManager:1 + urn:upnp-org:serviceId:ConnectionManager + /plugins/UPnP/MediaServer/ConnectionManager.xml + /plugins/UPnP/MediaServer/ConnectionManager/control + http://[% eventAddr %]/plugins/UPnP/MediaServer/ConnectionManager/eventsub + + + urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1 + urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar + /plugins/UPnP/MediaServer/MediaReceiverRegistrar.xml + /plugins/UPnP/MediaServer/MediaReceiverRegistrar/control + http://[% eventAddr %]/plugins/UPnP/MediaServer/MediaReceiverRegistrar/eventsub + + + [% serverURL %] + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/ConnectionManager.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/ConnectionManager.xml new file mode 100644 index 00000000000..6a365329448 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/ConnectionManager.xml @@ -0,0 +1,132 @@ + + + + 1 + 0 + + + + GetProtocolInfo + + + Source + out + SourceProtocolInfo + + + Sink + out + SinkProtocolInfo + + + + + GetCurrentConnectionIDs + + + ConnectionIDs + out + CurrentConnectionIDs + + + + + GetCurrentConnectionInfo + + + ConnectionID + in + A_ARG_TYPE_ConnectionID + + + RcsID + out + A_ARG_TYPE_RcsID + + + AVTransportID + out + A_ARG_TYPE_AVTransportID + + + ProtocolInfo + out + A_ARG_TYPE_ProtocolInfo + + + PeerConnectionManager + out + A_ARG_TYPE_ConnectionManager + + + PeerConnectionID + out + A_ARG_TYPE_ConnectionID + + + Direction + out + A_ARG_TYPE_Direction + + + Status + out + A_ARG_TYPE_ConnectionStatus + + + + + + + SourceProtocolInfo + string + + + SinkProtocolInfo + string + + + CurrentConnectionIDs + string + + + A_ARG_TYPE_ConnectionStatus + string + + OK + ContentFormatMismatch + InsufficientBandwidth + UnreliableChannel + Unknown + + + + A_ARG_TYPE_ConnectionManager + string + + + A_ARG_TYPE_Direction + string + + Input + Output + + + + A_ARG_TYPE_ProtocolInfo + string + + + A_ARG_TYPE_ConnectionID + i4 + + + A_ARG_TYPE_AVTransportID + i4 + + + A_ARG_TYPE_RcsID + i4 + + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/ContentDirectory.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/ContentDirectory.xml new file mode 100644 index 00000000000..9c3068b2fcc --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/ContentDirectory.xml @@ -0,0 +1,221 @@ + + + + 1 + 0 + + + + GetSearchCapabilities + + + SearchCaps + out + SearchCapabilities + + + + + GetSortCapabilities + + + SortCaps + out + SortCapabilities + + + + + GetSystemUpdateID + + + Id + out + SystemUpdateID + + + + + Browse + + + ObjectID + in + A_ARG_TYPE_ObjectID + + + BrowseFlag + in + A_ARG_TYPE_BrowseFlag + + + Filter + in + A_ARG_TYPE_Filter + + + StartingIndex + in + A_ARG_TYPE_Index + + + RequestedCount + in + A_ARG_TYPE_Count + + + SortCriteria + in + A_ARG_TYPE_SortCriteria + + + Result + out + A_ARG_TYPE_Result + + + NumberReturned + out + A_ARG_TYPE_Count + + + TotalMatches + out + A_ARG_TYPE_Count + + + UpdateID + out + A_ARG_TYPE_UpdateID + + + + + Search + + + ContainerID + in + A_ARG_TYPE_ObjectID + + + SearchCriteria + in + A_ARG_TYPE_SearchCriteria + + + Filter + in + A_ARG_TYPE_Filter + + + StartingIndex + in + A_ARG_TYPE_Index + + + RequestedCount + in + A_ARG_TYPE_Count + + + SortCriteria + in + A_ARG_TYPE_SortCriteria + + + Result + out + A_ARG_TYPE_Result + + + NumberReturned + out + A_ARG_TYPE_Count + + + TotalMatches + out + A_ARG_TYPE_Count + + + UpdateID + out + A_ARG_TYPE_UpdateID + + + + + + + SearchCapabilities + no + string + + + SortCapabilities + no + string + + + SystemUpdateID + yes + ui4 + + + + ContainerUpdateIDs + yes + string + + + A_ARG_TYPE_ObjectID + no + string + + + A_ARG_TYPE_Result + no + string + + + A_ARG_TYPE_SearchCriteria + no + string + + + A_ARG_TYPE_BrowseFlag + no + string + + BrowseMetadata + BrowseDirectChildren + + + + A_ARG_TYPE_Filter + no + string + + + A_ARG_TYPE_SortCriteria + no + string + + + A_ARG_TYPE_Index + no + ui4 + + + A_ARG_TYPE_Count + no + ui4 + + + A_ARG_TYPE_UpdateID + no + ui4 + + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/MediaReceiverRegistrar.xml b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/MediaReceiverRegistrar.xml new file mode 100644 index 00000000000..fb9daae9864 --- /dev/null +++ b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/MediaServer/MediaReceiverRegistrar.xml @@ -0,0 +1,88 @@ + + + + 1 + 0 + + + + IsAuthorized + + + DeviceID + in + A_ARG_TYPE_DeviceID + + + Result + out + A_ARG_TYPE_Result + + + + + RegisterDevice + + + RegistrationReqMsg + in + A_ARG_TYPE_RegistrationReqMsg + + + RegistrationRespMsg + out + A_ARG_TYPE_RegistrationRespMsg + + + + + IsValidated + + + DeviceID + in + A_ARG_TYPE_DeviceID + + + Result + out + A_ARG_TYPE_Result + + + + + + + A_ARG_TYPE_DeviceID + string + + + A_ARG_TYPE_Result + int + + + A_ARG_TYPE_RegistrationReqMsg + bin.base64 + + + A_ARG_TYPE_RegistrationRespMsg + bin.base64 + + + AuthorizationGrantedUpdateID + ui4 + + + AuthorizationDeniedUpdateID + ui4 + + + ValidationSucceededUpdateID + ui4 + + + ValidationRevokedUpdateID + ui4 + + + diff --git a/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/logo.png b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/logo.png new file mode 100644 index 00000000000..ecec6906cb4 Binary files /dev/null and b/Slim/Plugin/UPnP/HTML/EN/plugins/UPnP/logo.png differ diff --git a/Slim/Plugin/UPnP/MediaRenderer.pm b/Slim/Plugin/UPnP/MediaRenderer.pm new file mode 100644 index 00000000000..d3459dbc428 --- /dev/null +++ b/Slim/Plugin/UPnP/MediaRenderer.pm @@ -0,0 +1,218 @@ +package Slim::Plugin::UPnP::MediaRenderer; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaRenderer.pm 75368 2010-12-16T04:09:11.731914Z andy $ + +use strict; + +use URI::Escape qw(uri_escape uri_unescape); + +use Slim::Plugin::UPnP::Discovery; +use Slim::Plugin::UPnP::MediaRenderer::RenderingControl; +use Slim::Plugin::UPnP::MediaRenderer::ConnectionManager; +use Slim::Plugin::UPnP::MediaRenderer::AVTransport; +use Slim::Plugin::UPnP::MediaRenderer::ProtocolHandler; +use Slim::Plugin::UPnP::Common::Utils qw(xmlEscape); + +use Slim::Control::Request; +use Slim::Utils::Log; +use Slim::Utils::Prefs; +use Slim::Web::HTTP; + +my $log = logger('plugin.upnp'); + +# Some meta info about each player type for the description file +my %models = ( + slimp3 => { + modelName => 'SliMP3', + url => 'http://wiki.slimdevices.com/index.php/SLIMP3', + icon => '/html/images/Players/slimp3_250x250.png', + }, + Squeezebox => { + modelName => 'Squeezebox 1', + url => 'http://wiki.slimdevices.com/index.php/Squeezebox', + icon => '/html/images/Players/squeezebox_250x250.png', + }, + squeezebox2 => { + modelName => 'Squeezebox 2', + url => 'http://wiki.slimdevices.com/index.php/Squeezebox2', + icon => '/html/images/Players/squeezebox_250x250.png', + }, + squeezebox3 => { + modelName => 'Squeezebox 3', + url => 'http://www.slimdevices.com/pi_squeezebox.html', + icon => '/html/images/Players/squeezebox3_250x250.png', + }, + transporter => { + modelName => 'Transporter', + url => 'http://www.slimdevices.com/pi_transporter.html', + icon => '/html/images/Players/transporter_250x250.png', + }, + receiver => { + modelName => 'Squeezebox Receiver', + url => 'http://www.slimdevices.com/pi_receiver.html', + icon => '/html/images/Players/receiver_250x250.png', + }, + boom => { + modelName => 'Squeezebox Boom', + url => 'http://www.slimdevices.com/pi_boom.html', + icon => '/html/images/Players/boom_250x250.png', + }, + softsqueeze => { + modelName => 'Softsqueeze', + url => 'http://wiki.slimdevices.com/index.php/SoftSqueeze', + icon => '/html/images/Players/softsqueeze_250x250.png', + }, + controller => { + modelName => 'Squeezebox Controller', + url => 'http://www.slimdevices.com/pi_controller.html', + icon => '/html/images/Players/controller_250x250.png', + }, + squeezeplay => { + modelName => 'SqueezePlay', + url => 'http://wiki.slimdevices.com/index.php/SqueezePlay', + icon => '/html/images/Players/squeezeplay_250x250.png', + }, + baby => { + modelName => 'Squeezebox Radio', + url => 'http://wiki.slimdevices.com/index.php/Squeezebox_Radio', + icon => '/html/images/Players/baby_250x250.png', + }, + fab4 => { + modelName => 'Squeezebox Touch', + url => 'http://wiki.slimdevices.com/index.php/Squeezebox_Touch', + icon => '/html/images/Players/fab4_250x250.png', + }, + default => { + modelName => 'Squeezebox', + url => 'http://www.slimdevices.com', + icon => '/html/images/slimdevices_logo_250x250.png', + }, +); + +sub init { + my $class = shift; + + # Watch for new players. + # Each new player will get its own MediaRenderer device + Slim::Control::Request::subscribe( + \&newClient, + [['client'], ['new', 'reconnect']], + ); + + Slim::Control::Request::subscribe( + \&disconnectClient, + [['client'], ['disconnect']], + ); + + # Setup description and service URLs + Slim::Web::Pages->addPageFunction( 'plugins/UPnP/MediaRenderer.xml' => \&description ); + + # Init service modules + Slim::Plugin::UPnP::MediaRenderer::RenderingControl->init; + Slim::Plugin::UPnP::MediaRenderer::ConnectionManager->init; + Slim::Plugin::UPnP::MediaRenderer::AVTransport->init; + + # Init protocol handler + Slim::Player::ProtocolHandlers->registerHandler( + upnp => 'Slim::Plugin::UPnP::MediaRenderer::ProtocolHandler' + ); + + $log->info('UPnP MediaRenderer initialized'); +} + +sub shutdown { + my $class = shift; + + Slim::Control::Request::unsubscribe( \&newClient ); + Slim::Control::Request::unsubscribe( \&disconnectClient ); + + # Shutdown service modules + Slim::Plugin::UPnP::MediaRenderer::RenderingControl->shutdown; + Slim::Plugin::UPnP::MediaRenderer::ConnectionManager->shutdown; + Slim::Plugin::UPnP::MediaRenderer::AVTransport->shutdown; + + # Discovery will take care of unregistering all devices +} + +sub newClient { + my $request = shift; + my $client = $request->client || return; + + # Ignore if we're already enabled for this client + return if $client->pluginData('uuid'); + + $log->info( 'Setting up MediaRenderer for ' . $client->id ); + + my $uuid = Slim::Plugin::UPnP::Discovery->uuid($client); + $client->pluginData( uuid => $uuid ); + + my $hostport = Slim::Utils::Network::serverAddr() . ':' . preferences('server')->get('httpport'); + + Slim::Plugin::UPnP::Discovery->register( + uuid => $uuid, + url => "http://$hostport/plugins/UPnP/MediaRenderer.xml?player=" . uri_escape( $client->id ), + ttl => 1800, + device => 'urn:schemas-upnp-org:device:MediaRenderer:1', + services => [ + 'urn:schemas-upnp-org:service:ConnectionManager:1', + 'urn:schemas-upnp-org:service:AVTransport:1', + 'urn:schemas-upnp-org:service:RenderingControl:1', + ], + ); + + # Register this client with services + Slim::Plugin::UPnP::MediaRenderer::RenderingControl->newClient( $client ); + Slim::Plugin::UPnP::MediaRenderer::AVTransport->newClient( $client ); +} + +sub disconnectClient { + my $request = shift; + my $client = $request->client || return; + + $log->info( 'Client ' . $client->id . ' disconnected, shutting down MediaRenderer' ); + + if ( my $uuid = $client->pluginData('uuid') ) { + Slim::Plugin::UPnP::Discovery->unregister( $uuid ); + $client->pluginData( uuid => 0 ); + } + + # Disconnect this client from services + Slim::Plugin::UPnP::MediaRenderer::RenderingControl->disconnectClient( $client ); + Slim::Plugin::UPnP::MediaRenderer::AVTransport->disconnectClient( $client ); +} + +sub description { + my ( $client, $params, undef, undef, $response ) = @_; + + # Trigger 404 if no client or the web code gave us a random client + # because the client requested was not connected + if ( !$client || 'player=' . $client->id ne uri_unescape( $params->{url_query} ) ) { + $response->code(404); + return \''; + } + + my $hostport = Slim::Utils::Network::serverAddr() . ':' . preferences('server')->get('httpport'); + my $eventaddr = Slim::Utils::Network::serverAddr() . ':' . Slim::Plugin::UPnP::Events->port; + + my $info = $models{ $client->model(1) } || $models{default}; + + $params->{device} = { + id_esc => uri_escape( $client->id ), + name => xmlEscape($client->name), + model => $info->{modelName}, + url => $info->{url}, + serial => $client->id, + uuid => $client->pluginData('uuid'), + icon => $info->{icon}, + }; + + $params->{serverAddr} = $hostport; + $params->{serverURL} = 'http://' . $hostport; + $params->{eventAddr} = $eventaddr; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaRenderer.xml for ' . $client->id . ' requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaRenderer.xml", $params ); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaRenderer/AVTransport.pm b/Slim/Plugin/UPnP/MediaRenderer/AVTransport.pm new file mode 100644 index 00000000000..f6440cf0b06 --- /dev/null +++ b/Slim/Plugin/UPnP/MediaRenderer/AVTransport.pm @@ -0,0 +1,872 @@ +package Slim::Plugin::UPnP::MediaRenderer::AVTransport; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaRenderer/AVTransport.pm 75368 2010-12-16T04:09:11.731914Z andy $ + +use strict; + +use URI::Escape qw(uri_unescape); + +use Slim::Utils::Log; +use Slim::Utils::Prefs; +use Slim::Web::HTTP; + +use Slim::Plugin::UPnP::Common::Utils qw(xmlEscape secsToHMS hmsToSecs trackDetails absURL); + +use constant EVENT_RATE => 0.2; + +my $log = logger('plugin.upnp'); +my $prefs = preferences('server'); + +sub init { + my $class = shift; + + Slim::Web::Pages->addPageFunction( + 'plugins/UPnP/MediaRenderer/AVTransport.xml', + \&description, + ); +} + +sub shutdown { } + +sub description { + my ( $client, $params ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaRenderer AVTransport.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaRenderer/AVTransport.xml", $params ); +} + +sub newClient { + my ( $class, $client ) = @_; + + # Initialize all state variables + $client->pluginData( AVT => _initialState() ); +} + +sub disconnectClient { } + +sub _initialState { + return { + TransportState => 'NO_MEDIA_PRESENT', + TransportStatus => 'OK', + PlaybackStorageMedium => 'NONE', + RecordStorageMedium => 'NOT_IMPLEMENTED', + PossiblePlaybackStorageMedia => 'NONE,NETWORK', + PossibleRecordStorageMedia => 'NOT_IMPLEMENTED', + CurrentPlayMode => 'NORMAL', + TransportPlaySpeed => 1, + RecordMediumWriteStatus => 'NOT_IMPLEMENTED', + CurrentRecordQualityMode => 'NOT_IMPLEMENTED', + PossibleRecordQualityModes => 'NOT_IMPLEMENTED', + NumberOfTracks => 0, + CurrentTrack => 0, + CurrentTrackDuration => '00:00:00', + CurrentMediaDuration => '00:00:00', + CurrentTrackMetaData => '', + CurrentTrackURI => '', + AVTransportURI => '', + AVTransportURIMetaData => '', + NextAVTransportURI => '', + NextAVTransportURIMetaData => '', + CurrentTransportActions => 'Play,Stop,Pause,Seek,Next,Previous', + }; + + # Time/Counter Position variables are intentionally not kept here +} + +### Eventing + +sub clientEvent { + my $class = __PACKAGE__; + my $request = shift; + my $client = $request->client; + + my $cmd = $request->getRequest(1); + + if ( $cmd eq 'clear' ) { + main::DEBUGLOG && $log->is_debug && $log->debug('playlist clear event, resetting state'); + + $class->changeState( $client, _initialState() ); + return; + } + + # Use playmode to handle TransportState changes on any kind of event + my $mode = Slim::Player::Source::playmode($client); + + if ( $mode eq 'stop' ) { + main::DEBUGLOG && $log->is_debug && $log->debug("playlist $cmd event, changing state to STOPPED"); + + # Change to STOPPED unless we are in NO_MEDIA_PRESENT + if ( $client->pluginData()->{AVT}->{TransportState} ne 'NO_MEDIA_PRESENT' ) { + $class->changeState( $client, { + TransportState => 'STOPPED', + } ); + } + } + elsif ( $mode eq 'pause' ) { + main::DEBUGLOG && $log->is_debug && $log->debug("playlist $cmd event, changing state to PAUSED_PLAYBACK"); + + $class->changeState( $client, { + TransportState => 'PAUSED_PLAYBACK', + } ); + } + elsif ( $mode eq 'play' ) { + main::DEBUGLOG && $log->is_debug && $log->debug("playlist $cmd event, changing state to PLAYING"); + + $class->changeState( $client, { + TransportState => 'PLAYING', + } ); + } +} + +sub subscribe { + my ( $class, $client, $uuid ) = @_; + + # Subscribe to events for this client + Slim::Control::Request::subscribe( + \&clientEvent, [['playlist']], $client, + ); + + # Bump the number of subscribers for this client + my $pd = $client->pluginData(); + my $subs = $pd->{AVT_Subscribers} || 0; + $pd->{AVT_Subscribers} = ++$subs; + + # Send initial notify with complete data, only to this UUID + Slim::Plugin::UPnP::Events->notify( + service => __PACKAGE__, + id => $uuid, + data => { + LastChange => _event_xml( $pd->{AVT} ), + }, + ); +} + +sub sendEvent { + my ( $class, $client, $id, $changedVars ) = @_; + + my $pd = $client->pluginData(); + + return unless $pd->{AVT_Subscribers}; + + # Batch multiple calls together + $pd->{AVT_Pending} = { + %{ $pd->{AVT_Pending} || {} }, + %{$changedVars}, + }; + + # Don't send more often than every 0.2 seconds + Slim::Utils::Timers::killTimers( $client, \&sendPending ); + + my $lastAt = $pd->{AVT_LastEvented} || 0; + my $sendAt = Time::HiRes::time; + + if ( $sendAt - $lastAt < EVENT_RATE ) { + $sendAt += EVENT_RATE - ($sendAt - $lastAt); + } + + Slim::Utils::Timers::setTimer( $client, $sendAt, \&sendPending ); +} + +sub sendPending { + my $client = shift; + + my $pd = $client->pluginData(); + + Slim::Plugin::UPnP::Events->notify( + service => __PACKAGE__, + id => $client->id, + data => { + LastChange => _event_xml( $pd->{AVT_Pending} ), + }, + ); + + $pd->{AVT_Pending} = {}; + + # Indicate when last event was sent + $pd->{AVT_LastEvented} = Time::HiRes::time; +} + +sub changeState { + my ( $class, $client, $vars ) = @_; + + my $isDebug = main::DEBUGLOG && $log->is_debug; + + my $state = $client->pluginData()->{AVT}; + my $changed = {}; + my $count = 0; + + while ( my ($k, $v) = each %{$vars} ) { + if ( $v ne $state->{$k} ) { + $isDebug && $log->debug("State change: $k => $v"); + $state->{$k} = $changed->{$k} = $v; + $count++; + } + } + + if ($count) { + main::INFOLOG && $log->is_info && $log->info( $client->id . ' state change: ' . Data::Dump::dump($changed) ); + $class->sendEvent( $client, $client->id, $changed ); + } +} + +sub unsubscribe { + my ( $class, $client ) = @_; + + my $subs = $client->pluginData('AVT_Subscribers'); + + if ( !$subs ) { + $subs = 1; + } + + $client->pluginData( AVT_Subscribers => --$subs ); +} + +### Action methods + +sub SetAVTransportURI { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $newstate; + my $mediaDuration; + my $trackDuration; + my $medium; + my $numTracks; + my $curTrack; + + # If we get an empty CurrentURI value, clear the playlist + if ( exists $args->{CurrentURI} && $args->{CurrentURI} eq '' ) { + $client->execute( [ 'playlist', 'clear' ] ); + + $newstate = 'NO_MEDIA_PRESENT'; + $mediaDuration = $trackDuration = '00:00:00'; + $medium = 'NONE'; + $numTracks = 0; + $curTrack = 0; + } + else { + my $meta = $class->_DIDLLiteToHash( $args->{CurrentURIMetaData} ); + + # XXX check upnp:class, parse playlist if necessary, return 716 if not found or other parse error + + if ( !$meta->{res} ) { + return [ 714 => "Illegal MIME-type" ]; + } + + my $pd = $client->pluginData(); + + # Convert URI to protocol handler + my $upnp_uri = $meta->{res}->{uri}; + $upnp_uri =~ s/^http/upnp/; + + Slim::Music::Info::setBitrate( $upnp_uri, $meta->{res}->{bitrate} ); + Slim::Music::Info::setDuration( $upnp_uri, $meta->{res}->{secs} ); + + $mediaDuration = $meta->{res}->{duration}; # XXX more if URI is a playlist? + $trackDuration = $mediaDuration; + $medium = 'NETWORK'; + $numTracks = 1; # XXX more if playlist + $curTrack = 1; + + $pd->{avt_AVTransportURIMetaData_hash} = $meta; + + my $tstate = $pd->{AVT}->{TransportState}; + + # This command behaves differently depending on the current transport state + + if ( $tstate eq 'NO_MEDIA_PRESENT' || $tstate eq 'STOPPED' ) { + # Both of these go to STOPPED, so load the track without playing it + $client->execute( [ 'playlist', 'clear' ] ); + $client->execute( [ 'playlist', 'add', $upnp_uri, $meta->{title} ] ); + $newstate = 'STOPPED'; + } + elsif ( $tstate eq 'PLAYING' || $tstate eq 'TRANSITIONING' ) { + # Both of these go to PLAYING with the new URI + $client->execute( [ 'playlist', 'play', $upnp_uri, $meta->{title} ] ); + $newstate = $tstate; + } + elsif ( $tstate eq 'PAUSED_PLAYBACK' ) { + # A bit strange, this is apparently supposed to load the new track but remains paused + # We'll set it to STOPPED to keep it simple + $client->execute( [ 'playlist', 'clear' ] ); + $client->execute( [ 'playlist', 'add', $upnp_uri, $meta->{title} ] ); + $newstate = 'STOPPED'; + } + } + + # Event notification, on a timer so playlist clear comes first and deletes everything + # then this resets the new data. + Slim::Utils::Timers::setTimer( undef, Time::HiRes::time, sub { + # Change state variables + $class->changeState( $client, { + TransportState => $newstate, + AVTransportURI => $args->{CurrentURI}, + CurrentTrackURI => $args->{CurrentURI}, # XXX different if playlist + AVTransportURIMetaData => $args->{CurrentURIMetaData}, + CurrentTrackMetaData => $args->{CurrentURIMetaData}, # XXX different if playlist? + PlaybackStorageMedium => $medium, + CurrentMediaDuration => $mediaDuration, + CurrentTrackDuration => $trackDuration, + NumberOfTracks => $numTracks, + CurrentTrack => $curTrack, + } ); + } ); + + return; +} + +sub SetNextAVTransportURI { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $meta = $class->_DIDLLiteToHash( $args->{NextURIMetaData} ); + + # XXX parse playlist? + + if ( !$meta->{res} ) { + return [ 714 => 'Illegal MIME-type' ]; + } + + # Save hash version of metadata + $client->pluginData( avt_NextAVTransportURIMetaData_hash => $meta ); + + # Change state variables + $class->changeState( $client, { + NextAVTransportURI => $args->{NextURI}, + NextAVTransportURIMetaData => $args->{NextURIMetaData}, + } ); + + return; +} + +sub GetMediaInfo { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $state = $client->pluginData()->{AVT}; + + # XXX this won't work for non-UPnP tracks + return ( + SOAP::Data->name( NrTracks => $state->{NumberOfTracks} ), + SOAP::Data->name( MediaDuration => $state->{CurrentMediaDuration} ), + SOAP::Data->name( CurrentURI => $state->{AVTransportURI} ), + SOAP::Data->name( CurrentURIMetaData => $state->{AVTransportURIMetaData} ), + SOAP::Data->name( NextURI => $state->{NextAVTransportURI} ), + SOAP::Data->name( NextURIMetaData => $state->{NextAVTransportURIMetaData} ), + SOAP::Data->name( PlayMedium => $state->{PlaybackStorageMedium} ), + SOAP::Data->name( RecordMedium => 'NOT_IMPLEMENTED' ), + SOAP::Data->name( WriteStatus => 'NOT_IMPLEMENTED' ), + ); +} + +sub GetTransportInfo { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $state = $client->pluginData()->{AVT}; + + return ( + SOAP::Data->name( CurrentTransportState => $state->{TransportState} ), + SOAP::Data->name( CurrentTransportStatus => $state->{TransportStatus} ), + SOAP::Data->name( CurrentSpeed => 1 ), + ); +} + +sub GetPositionInfo { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $state = $client->pluginData()->{AVT}; + + # position data is not stored in the state, it changes too fast + my $position = $class->_relativeTimePosition($client); + my $counterPosition = $class->_relativeCounterPosition($client); + + return ( + SOAP::Data->name( Track => $state->{CurrentTrack} ), + SOAP::Data->name( TrackDuration => $state->{CurrentTrackDuration} ), + SOAP::Data->name( TrackMetaData => $state->{CurrentTrackMetaData} ), + SOAP::Data->name( TrackURI => $state->{CurrentTrackURI} ), + SOAP::Data->name( RelTime => $position ), + SOAP::Data->name( AbsTime => $position ), + SOAP::Data->name( RelCount => $counterPosition ), + SOAP::Data->name( AbsCount => $counterPosition ), + ); +} + +sub GetDeviceCapabilities { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + return ( + SOAP::Data->name( PlayMedia => 'NONE,HDD,NETWORK,UNKNOWN' ), + SOAP::Data->name( RecMedia => 'NOT_IMPLEMENTED' ), + SOAP::Data->name( RecQualityModes => 'NOT_IMPLEMENTED' ), + ); +} + +sub GetTransportSettings { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $state = $client->pluginData()->{AVT}; + + return ( + SOAP::Data->name( PlayMode => $state->{CurrentPlayMode} ), + SOAP::Data->name( RecQualityMode => 'NOT_IMPLEMENTED' ), + ); +} + +sub Stop { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + # Stop is not allowed with no media + if ( $client->pluginData()->{AVT}->{TransportState} eq 'NO_MEDIA_PRESENT' ) { + return [ 701 => 'Transition not available' ]; + } + + $client->execute(['stop']); + + return; +} + +sub Play { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + if ( $args->{Speed} != 1 ) { + return [ 717 => 'Play speed not supported' ]; + } + + my $state = $client->pluginData()->{AVT}; + + # Make sure we have an AVTransportURI loaded + if ( !$state->{AVTransportURI} ) { + return [ 716 => 'Resource not found' ]; + } + + my $transportState = $state->{TransportState}; + + my $upnp_uri = $state->{AVTransportURI}; + $upnp_uri =~ s/^http/upnp/; + + if ( $transportState eq 'PLAYING' || $transportState eq 'TRANSITIONING' ) { + # Check if same track is already playing + my $playingURI = $client->playingSong->currentTrack->url; + if ( $upnp_uri eq $playingURI ) { + main::DEBUGLOG && $log->is_debug && $log->debug("Play for $upnp_uri ignored, already playing"); + return; + } + } + elsif ( $transportState eq 'PAUSED_PLAYBACK' ) { + # Check if we should just unpause + my $playingURI = $client->playingSong->currentTrack->url; + if ( $upnp_uri eq $playingURI ) { + main::DEBUGLOG && $log->is_debug && $log->debug("Play for $upnp_uri triggering unpause"); + + $client->execute(['play']); # will resume + + return; + } + } + + # All other cases, start playing the current transport URI + # which has already been loaded to index 0 by SetAVTransportURI + $client->execute([ 'playlist', 'jump', 0 ]); + + # State changes to TRANSITIONING, after playlist jump + # is handled it will be changed to PLAYING + $class->changeState( $client, { + TransportState => 'TRANSITIONING', + } ); + + return; +} + +sub Pause { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + # XXX not allowed in some states + + $client->execute(['pause']); + + $class->changeState( $client, { + TransportState => 'PAUSED_PLAYBACK', + } ); + + return; +} + +sub Seek { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $unit = $args->{Unit}; + my $target = $args->{Target}; + + if ( !$target ) { + return [ 711 => 'Illegal seek target' ]; + } + + # XXX: support TRACK_NR mode for playlists + + if ( $unit eq 'ABS_TIME' || $unit eq 'REL_TIME' ) { + # Seek to time + my $seeksecs = hmsToSecs($target); + my $tracksecs = hmsToSecs( $client->pluginData()->{AVT}->{CurrentTrackDuration} ); + + if ( $seeksecs > $tracksecs ) { + return [ 711 => "Illegal seek target ($seeksecs out of range, max: $tracksecs)" ]; + } + + $client->execute(['time', $seeksecs]); + + # State changes to TRANSITIONING, after playlist newsong + # is handled it will be changed to PLAYING + $class->changeState( $client, { + TransportState => 'TRANSITIONING', + } ); + } + else { + return [ 710 => 'Seek mode not supported' ]; + } + + return; +} + +sub Next { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $state = $client->pluginData()->{AVT}; + + if ( $state->{NumberOfTracks} <= 1 ) { + return [ 711 => 'Illegal seek target' ]; + } + + # XXX skip to the next track in the playlist + + return; +} + +sub Previous { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $state = $client->pluginData()->{AVT}; + + if ( $state->{NumberOfTracks} <= 1 ) { + return [ 711 => 'Illegal seek target' ]; + } + + # XXX skip to the previous track in the playlist + + return; +} + +sub SetPlayMode { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + my $mode = $args->{NewPlayMode}; + + if ( !$mode || $mode !~ /^(?:NORMAL|SHUFFLE|REPEAT_ONE|REPEAT_ALL)$/ ) { + return [ 712 => 'Play mode not supported' ]; + } + + $class->changeState( $client, { + CurrentPlayMode => $mode, + } ); + + return; +} + +sub GetCurrentTransportActions { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 718 => 'Invalid InstanceID' ]; + } + + return ( + SOAP::Data->name( Actions => $client->pluginData()->{AVT}->{CurrentTransportActions} ), + ); +} + +### Helper methods + +# Elapsed time in H:MM:SS[.F+] format +sub _relativeTimePosition { + my ( $class, $client ) = @_; + + my $elapsed = '00:00:00'; + + if ( my $secs = $client->controller->playingSongElapsed() ) { + $elapsed = secsToHMS($secs); + } + + return $elapsed; +} + +# A 'dimensionless counter' as an integer, we'll just return the integer seconds elapsed +sub _relativeCounterPosition { + my ( $class, $client ) = @_; + + return sprintf "%d", $client->controller->playingSongElapsed(); +} + +my $xs; +sub _xml_simple { + return XML::Simple->new( + RootName => undef, + XMLDecl => undef, + SuppressEmpty => undef, + ForceContent => 1, + ForceArray => [ + 'upnp:artist', + 'upnp:albumArtURI', + 'res', + ], + ); +} + +sub _DIDLLiteToHash { + my ( $class, $xml ) = @_; + + return {} unless $xml; + + $xs ||= _xml_simple(); + + my $x = eval { $xs->XMLin($xml) }; + if ( $@ ) { + $log->error("Unable to parse DIDL-Lite XML: $@"); + return {}; + } + + # Create a saner structure, as the DIDL-Lite can be very complex + $x = $x->{item}; + + my $meta = {}; + + if ( $x->{'upnp:artist'} ) { + $meta->{artist} = $x->{'upnp:artist'}->[0]->{content}; + } + else { + $meta->{artist} = $x->{'dc:creator'} ? $x->{'dc:creator'}->{content} : 'Unknown Artist'; + } + + $meta->{album} = $x->{'upnp:album'} ? $x->{'upnp:album'}->{content} : 'Unknown Album'; + $meta->{title} = $x->{'dc:title'}->{content} || '', + $meta->{cover} = $x->{'upnp:albumArtURI'} ? $x->{'upnp:albumArtURI'}->[0]->{content} : ''; + + # Find the best res item to play + for my $r ( @{ $x->{res} } ) { + my ($mime) = $r->{protocolInfo} =~ /[^:]+:[^:]+:([^:+]+):/; + next if !$mime || !Slim::Music::Info::mimeToType($mime); + + # Some servers must have missed the (really stupid) part in + # the spec where bitrate is defined as bytes/sec, not bits/sec + # We try to handle this for common MP3 bitrates + my $bitrate = $r->{bitrate}; + if ( $bitrate =~ /^(?:64|96|128|160|192|256|320)000$/ ) { + $bitrate /= 8; + } + + $meta->{res} = { + uri => $r->{content}, + mime => $mime, + protocolInfo => $r->{protocolInfo}, + bitrate => $bitrate * 8, + secs => hmsToSecs( $r->{duration} ), + duration => $r->{duration} || '', + }; + + last; + } + + return $meta; +} + +sub _event_xml { + my $data = shift; + + $xs ||= _xml_simple(); + + my $out = {}; + + while ( my ($k, $v) = each %{$data} ) { + $out->{$k} = { + val => $v, + }; + } + + # Can't figure out how to produce this with XML::Simple + my $xml + = '' + . "\n" + . $xs->XMLout( $out ) + . '' + . ''; + + return $xml; +} + +=pod XXX +sub _currentTrackURI { + my ( $class, $client ) = @_; + + my $uri = ''; + + if ( my $song = ($client->playingSong() || $client->streamingSong()) ) { + # Return the URL an external client would use to stream this song + my $track = $song->currentTrack; + + my $id = $track->id; + if ( $id > 0 ) { + $uri = absURL('/music/' . $id . '/download'); + } + else { + # Remote URL + $uri = $track->url; + + # URL may be from UPnP + $uri =~ s/^upnp/http/; + } + } + + # Check for a UPnP track set via SetAVTransport + elsif ( my $avtu = $client->pluginData('avt_AVTransportURI') ) { + $uri = $avtu; + } + + $client->pluginData( avt_AVTransportURI => $uri ); + + return $uri; +} + +sub _currentTrackMetaData { + my ( $class, $client, $refresh ) = @_; + + # Check for a UPnP track set via SetAVTransport (or cached from below) + if ( !$refresh ) { + if ( my $xml = $client->pluginData('avt_AVTransportURIMetaData') ) { + return $xml; + } + } + + my $meta = ''; + + if ( my $song = ($client->playingSong() || $client->streamingSong()) ) { + my $track = $song->currentTrack; + + # XXX could construct real /a//l//t/ path but is this needed? + my $tid = '/t/' . $track->id; + my $pid = '/t'; + + $meta = '' + . qq{} + . trackDetails($track, '*') + . ''; + + # Cache this in pluginData to avoid database queries every time it's called + $client->pluginData( avt_AVTransportURIMetaData => $meta ); + $client->pluginData( avt_AVTransportURIMetaData_hash => $class->_DIDLLiteToHash($meta) ); + } + + return $meta; +} + +sub _currentTransportActions { + my ( $class, $client ) = @_; + + my $actions = 'PLAY,STOP'; + + if ( my $song = $client->controller()->playingSong() ) { + if ( $song->canSeek() ) { + $actions .= ',SEEK'; + } + + my $controller = $client->controller(); + + my $isPlaying = $controller->isPlaying(); + + if ( my $handler = $song->currentTrackHandler() ) { + if ( $handler->can('canDoAction') ) { + # Some restrictive plugins, check for allowed actions + my $master = $controller->master; + my $url = $song->currentTrack()->url; + + if ( $handler->canDoAction($master, $url, 'pause') && $isPlaying ) { + $actions .= ',PAUSE'; + } + + if ( $handler->canDoAction($master, $url, 'stop') ) { + $actions .= ',NEXT'; + } + + if ( $handler->canDoAction($master, $url, 'rew') ) { + $actions .= ',PREVIOUS'; + } + } + else { + # Not a restrictive handler + $actions .= ',PAUSE' if $isPlaying; + $actions .= ',NEXT,PREVIOUS'; + } + } + else { + $actions .= ',PAUSE' if $isPlaying; + $actions .= ',NEXT,PREVIOUS'; + } + } + + return $actions; +} +=cut + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaRenderer/ConnectionManager.pm b/Slim/Plugin/UPnP/MediaRenderer/ConnectionManager.pm new file mode 100644 index 00000000000..0823ba26aec --- /dev/null +++ b/Slim/Plugin/UPnP/MediaRenderer/ConnectionManager.pm @@ -0,0 +1,242 @@ +package Slim::Plugin::UPnP::MediaRenderer::ConnectionManager; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaRenderer/ConnectionManager.pm 75368 2010-12-16T04:09:11.731914Z andy $ + +use strict; + +use Slim::Utils::Log; +use Slim::Web::HTTP; + +my $log = logger('plugin.upnp'); + +sub init { + my $class = shift; + + Slim::Web::Pages->addPageFunction( + 'plugins/UPnP/MediaRenderer/ConnectionManager.xml', + \&description, + ); +} + +sub shutdown { } + +sub description { + my ( $client, $params ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaRenderer ConnectionManager.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaRenderer/ConnectionManager.xml", $params ); +} + +### Eventing + +sub subscribe { + my ( $class, $client, $uuid ) = @_; + + my $sink = $class->_sinkProtocols($client); + + # Send initial notify with complete data + Slim::Plugin::UPnP::Events->notify( + service => $class, + id => $uuid, # only notify this UUID, since this is an initial notify + data => { + SourceProtocolInfo => '', + SinkProtocolInfo => join( ',', @{$sink} ), + CurrentConnectionIDs => 0, + }, + ); +} + +sub unsubscribe { + # Nothing to do +} + +### Action methods + +sub GetCurrentConnectionIDs { + my $class = shift; + + return ( + SOAP::Data->name( ConnectionIDs => 0 ), + ); +} + +sub GetProtocolInfo { + my ( $class, $client ) = @_; + + my $sink = $class->_sinkProtocols($client); + + return ( + SOAP::Data->name( Source => '' ), + SOAP::Data->name( Sink => join ',', @{$sink} ), + ); +} + +sub GetCurrentConnectionInfo { + my ( $class, $client, $args ) = @_; + + if ( $args->{ConnectionID} != 0 ) { + return [ 706 => 'Invalid connection reference' ]; + } + + my $sink = $client->pluginData->{CM_SinkProtocolInfo}; + if ( !$sink ) { + $class->GetProtocolInfo($client); + $sink = $client->pluginData->{CM_SinkProtocolInfo}; + } + + # Get mime type of currently playing song if any + # XXX needs to interface with AVTransport + my $type = ''; + if ( my $song = $client->playingSong() ) { + if ( my $format = $song->streamformat() ) { + my $mime = $Slim::Music::Info::types{ $format }; + ($type) = grep { /$mime/ } @{$sink}; + } + } + + return ( + SOAP::Data->name( RcsID => 0 ), + SOAP::Data->name( AVTransportID => 0 ), + SOAP::Data->name( ProtocolInfo => $type ), + SOAP::Data->name( PeerConnectionManager => '' ), + SOAP::Data->name( PeerConnectionID => -1 ), + SOAP::Data->name( Direction => 'Input' ), + SOAP::Data->name( Status => 'OK' ), + ); +} + +### Helpers + +=pod +/* DLNA.ORG_FLAGS, padded with 24 trailing 0s + * 80000000 31 senderPaced + * 40000000 30 lsopTimeBasedSeekSupported + * 20000000 29 lsopByteBasedSeekSupported + * 10000000 28 playcontainerSupported + * 8000000 27 s0IncreasingSupported + * 4000000 26 sNIncreasingSupported + * 2000000 25 rtspPauseSupported + * 1000000 24 streamingTransferModeSupported + * 800000 23 interactiveTransferModeSupported + * 400000 22 backgroundTransferModeSupported + * 200000 21 connectionStallingSupported + * 100000 20 dlnaVersion15Supported + * + * Example: (1 << 24) | (1 << 22) | (1 << 21) | (1 << 20) + * DLNA.ORG_FLAGS=01700000[000000000000000000000000] // [] show padding +=cut + +sub _sinkProtocols { + my ( $class, $client ) = @_; + + my $sink = $client->pluginData->{CM_SinkProtocolInfo}; + if ( !$sink ) { + my $flags = sprintf "%.8x%.24x", + (1 << 24) | (1 << 22) | (1 << 21) | (1 << 20), 0; + + # MP3 supported by everything + my @formats = ( + "http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + ); + + # Natively supported formats + my @cf = $client->formats; + + my $hasPCM = grep { /pcm/ } @cf; + my $hasAAC = grep { /aac/ } @cf; + my $hasWMA = grep { /wma/ } @cf; + my $hasWMAP = grep { /wmap/ } @cf; + my $hasOgg = grep { /ogg/ } @cf; + my $hasFLAC = grep { /flc/ } @cf; + + # Transcoder-supported formats + my $canTranscode = sub { + my $format = shift; + + my $profile + = $hasFLAC ? "${format}-flc-*-*" + : $hasPCM ? "${format}-pcm-*-*" + : "${format}-mp3-*-*"; + + return main::TRANSCODING && Slim::Player::TranscodingHelper::isEnabled($profile); + }; + + if ( $hasPCM ) { + push @formats, ( + "http-get:*:audio/L16;rate=8000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=8000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=11025;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=11025;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=12000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=12000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=16000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=16000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=22050;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=22050;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=24000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=24000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=32000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=32000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + ); + } + + if ( $hasAAC || $canTranscode->('aac') ) { + push @formats, ( + "http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=HEAAC_L2_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + ); + } + + if ( $hasAAC || $canTranscode->('mp4') ) { + # Seeking not supported for remote MP4 content (OP=00) + push @formats, ( + "http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/mp4:DLNA.ORG_PN=HEAAC_L2_ISO;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=$flags", + ); + } + + if ( $hasWMA || $canTranscode->('wma') ) { + push @formats, ( + "http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + ); + } + + if ( $hasWMAP || $canTranscode->('wmap') ) { + push @formats, ( + "http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAPRO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + ); + } + + if ( $hasOgg || $canTranscode->('ogg') ) { + # Seeking not supported for remote Vorbis content (OP=00) + push @formats, ( + "http-get:*:application/ogg:DLNA.ORG_OP=00;DLNA.ORG_FLAGS=$flags", + ); + } + + if ( $hasFLAC || $canTranscode->('flc') ) { + # Seeking not supported for remote FLAC content (OP=00) + push @formats, ( + "http-get:*:audio/x-flac:DLNA.ORG_OP=00;DLNA.ORG_FLAGS=$flags", + ); + } + + # XXX Disable DLNA stuff for now + for ( @formats ) { + s/:DLNA.+/:\*/; + } + + $sink = $client->pluginData( CM_SinkProtocolInfo => \@formats ); + } + + return $sink; +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaRenderer/ProtocolHandler.pm b/Slim/Plugin/UPnP/MediaRenderer/ProtocolHandler.pm new file mode 100644 index 00000000000..a0113bce0d3 --- /dev/null +++ b/Slim/Plugin/UPnP/MediaRenderer/ProtocolHandler.pm @@ -0,0 +1,94 @@ +package Slim::Plugin::UPnP::MediaRenderer::ProtocolHandler; + +use strict; +use base qw(Slim::Player::Protocols::HTTP); + +use Slim::Utils::Cache; +use Slim::Utils::Log; +use Slim::Utils::Misc; + +my $log = logger('plugin.upnp'); + +sub isRemote { 1 } + +sub getFormatForURL { 'mp3' } # XXX + +# XXX use DLNA.ORG_OP value, and/or MIME type +sub canSeek { 1 } # We'll assume Range requests are supported by all servers, + # and this is also needed for pause to work properly + +sub canSeekError { return ( 'SEEK_ERROR_TYPE_NOT_SUPPORTED', 'UPnP/DLNA' ); } + +# To support remote streaming (synced players), we need to subclass Protocols::HTTP +sub new { + my $class = shift; + my $args = shift; + + my $client = $args->{client}; + my $song = $args->{song}; + my $streamUrl = $song->streamUrl() || return; + + main::DEBUGLOG && $log->is_debug && $log->debug( 'Remote streaming UPnP track: ' . $streamUrl ); + + my $sock = $class->SUPER::new( { + url => $streamUrl, + song => $args->{song}, + client => $client, + bitrate => 128_000, # XXX + } ) || return; + + ${*$sock}{contentType} = 'audio/mpeg'; # XXX + + return $sock; +} + +# Avoid scanning +sub scanUrl { + my ($class, $url, $args) = @_; + $args->{cb}->($args->{song}->currentTrack()); +} + +sub audioScrobblerSource { 'P' } + +# XXX parseHeaders, needed? + +# XXX parseDirectHeaders, needed? + +# XXX seek data, using res@size, res@duration instead of bitrate + +sub isRepeatingStream { + my (undef, $song) = @_; + + return 0; # XXX playlists, REPEAT_ONE, REPEAT_ALL, SHUFFLE +} + +# XXX getNextTrack (playlists, next track) + +sub getMetadataFor { + my ( $class, $client, $url ) = @_; + + my $pd = $client->pluginData(); + my $meta = $pd->{avt_AVTransportURIMetaData_hash}; + my $res = $meta->{res}; + + return { + artist => $meta->{artist}, + album => $meta->{album}, + title => $meta->{title}, + cover => $meta->{cover} || '', # XXX default + icon => '', # XXX default icon + duration => $res->{secs} || 0, + bitrate => $res->{bitrate} ? ($res->{bitrate} / 1000) . 'kbps' : 0, + type => $res->{mime} . ' (UPnP/DLNA)', + }; +} + +sub canDirectStreamSong { + my ( $class, $client, $song ) = @_; + + # We need to check with the base class (HTTP) to see if we + # are synced or if the user has set mp3StreamingMethod + return $class->SUPER::canDirectStream($client, $song->streamUrl(), $class->getFormatForURL()); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaRenderer/RenderingControl.pm b/Slim/Plugin/UPnP/MediaRenderer/RenderingControl.pm new file mode 100644 index 00000000000..5282cc9dc08 --- /dev/null +++ b/Slim/Plugin/UPnP/MediaRenderer/RenderingControl.pm @@ -0,0 +1,315 @@ +package Slim::Plugin::UPnP::MediaRenderer::RenderingControl; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaRenderer/RenderingControl.pm 75368 2010-12-16T04:09:11.731914Z andy $ + +use strict; + +use URI::Escape qw(uri_unescape); +use XML::Simple qw(XMLout); + +use Slim::Utils::Log; +use Slim::Utils::Prefs; +use Slim::Web::HTTP; + +use constant EVENT_RATE => 0.2; + +my $log = logger('plugin.upnp'); +my $prefs = preferences('server'); + +sub init { + my $class = shift; + + Slim::Web::Pages->addPageFunction( + 'plugins/UPnP/MediaRenderer/RenderingControl.xml', + \&description, + ); + + # Since prefs change functions are for every client and cannot + # be removed, we set them up once here. + + $prefs->setChange( sub { + my $client = $_[2]; + # Only notify if player is on when brightness changes + if ( $client->power ) { + $client->pluginData('RC_LastChange')->{Brightness} = $_[1]; + $class->event( $client => 'RC_LastChange' ); + } + }, 'powerOnBrightness' ); + + $prefs->setChange( sub { + my $client = $_[2]; + # Only notify if player is off when brightness changes + if ( !$client->power ) { + $client->pluginData('RC_LastChange')->{Brightness} = $_[1]; + $class->event( $client => 'RC_LastChange' ); + } + }, 'powerOffBrightness' ); + + # XXX idleBrightness? + + $prefs->setChange( sub { + my $client = $_[2]; + $client->pluginData('RC_LastChange')->{Volume} = $_[1]; + $class->event( $client => 'RC_LastChange' ); + }, 'volume' ); + + $prefs->setChange( sub { + my $client = $_[2]; + $client->pluginData('RC_LastChange')->{Mute} = $_[1]; + $class->event( $client => 'RC_LastChange' ); + }, 'mute' ); +} + +sub shutdown { } + +sub description { + my ( $client, $params ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaRenderer RenderingControl.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaRenderer/RenderingControl.xml", $params ); +} + +sub newClient { + my ( $class, $client ) = @_; + + $client->pluginData( RC_LastChange => {} ); +} + +sub disconnectClient { + my ( $class, $client ) = @_; + + $client->pluginData( RC_LastChange => {} ); +} + +### Eventing + +sub subscribe { + my ( $class, $client, $uuid ) = @_; + + # Bump the number of subscribers for this client + my $subs = $client->pluginData('rc_subscribers') || 0; + $client->pluginData( rc_subscribers => ++$subs ); + + my $cprefs = $prefs->client($client); + + # Setup state variables + my $mute = $cprefs->get('mute') ? 1 : 0; + my $brightness = $client->power ? $cprefs->get('powerOnBrightness') : $cprefs->get('powerOffBrightness'); + + # Send initial notify with complete data + Slim::Plugin::UPnP::Events->notify( + service => __PACKAGE__, + id => $uuid, # only notify this UUID, since this is an initial notify + data => { + LastChange => _event_xml( { + PresetNameList => 'FactoryDefaults', + Brightness => $brightness, + Mute => $mute, + Volume => $cprefs->get('volume'), + } ), + }, + ); + + $client->pluginData( rc_lastEvented => Time::HiRes::time() ); +} + +sub event { + my ( $class, $client, $var ) = @_; + + if ( $client->pluginData('rc_subscribers') ) { + # Don't send more often than every 0.2 seconds + Slim::Utils::Timers::killTimers( $client, \&sendEvent ); + + my $lastAt = $client->pluginData('rc_lastEvented'); + my $sendAt = Time::HiRes::time(); + + if ( $sendAt - $lastAt < EVENT_RATE ) { + $sendAt += EVENT_RATE - ($sendAt - $lastAt); + } + + Slim::Utils::Timers::setTimer( + $client, + $sendAt, + \&sendEvent, + $var, + ); + } +} + +sub sendEvent { + my ( $client, $var ) = @_; + + Slim::Plugin::UPnP::Events->notify( + service => __PACKAGE__, + id => $client->id, + data => { + LastChange => _event_xml( $client->pluginData($var) ), + }, + ); + + # Clear the RC_LastChange state + $client->pluginData( $var => {} ); + + # Indicate when last event was sent + $client->pluginData( rc_lastEvented => Time::HiRes::time() ); +} + +sub unsubscribe { + my ( $class, $client ) = @_; + + my $subs = $client->pluginData('rc_subscribers'); + + if ( !$subs ) { + $subs = 1; + } + + $client->pluginData( rc_subscribers => --$subs ); +} + +### Action methods + +sub ListPresets { + my ( $class, $client, $args ) = @_; + + return SOAP::Data->name( + CurrentPresetNameList => 'FactoryDefaults', + ); +} + +sub SelectPreset { + my ( $class, $client, $args ) = @_; + + if ( $args->{PresetName} eq 'FactoryDefaults' ) { + # FactoryDefaults is no mute, 50 volume + # XXX brightness? + $prefs->client($client)->set( mute => 0 ); + $prefs->client($client)->set( volume => 50 ); + } + else { + return [ 701 => 'Invalid Name' ]; + } + + return; +} + +sub GetBrightness { + my ( $class, $client, $args ) = @_; + + return SOAP::Data->name( CurrentBrightness => $client->currBrightness() ); +} + +sub SetBrightness { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 702 => 'Invalid InstanceID' ]; + } + + if ( $args->{DesiredBrightness} >= 0 && $args->{DesiredBrightness} <= $client->maxBrightness ) { + # set brightness pref depending on mode + my $pref = $client->power ? 'powerOnBrightness' : 'powerOffBrightness'; + $prefs->client($client)->set( $pref => $args->{DesiredBrightness} ); + } + + return; +} + +sub GetMute { + my ( $class, $client, $args ) = @_; + + if ( $args->{Channel} ne 'Master' ) { + return [ 703 => 'Invalid Channel' ]; + } + + my $mute = $prefs->client($client)->get('mute') ? 1 : 0; + return SOAP::Data->name( CurrentMute => $mute ); +} + +sub SetMute { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 702 => 'Invalid InstanceID' ]; + } + + if ( $args->{Channel} ne 'Master' ) { + return [ 703 => 'Invalid Channel' ]; + } + + my $mute = $args->{DesiredMute} == 0 ? 0 : 1; + + $client->execute(['mixer', 'muting', $mute]); + + return; +} + +sub GetVolume { + my ( $class, $client, $args ) = @_; + + if ( $args->{Channel} ne 'Master' ) { + return [ 703 => 'Invalid Channel' ]; + } + + my $vol = $prefs->client($client)->get('volume'); + return SOAP::Data->name( CurrentVolume => $vol ); +} + +sub SetVolume { + my ( $class, $client, $args ) = @_; + + if ( $args->{InstanceID} != 0 ) { + return [ 702 => 'Invalid InstanceID' ]; + } + + if ( $args->{Channel} ne 'Master' ) { + return [ 703 => 'Invalid Channel' ]; + } + + if ( $args->{DesiredVolume} >= 0 && $args->{DesiredVolume} <= 100 ) { + $client->volume( $args->{DesiredVolume} ); + } + + return; +} + +my $xs; +sub _event_xml { + my $data = shift; + + $xs ||= XML::Simple->new( + RootName => undef, + XMLDecl => undef, + SuppressEmpty => undef, + ); + + my $out = {}; + + while ( my ($k, $v) = each %{$data} ) { + if ( $k eq 'Mute' || $k eq 'Volume' ) { + $out->{$k} = { + channel => 'Master', + val => $v, + }; + } + else { + $out->{$k} = { + val => $v, + }; + } + } + + # Can't figure out how to produce this with XML::Simple + my $xml + = '' + . "\n" + . $xs->XMLout( $out ) + . '' + . ''; + + main::DEBUGLOG && $log->is_debug && $log->debug("RenderingControl event: $xml"); + + return $xml; +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaServer.pm b/Slim/Plugin/UPnP/MediaServer.pm new file mode 100644 index 00000000000..425a40e846b --- /dev/null +++ b/Slim/Plugin/UPnP/MediaServer.pm @@ -0,0 +1,85 @@ +package Slim::Plugin::UPnP::MediaServer; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaServer.pm 78831 2011-07-25T16:48:09.710754Z andy $ + +use strict; + +use Slim::Plugin::UPnP::Discovery; +use Slim::Plugin::UPnP::MediaServer::ConnectionManager; +use Slim::Plugin::UPnP::MediaServer::ContentDirectory; +use Slim::Plugin::UPnP::MediaServer::MediaReceiverRegistrar; +use Slim::Plugin::UPnP::Common::Utils qw(xmlEscape); + +use Slim::Utils::Log; +use Slim::Utils::Prefs; +use Slim::Web::HTTP; + +my $log = logger('plugin.upnp'); +my $prefs = preferences('server'); + +sub init { + my $class = shift; + + # Setup description and service URLs + Slim::Web::Pages->addPageFunction( 'plugins/UPnP/MediaServer.xml' => \&description ); + + # Init service modules + Slim::Plugin::UPnP::MediaServer::ConnectionManager->init; + Slim::Plugin::UPnP::MediaServer::ContentDirectory->init; + Slim::Plugin::UPnP::MediaServer::MediaReceiverRegistrar->init; + + my $hostport = Slim::Utils::Network::serverAddr() . ':' . $prefs->get('httpport'); + + Slim::Plugin::UPnP::Discovery->register( + uuid => uc( $prefs->get('server_uuid') ), + url => "http://$hostport/plugins/UPnP/MediaServer.xml", + ttl => 1800, + device => 'urn:schemas-upnp-org:device:MediaServer:1', + services => [ + 'urn:schemas-upnp-org:service:ConnectionManager:1', + 'urn:schemas-upnp-org:service:ContentDirectory:1', + ], + ); + + $log->info('UPnP MediaServer initialized'); +} + +sub shutdown { + my $class = shift; + + # Shutdown service modules + Slim::Plugin::UPnP::MediaServer::ConnectionManager->shutdown; + Slim::Plugin::UPnP::MediaServer::ContentDirectory->shutdown; + Slim::Plugin::UPnP::MediaServer::MediaReceiverRegistrar->shutdown; +} + +sub description { + my ( $client, $params ) = @_; + + my $hostport = Slim::Utils::Network::serverAddr() . ':' . $prefs->get('httpport'); + my $eventaddr = Slim::Utils::Network::serverAddr() . ':' . Slim::Plugin::UPnP::Events->port; + + my $server_uuid = $prefs->get('server_uuid'); + + $params->{serverAddr} = $hostport; + $params->{serverURL} = 'http://' . $hostport; + $params->{eventAddr} = $eventaddr; + + # Replace the first 8 chars of server_uuid with a constant value that identifies this + # as an SBS server + my $serial = $server_uuid; + substr $serial, 0, 8, '106173c8'; + + $params->{device} = { + name => 'Logitech Media Server [' . xmlEscape(Slim::Utils::Misc::getLibraryName()) . ']', + version => $::VERSION . ' r' . $::REVISION, + serial => $serial, + uuid => uc($server_uuid), + }; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaServer.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaServer.xml", $params ); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaServer/ConnectionManager.pm b/Slim/Plugin/UPnP/MediaServer/ConnectionManager.pm new file mode 100644 index 00000000000..1a99929b896 --- /dev/null +++ b/Slim/Plugin/UPnP/MediaServer/ConnectionManager.pm @@ -0,0 +1,145 @@ +package Slim::Plugin::UPnP::MediaServer::ConnectionManager; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaServer/ConnectionManager.pm 75368 2010-12-16T04:09:11.731914Z andy $ + +use strict; + +use Slim::Utils::Log; +use Slim::Web::HTTP; + +my $log = logger('plugin.upnp'); + +my $SourceProtocolInfo; + +sub init { + my $class = shift; + + Slim::Web::Pages->addPageFunction( + 'plugins/UPnP/MediaServer/ConnectionManager.xml', + \&description, + ); +} + +sub shutdown { } + +sub description { + my ( $client, $params ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaServer ConnectionManager.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaServer/ConnectionManager.xml", $params ); +} + +### Eventing + +sub subscribe { + my ( $class, $client, $uuid ) = @_; + + my $source = $class->_sourceProtocols; + + # Send initial notify with complete data + Slim::Plugin::UPnP::Events->notify( + service => $class, + id => $uuid, # only notify this UUID, since this is an initial notify + data => { + SourceProtocolInfo => join( ',', @{$source} ), + SinkProtocolInfo => '', + CurrentConnectionIDs => 0, + }, + ); +} + +sub unsubscribe { + # Nothing to do +} + +### Action methods + +sub GetCurrentConnectionIDs { + my $class = shift; + + return SOAP::Data->name( ConnectionIDs => 0 ); +} + +sub GetProtocolInfo { + my $class = shift; + + my $source = $class->_sourceProtocols; + + return ( + SOAP::Data->name( Source => join ',', @{$source} ), + SOAP::Data->name( Sink => '' ), + ); +} + +sub GetCurrentConnectionInfo { + my ( $class, $client, $args ) = @_; + + if ( $args->{ConnectionID} != 0 ) { + return [ 706 => 'Invalid connection reference' ]; + } + + return ( + SOAP::Data->name( RcsID => -1 ), + SOAP::Data->name( AVTransportID => -1 ), + SOAP::Data->name( ProtocolInfo => '' ), + SOAP::Data->name( PeerConnectionManager => '' ), + SOAP::Data->name( PeerConnectionID => -1 ), + SOAP::Data->name( Direction => 'Output' ), + SOAP::Data->name( Status => 'OK' ), + ); +} + +### Helpers + +sub _sourceProtocols { + my $class = shift; + + if ( !$SourceProtocolInfo ) { + my $flags = sprintf "%.8x%.24x", + (1 << 24) | (1 << 22) | (1 << 21) | (1 << 20), 0; + + my @formats = ( + "http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=8000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=8000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=11025;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=11025;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=12000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=12000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=16000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=16000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=22050;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=22050;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=24000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=24000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=32000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=32000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01,DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=HEAAC_L2_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/mp4:DLNA.ORG_PN=HEAAC_L2_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAPRO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:application/ogg:DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + "http-get:*:audio/x-flac:DLNA.ORG_OP=01;DLNA.ORG_FLAGS=$flags", + ); + + # XXX Disable DLNA stuff for now + for ( @formats ) { + s/:DLNA.+/:\*/; + } + + $SourceProtocolInfo = \@formats; + } + + return $SourceProtocolInfo; +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaServer/ContentDirectory.pm b/Slim/Plugin/UPnP/MediaServer/ContentDirectory.pm new file mode 100644 index 00000000000..960a2d3102f --- /dev/null +++ b/Slim/Plugin/UPnP/MediaServer/ContentDirectory.pm @@ -0,0 +1,1293 @@ +package Slim::Plugin::UPnP::MediaServer::ContentDirectory; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaServer/ContentDirectory.pm 78831 2011-07-25T16:48:09.710754Z andy $ + +use strict; + +use I18N::LangTags qw(extract_language_tags); +use URI::Escape qw(uri_escape_utf8); + +use Slim::Utils::Log; +use Slim::Utils::Prefs; +use Slim::Utils::Strings qw(string); +use Slim::Web::HTTP; + +use Slim::Plugin::UPnP::Common::Utils qw(xmlEscape absURL secsToHMS trackDetails videoDetails imageDetails); + +use constant EVENT_RATE => 0.2; + +my $log = logger('plugin.upnp'); +my $prefs = preferences('server'); + +my $STATE; + +sub init { + my $class = shift; + + Slim::Web::Pages->addPageFunction( + 'plugins/UPnP/MediaServer/ContentDirectory.xml', + \&description, + ); + + $STATE = { + SystemUpdateID => Slim::Music::Import->lastScanTime(), + _subscribers => 0, + _last_evented => 0, + }; + + # Monitor for changes in the database + Slim::Control::Request::subscribe( \&refreshSystemUpdateID, [['rescan'], ['done']] ); +} + +sub shutdown { } + +sub refreshSystemUpdateID { + $STATE->{SystemUpdateID} = Slim::Music::Import->lastScanTime(); + __PACKAGE__->event('SystemUpdateID'); +} + +sub description { + my ( $client, $params ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaServer ContentDirectory.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaServer/ContentDirectory.xml", $params ); +} + +### Eventing + +sub subscribe { + # Bump the number of subscribers + $STATE->{_subscribers}++; + + # Send initial event + sendEvent( undef, 'SystemUpdateID' ); +} + +sub event { + my ( $class, $var ) = @_; + + if ( $STATE->{_subscribers} ) { + # Don't send more often than every 0.2 seconds + Slim::Utils::Timers::killTimers( undef, \&sendEvent ); + + my $lastAt = $STATE->{_last_evented}; + my $sendAt = Time::HiRes::time(); + + if ( $sendAt - $lastAt < EVENT_RATE ) { + $sendAt += EVENT_RATE - ($sendAt - $lastAt); + } + + Slim::Utils::Timers::setTimer( + undef, + $sendAt, + \&sendEvent, + $var, + ); + } +} + +sub sendEvent { + my ( undef, $var ) = @_; + + Slim::Plugin::UPnP::Events->notify( + service => __PACKAGE__, + id => 0, # will notify everyone + data => { + $var => $STATE->{$var}, + }, + ); + + # Indicate when last event was sent + $STATE->{_last_evented} = Time::HiRes::time(); +} + +sub unsubscribe { + if ( $STATE->{_subscribers} > 0 ) { + $STATE->{_subscribers}--; + } +} + +### Action methods + +sub GetSearchCapabilities { + return SOAP::Data->name( + SearchCaps => 'dc:title,dc:creator,upnp:artist,upnp:album,upnp:genre', + ); +} + +sub GetSortCapabilities { + return SOAP::Data->name( + SortCaps => 'dc:title,dc:creator,dc:date,upnp:artist,upnp:album,upnp:genre,upnp:originalTrackNumber', + ); +} + +sub GetSystemUpdateID { + return SOAP::Data->name( Id => $STATE->{SystemUpdateID} ); +} + +sub Browse { + my ( $class, undef, $args, $headers ) = @_; + + my $id = $args->{ObjectID}; + my $flag = $args->{BrowseFlag}; + my $filter = $args->{Filter}; + my $start = $args->{StartingIndex}; + # spec says "RequestedCount=0 indicates request all entries.", but we don't want to kill the server, only return 200 items + my $limit = $args->{RequestedCount} || 200; + my $sort = $args->{SortCriteria}; + + my $cmd; + my $xml; + my $results; + my $count = 0; + my $total = 0; + + if ( $flag !~ /^(?:BrowseMetadata|BrowseDirectChildren)$/ ) { + return [ 720 => 'Cannot process the request (invalid BrowseFlag)' ]; + } + + # Strings are needed for the top-level and years menus + my $strings; + my $string = sub { + # Localize menu options from Accept-Language header + if ( !$strings ) { + $strings = Slim::Utils::Strings::loadAdditional( $prefs->get('language') ); + + if ( my $lang = $headers->{'accept-language'} ) { + my $all_langs = Slim::Utils::Strings::languageOptions(); + + foreach my $language (extract_language_tags($lang)) { + $language = uc($language); + $language =~ s/-/_/; # we're using zh_cn, the header says zh-cn + + if (defined $all_langs->{$language}) { + $strings = Slim::Utils::Strings::loadAdditional($language); + last; + } + } + } + } + + my $token = uc(shift); + my $string = $strings->{$token}; + if ( @_ ) { return sprintf( $string, @_ ); } + return $string; + }; + + # ContentDirectory menu/IDs are as follows: CLI query: + + # Home Menu + # --------- + # Music + # Video + # Pictures + + # Music (/music) + # ----- + # Artists (/a) artists + # Artist 1 (/a//l) albums artist_id: sort:album + # Album 1 (/a//l//t) titles album_id: sort:tracknum + # Track 1 (/a//l//t/) titles track_id: + # Albums (/l) albums sort:album + # Album 1 (/l//t) titles album_id: sort:tracknum + # Track 1 (/l//t/) titles track_id: + # Genres (/g) genres sort:album + # Genre 1 (/g//a) artists genre_id: + # Artist 1 (/g//a//l) albums genre_id: artist_id: sort:album + # Album 1 (/g//a//l//t) titles album_id: sort:tracknum + # Track 1 (/g//a//l//t/) titles track_id: + # Year (/y) years + # 2010 (/y/2010/l) albums year: sort:album + # Album 1 (/y/2010/l//t) titles album_id: sort:tracknum + # Track 1 (/y/2010/l//t/) titles track_id: + # New Music (/n) albums sort:new + # Album 1 (/n//t) titles album_id: sort:tracknum + # Track 1 (/n//t/) titles track_id: + # Music Folder (/m) musicfolder + # Folder (/m//m) musicfolder folder_id: + # Playlists (/p) playlists + # Playlist 1 (/p//t) playlists tracks playlist_id: + # Track 1 (/p//t/) titles track_id: + + # Extras for standalone track items, AVTransport uses these + # Tracks (/t) (cannot be browsed) + # Track 1 (/t/) + + # Video (/video) + # ----- + # Browse Video Folder (/v) + # Video Folder (/vf) + # Folder 1 (/vf/id) + # All Videos (/va) videos + # Video 1 (/va/) video_titles video_hash: + + # Images (/images) + # ----- + # All Pictures (/ia) + # By Date (/id) image_titles timeline:dates + # 2011-07-03 (/id/2011/07/03) image_titles timeline:day search:2011-07-03 + # Photo 1 (/id/2011/07/03/) image_titles image_id: + # Albums (/il) image_titles albums:1 + # Album 1 (/il/) image_titles albums:1 search: + # Folders (/if) image_titles folders:1 + # Folder 1 (/if/) image_titles folders:1 search: + # By Year (/it) image_titles timeline:years + # 2011 (/it/2011) image_titles timeline:months search:2011 + # 07 (/it/2011/07) image_titles timeline:days search:2011-07 + # 03 (/it/2011/07/03) image_titles timeline:day search:2011-07-03 + # Photo 1 (/it/2011/07/03/) image_titles image_id: + + if ( $id eq '0' || ($flag eq 'BrowseMetadata' && $id =~ m{^/(?:music|video|images)$}) ) { # top-level menu + my $type = 'object.container'; + my $menu = [ + { id => '/music', parentID => 0, type => $type, title => $string->('MUSIC') }, + { id => '/images', parentID => 0, type => $type, title => $string->('PICTURES') }, + { id => '/video', parentID => 0, type => $type, title => $string->('VIDEO') }, + ]; + + if ( $flag eq 'BrowseMetadata' ) { + if ( $id eq '0' ) { + $menu = [ { + id => 0, + parentID => -1, + type => 'object.container', + title => 'Logitech Media Server [' . xmlEscape(Slim::Utils::Misc::getLibraryName()) . ']', + searchable => 1, + } ]; + } + else { + # pull out the desired menu item + my ($item) = grep { $_->{id} eq $id } @{$menu}; + $menu = [ $item ]; + } + } + + ($xml, $count, $total) = _arrayToDIDLLite( { + array => $menu, + sort => $sort, + start => $start, + limit => $limit, + } ); + } + elsif ( $id eq '/music' || ($flag eq 'BrowseMetadata' && length($id) == 2) ) { # Music menu, or metadata for a music menu item + my $type = 'object.container'; + my $menu = [ + { id => '/a', parentID => '/music', type => $type, title => $string->('ARTISTS') }, + { id => '/l', parentID => '/music', type => $type, title => $string->('ALBUMS') }, + { id => '/g', parentID => '/music', type => $type, title => $string->('GENRES') }, + { id => '/y', parentID => '/music', type => $type, title => $string->('BROWSE_BY_YEAR') }, + { id => '/n', parentID => '/music', type => $type, title => $string->('BROWSE_NEW_MUSIC') }, + { id => '/m', parentID => '/music', type => $type, title => $string->('BROWSE_MUSIC_FOLDER') }, + { id => '/p', parentID => '/music', type => $type, title => $string->('PLAYLISTS') }, + ]; + + if ( $flag eq 'BrowseMetadata' ) { + # pull out the desired menu item + my ($item) = grep { $_->{id} eq $id } @{$menu}; + $menu = [ $item ]; + } + + ($xml, $count, $total) = _arrayToDIDLLite( { + array => $menu, + sort => $sort, + start => $start, + limit => $limit, + } ); + } + elsif ( $id eq '/video' || ($flag eq 'BrowseMetadata' && $id =~ m{^/(?:vf|va)$}) ) { # Video menu + my $type = 'object.container'; + my $menu = [ + { id => '/vf', parentID => '/video', type => $type, title => $string->('BROWSE_VIDEO_FOLDER') }, + { id => '/va', parentID => '/video', type => $type, title => $string->('BROWSE_ALL_VIDEOS') }, + ]; + + if ( $flag eq 'BrowseMetadata' ) { + # pull out the desired menu item + my ($item) = grep { $_->{id} eq $id } @{$menu}; + $menu = [ $item ]; + } + + ($xml, $count, $total) = _arrayToDIDLLite( { + array => $menu, + sort => $sort, + start => $start, + limit => $limit, + } ); + } + elsif ( $id eq '/images' || ($flag eq 'BrowseMetadata' && $id =~ m{^/(?:ia|id|it|il|if)$}) ) { # Image menu + my $type = 'object.container'; + my $menu = [ + { id => '/il', parentID => '/images', type => $type, title => $string->('ALBUMS') }, + { id => '/it', parentID => '/images', type => $type, title => $string->('YEAR') }, + { id => '/id', parentID => '/images', type => $type, title => $string->('DATE') }, + { id => '/if', parentID => '/images', type => $type, title => $string->('FOLDERS') }, + { id => '/ia', parentID => '/images', type => $type, title => $string->('BROWSE_ALL_PICTURES') }, + ]; + + if ( $flag eq 'BrowseMetadata' ) { + # pull out the desired menu item + my ($item) = grep { $_->{id} eq $id } @{$menu}; + $menu = [ $item ]; + } + + ($xml, $count, $total) = _arrayToDIDLLite( { + array => $menu, + sort => $sort, + start => $start, + limit => $limit, + } ); + } + else { + # Determine CLI command to use + # The command is different depending on the flag: + # BrowseMetadata will request only 1 specific item + # BrowseDirectChildren will request the desired number of children + if ( $id =~ m{^/a} ) { + if ( $id =~ m{/l/(\d+)/t$} ) { + if ( $sort && $sort !~ /^\+upnp:originalTrackNumber$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit album_id:$1 sort:tracknum tags:AGldyorfTIctnDU" + : "albums 0 1 album_id:$1 tags:alyj"; + } + elsif ( $id =~ m{/t/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + elsif ( $id =~ m{/a/(\d+)/l$} ) { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "albums $start $limit artist_id:$1 sort:album tags:alyj" + : "artists 0 1 artist_id:$1"; + } + else { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = "artists $start $limit"; + } + } + elsif ( $id =~ m{^/l} ) { + if ( $id =~ m{/l/(\d+)/t$} ) { + if ( $sort && $sort !~ /^\+upnp:originalTrackNumber$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit album_id:$1 sort:tracknum tags:AGldyorfTIctnDU" + : "albums 0 1 album_id:$1 tags:alyj"; + } + elsif ( $id =~ m{/t/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + else { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = "albums $start $limit sort:album tags:alyj"; + } + } + elsif ( $id =~ m{^/g} ) { + if ( $id =~ m{/t/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + elsif ( $id =~ m{^/g/\d+/a/\d+/l/(\d+)/t$} ) { + if ( $sort && $sort !~ /^\+upnp:originalTrackNumber$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit album_id:$1 sort:tracknum tags:AGldyorfTIctnDU" + : "albums 0 1 album_id:$1 tags:alyj"; + } + elsif ( $id =~ m{^/g/(\d+)/a/(\d+)/l$} ) { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "albums $start $limit genre_id:$1 artist_id:$2 sort:album tags:alyj" + : "artists 0 1 genre_id:$1 artist_id:$2"; + } + elsif ( $id =~ m{^/g/(\d+)/a$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "artists $start $limit genre_id:$1" + : "genres 0 1 genre_id:$1" + } + else { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = "genres $start $limit"; + } + } + elsif ( $id =~ m{^/y} ) { + if ( $id =~ m{/t/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + elsif ( $id =~ m{/l/(\d+)/t$} ) { + if ( $sort && $sort !~ /^\+upnp:originalTrackNumber$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit album_id:$1 sort:tracknum tags:AGldyorfTIctnDU" + : "albums 0 1 album_id:$1 tags:alyj"; + } + elsif ( $id =~ m{/y/(\d+)/l$} ) { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "albums $start $limit year:$1 sort:album tags:alyj" + : "years 0 1 year:$1"; + } + else { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = "years $start $limit"; + } + } + elsif ( $id =~ m{^/n} ) { + if ( $id =~ m{/t/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + elsif ( $id =~ m{/n/(\d+)/t$} ) { + if ( $sort && $sort !~ /^\+upnp:originalTrackNumber$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit album_id:$1 sort:tracknum tags:AGldyorfTIctnDU" + : "albums 0 1 album_id:$1 tags:alyj"; + } + else { + # Limit results to pref or 100 + my $preflimit = $prefs->get('browseagelimit') || 100; + if ( $limit > $preflimit ) { + $limit = $preflimit; + } + + $cmd = "albums $start $limit sort:new tags:alyj"; + } + } + elsif ( $id =~ m{^/m} ) { + if ( $id =~ m{/m/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + elsif ( $id =~ m{/m/(\d+)/m$} ) { + my $fid = $1; + + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = $flag eq 'BrowseDirectChildren' + ? "musicfolder $start $limit folder_id:$fid" + : "musicfolder 0 1 folder_id:$fid return_top:1"; + } + else { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = "musicfolder $start $limit"; + } + } + elsif ( $id =~ m{^/p} ) { + if ( $id =~ m{/t/(\d+)$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "titles $start $limit track_id:$1 tags:AGldyorfTIctnDU" + : "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + elsif ( $id =~ m{^/p/(\d+)/t$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "playlists tracks $start $limit playlist_id:$1 tags:AGldyorfTIctnDU" + : "playlists 0 1 playlist_id:$1"; + } + else { + if ( $sort && $sort !~ /^\+dc:title$/ ) { + $log->warn('Unsupported sort: ' . Data::Dump::dump($args)); + } + + $cmd = "playlists $start $limit"; + } + } + elsif ( $id =~ m{^/t/(\d+)$} ) { + $cmd = "titles 0 1 track_id:$1 tags:AGldyorfTIctnDU"; + } + + ### Video + elsif ( $id =~ m{^/va} ) { # All Videos + if ( $id =~ m{/([0-9a-f]{8})$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "video_titles $start $limit video_id:$1 tags:dorfcwhtnDUl" + : "video_titles 0 1 video_id:$1 tags:dorfcwhtnDUl"; + } + else { + $cmd = "video_titles $start $limit tags:dorfcwhtnDUl"; + } + } + + elsif ( $id =~ m{^/vf} ) { # folders + my ($folderId) = $id =~ m{^/vf/(.+)}; + + if ( $folderId ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "mediafolder $start $limit type:video folder_id:$folderId tags:dorfcwhtnDUlJ" + : "mediafolder 0 1 type:video folder_id:$folderId return_top:1 tags:dorfcwhtnDUlJ"; + } + + elsif ( $id eq '/vf' ) { + $cmd = "mediafolder $start $limit type:video tags:dorfcwhtnDUlJ"; + } + } + + ### Images + elsif ( $id =~ m{^/ia} ) { # All Images + if ( $id =~ m{/([0-9a-f]{8})$} ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "image_titles $start $limit image_id:$1 tags:ofwhtnDUlO" + : "image_titles 0 1 image_id:$1 tags:ofwhtnDUlO"; + } + else { + $cmd = "image_titles $start $limit tags:ofwhtnDUlO"; + } + } + + elsif ( $id =~ m{^/if} ) { # folders + my ($folderId) = $id =~ m{^/if/(.+)}; + + if ( $folderId ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "mediafolder $start $limit type:image folder_id:$folderId tags:ofwhtnDUlOJ" + : "mediafolder 0 1 type:image folder_id:$folderId return_top:1 tags:ofwhtnDUlOJ"; + } + + elsif ( $id eq '/if' ) { + $cmd = "mediafolder $start $limit type:image tags:ofwhtnDUlOJ"; + } + } + + elsif ( $id =~ m{^/il} ) { # albums + my ($albumId) = $id =~ m{^/il/(.+)}; + + if ( $albumId ) { + $albumId = uri_escape_utf8($albumId); + + $cmd = $flag eq 'BrowseDirectChildren' + ? "image_titles $start $limit albums:1 search:$albumId tags:ofwhtnDUlO" + : "image_titles 0 1 albums:1"; + } + + elsif ( $id eq '/il' ) { + $cmd = "image_titles $start $limit albums:1"; + } + } + + elsif ( $id =~ m{^/(?:it|id)} ) { # timeline hierarchy + + my ($tlId) = $id =~ m{^/(?:it|id)/(.+)}; + my ($year, $month, $day, $pic) = $tlId ? split('/', $tlId) : (); + + if ( $pic ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "image_titles 0 1 image_id:$pic tags:ofwhtnDUlO" + : "image_titles 0 1 timeline:day search:$year-$month-$day tags:ofwhtnDUlO"; + } + + # if we've got a full date, show pictures + elsif ( $year && $month && $day ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "image_titles $start $limit timeline:day search:$year-$month-$day tags:ofwhtnDUlO" + : "image_titles 0 1 timeline:days search:$year-$month"; + } + + # show days for a given month/year + elsif ( $year && $month ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "image_titles $start $limit timeline:days search:$year-$month" + : "image_titles 0 1 timeline:months search:$year"; + } + + # show months for a given year + elsif ( $year ) { + $cmd = $flag eq 'BrowseDirectChildren' + ? "image_titles $start $limit timeline:months search:$year" + : "image_titles 0 1 timeline:years"; + } + + elsif ( $id eq '/it' ) { + $cmd = "image_titles $start $limit timeline:years"; + } + + elsif ( $id eq '/id' ) { + $cmd = "image_titles $start $limit timeline:dates"; + } + } + + if ( !$cmd ) { + return [ 701 => 'No such object' ]; + } + + main::INFOLOG && $log->is_info && $log->info("Executing command: $cmd"); + + # Run the request + my $request = Slim::Control::Request->new( undef, [ split( / /, $cmd ) ] ); + if ( $request->isStatusDispatchable ) { + $request->execute(); + if ( $request->isStatusError ) { + return [ 720 => 'Cannot process the request (' . $request->getStatusText . ')' ]; + } + $results = $request->getResults; + } + else { + return [ 720 => 'Cannot process the request (' . $request->getStatusText . ')' ]; + } + + my ($parentID) = $id =~ m{^(.*)/}; + + ($xml, $count, $total) = _queryToDIDLLite( { + cmd => $cmd, + results => $results, + flag => $flag, + id => $id, + parentID => $parentID, + filter => $filter, + string => $string, + } ); + } + + utf8::encode($xml); # Just to be safe, not sure this is needed + + return ( + SOAP::Data->name( Result => $xml ), + SOAP::Data->name( NumberReturned => $count ), + SOAP::Data->name( TotalMatches => $total ), + SOAP::Data->name( UpdateID => $STATE->{SystemUpdateID} ), + ); +} + +sub Search { + my ( $class, undef, $args, $headers ) = @_; + + my $id = $args->{ContainerID}; + my $search = $args->{SearchCriteria} || '*'; + my $filter = $args->{Filter}; + my $start = $args->{StartingIndex}; + my $limit = $args->{RequestedCount}; + my $sort = $args->{SortCriteria}; + + my $xml; + my $results; + my $count = 0; + my $total = 0; + + if ( $id != 0 ) { + return [ 708 => 'Unsupported or invalid search criteria (only ContainerID 0 is supported)' ]; + } + + my ($cmd, $table, $searchsql, $tags) = _decodeSearchCriteria($search); + + my ($sortsql, $stags) = _decodeSortCriteria($sort, $table); + $tags .= $stags; + + if ($cmd eq 'image_titles') { + $tags .= 'ofwhtnDUlO'; + } + elsif ($cmd eq 'video_titles') { + $tags .= 'dorfcwhtnDUl'; + } + else { + # Avoid 'A' and 'G' tags because they will run extra queries + $tags .= 'agldyorfTIctnDU'; + } + + if ( $sort && !$sortsql ) { + return [ 708 => 'Unsupported or invalid sort criteria' ]; + } + + if ( !$cmd ) { + return [ 708 => 'Unsupported or invalid search criteria' ]; + } + + # Construct query + $cmd = [ $cmd, $start, $limit, "tags:$tags", "search:sql=($searchsql)", "sort:sql=$sortsql" ]; + + main::INFOLOG && $log->is_info && $log->info("Executing command: " . Data::Dump::dump($cmd)); + + # Run the request + my $results; + my $request = Slim::Control::Request->new( undef, $cmd ); + if ( $request->isStatusDispatchable ) { + $request->execute(); + if ( $request->isStatusError ) { + return [ 708 => 'Unsupported or invalid search criteria' ]; + } + $results = $request->getResults; + } + else { + return [ 708 => 'Unsupported or invalid search criteria' ]; + } + + ($xml, $count, $total) = _queryToDIDLLite( { + cmd => $cmd, + results => $results, + flag => '', + id => $table eq 'tracks' ? '/t' : $table eq 'videos' ? '/v' : '/i', + filter => $filter, + } ); + + return ( + SOAP::Data->name( Result => $xml ), + SOAP::Data->name( NumberReturned => $count ), + SOAP::Data->name( TotalMatches => $total ), + SOAP::Data->name( UpdateID => $STATE->{SystemUpdateID} ), + ); +} + +sub _queryToDIDLLite { + my $args = shift; + + my $cmd = $args->{cmd}; + my $results = $args->{results}; + my $flag = $args->{flag}; + my $id = $args->{id}; + my $parentID = $args->{parentID}; + my $filter = $args->{filter}; + + my $count = 0; + my $total = $results->{count}; + + my $filterall = ($filter eq '*'); + + if ( ref $cmd eq 'ARRAY' ) { + $cmd = join( ' ', @{$cmd} ); + } + + my $xml = ''; + + if ( $cmd =~ /^artists/ ) { + for my $artist ( @{ $results->{artists_loop} || [] } ) { + $count++; + my $aid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $artist->{id} . '/l'; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the artist's parent + ($parent) = $id =~ m{^(.*/a)}; + } + + $xml .= qq{} + . 'object.container.person.musicArtist' + . '' . xmlEscape($artist->{artist}) . '' + . ''; + } + } + elsif ( $cmd =~ /^albums/ ) { + # Fixup total for sort:new listing + if ( $cmd =~ /sort:new/ && (my $max = $prefs->get('browseagelimit')) < $total) { + $total = $max if $max < $total; + } + + for my $album ( @{ $results->{albums_loop} || [] } ) { + $count++; + my $aid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $album->{id} . '/t'; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the album's parent + ($parent) = $id =~ m{^(.*/(?:l|n))}; # both /l and /n top-level items use this + } + + my $coverid = $album->{artwork_track_id}; + + # XXX musicAlbum should have childCount attr (per DLNA) + $xml .= qq{} + . 'object.container.album.musicAlbum' + . '' . xmlEscape($album->{album}) . ''; + + if ( $filterall || $filter =~ /dc:creator/ ) { + $xml .= '' . xmlEscape($album->{artist}) . ''; + } + if ( $filterall || $filter =~ /upnp:artist/ ) { + $xml .= '' . xmlEscape($album->{artist}) . ''; + } + if ( $filterall || $filter =~ /dc:date/ ) { + $xml .= '' . xmlEscape($album->{year}) . '-01-01'; # DLNA requires MM-DD + } + if ( $filterall || $filter =~ /upnp:albumArtURI/ ) { + $xml .= '' . absURL("/music/$coverid/cover") . ''; + } + + $xml .= ''; + } + } + elsif ( $cmd =~ /^genres/ ) { + for my $genre ( @{ $results->{genres_loop} || [] } ) { + $count++; + my $gid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $genre->{id} . '/a'; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the genre's parent + ($parent) = $id =~ m{^(.*/g)}; + } + + $xml .= qq{} + . 'object.container.genre.musicGenre' + . '' . xmlEscape($genre->{genre}) . '' + . ''; + } + } + elsif ( $cmd =~ /^years/ ) { + for my $year ( @{ $results->{years_loop} || [] } ) { + $count++; + my $year = $year->{year}; + + my $yid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $year . '/l'; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the year's parent + ($parent) = $id =~ m{^(.*/y)}; + } + + if ( $year eq '0' ) { + $year = $args->{string}->('UNK'); + } + + $xml .= qq{} + . 'object.container' + . '' . $year . '' + . ''; + } + } + elsif ( $cmd =~ /^musicfolder/ ) { + my @trackIds; + for my $folder ( @{ $results->{folder_loop} || [] } ) { + my $fid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $folder->{id} . '/m'; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the folder's parent + ($parent) = $id =~ m{^(.*/m)/\d+/m}; + } + + my $type = $folder->{type}; + + if ( $type eq 'folder' || $type eq 'unknown' ) { + $count++; + $xml .= qq{} + . 'object.container.storageFolder' + . '' . xmlEscape($folder->{filename}) . '' + . ''; + } + elsif ( $type eq 'playlist' ) { + warn "*** Playlist type: " . Data::Dump::dump($folder) . "\n"; + $total--; + } + elsif ( $type eq 'track' ) { + # Save the track ID for later lookup + push @trackIds, $folder->{id}; + $total--; + } + } + + if ( scalar @trackIds ) { + my $tracks = Slim::Control::Queries::_getTagDataForTracks( 'AGldyorfTIct', { + trackIds => \@trackIds, + } ); + + for my $trackId ( @trackIds ) { + $count++; + $total++; + my $track = $tracks->{$trackId}; + my $tid = $id . '/' . $trackId; + + # Rewrite id to end with /t/ so it doesn't look like another folder + $tid =~ s{m/(\d+)$}{t/$1}; + + $xml .= qq{} + . trackDetails($track, $filter) + . ''; + } + } + } + elsif ( $cmd =~ /^titles/ ) { + for my $track ( @{ $results->{titles_loop} || [] } ) { + $count++; + my $tid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $track->{id}; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the track's parent + ($parent) = $id =~ m{^(.*/t)}; + + # Special case for /m path items, their parent ends in /m + if ( $parent =~ m{^/m} ) { + $parent =~ s/t$/m/; + } + } + + $xml .= qq{} + . trackDetails($track, $filter) + . ''; + } + } + elsif ( $cmd =~ /^playlists tracks/ ) { + for my $track ( @{ $results->{playlisttracks_loop} || [] } ) { + $count++; + my $tid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $track->{id}; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the track's parent + ($parent) = $id =~ m{^(.*/t)}; + } + + $xml .= qq{} + . trackDetails($track, $filter) + . ''; + } + } + elsif ( $cmd =~ /^playlists/ ) { + for my $playlist ( @{ $results->{playlists_loop} || [] } ) { + $count++; + my $pid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $playlist->{id} . '/t'; + + $xml .= qq{} + . 'object.container.playlistContainer' + . '' . xmlEscape($playlist->{playlist}) . '' + . ''; + } + } + elsif ( $cmd =~ /^video_titles/ ) { + for my $video ( @{ $results->{videos_loop} || [] } ) { + $count++; + my $vid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $video->{id}; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the video's parent + # XXX + } + + $xml .= qq{} + . videoDetails($video, $filter) + . ''; + } + } + # mediafolder query is being used by images and videos + elsif ( $cmd =~ /^mediafolder.*type:video/ ) { + + for my $item ( @{ $results->{folder_loop} || [] } ) { + $count++; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the image's parent + # XXX + } + + my $type = $item->{type}; + + if ( $type eq 'folder' || $type eq 'unknown' ) { + my $fid = $flag eq 'BrowseMetadata' ? $id : '/vf/' . $item->{id}; + $xml .= qq{} + . 'object.container.storageFolder' + . '' . xmlEscape($item->{filename}) . '' + . ''; + } + elsif ( $type eq 'video' ) { + $item->{id} = $item->{hash}; + my $fid = $flag eq 'BrowseMetadata' ? '/va' : '/va/' . $item->{hash}; + $xml .= qq{} + . videoDetails($item, $filter) + . ''; + } + } + } + elsif ( $cmd =~ /^mediafolder.*type:image/ ) { + + for my $item ( @{ $results->{folder_loop} || [] } ) { + $count++; + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the image's parent + # XXX + } + + my $type = $item->{type}; + + if ( $type eq 'folder' || $type eq 'unknown' ) { + my $fid = $flag eq 'BrowseMetadata' ? $id : '/if/' . $item->{id}; + $xml .= qq{} + . 'object.container.storageFolder' + . '' . xmlEscape($item->{filename}) . '' + . ''; + } + elsif ( $type eq 'image' ) { + $item->{id} = $item->{hash}; + my $fid = $flag eq 'BrowseMetadata' ? '/ia' : '/ia/' . $item->{id}; + $xml .= qq{} + . imageDetails($item, $filter) + . ''; + } + } + } + elsif ( $cmd =~ /^image_titles.*timeline:(?:years|months|days|dates)/ + || ($cmd =~ /^image_titles.*albums:/ && $cmd !~ /search:/) ) { + + for my $image ( @{ $results->{images_loop} || [] } ) { + $count++; + my $vid = $flag eq 'BrowseMetadata' ? $id : ($id . '/' . $image->{id}); + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the image's parent + # XXX + } + + $xml .= qq{} + . 'object.container' + . '' . xmlEscape($image->{title}) . '' + . ''; + } + } + elsif ( $cmd =~ /^image_titles/ ) { + for my $image ( @{ $results->{images_loop} || [] } ) { + $count++; + my $vid = $flag eq 'BrowseMetadata' ? $id : $id . '/' . $image->{id}; + + my $parent = $id; + + if ( $flag eq 'BrowseMetadata' ) { # point parent to the image's parent + # XXX + } + + $xml .= qq{} + . imageDetails($image, $filter) + . ''; + } + } + + $xml .= ''; + + # Return empty string if we got no results + if ( $count == 0 ) { + $xml = ''; + } + + return ($xml, $count, $total); +} + +sub _arrayToDIDLLite { + my $args = shift; + + my $array = $args->{array}; + my $sort = $args->{sort}; + my $start = $args->{start}; + my $limit = $args->{limit}; + + my $count = 0; + my $total = 0; + + my $xml = ''; + + my @sorted; + + # Only title is available for sorting here + if ( $sort && $sort =~ /([+-])dc:title/ ) { + if ( $1 eq '+' ) { + @sorted = sort { $a->{title} cmp $b->{title} } @{$array}; + } + else { + @sorted = sort { $b->{title} cmp $a->{title} } @{$array}; + } + } + else { + @sorted = @{$array}; + } + + for my $item ( @sorted ) { + $total++; + + if ($start) { + next if $start >= $total; + } + + if ($limit) { + next if $limit <= $count; + } + + $count++; + + my $id = $item->{id}; + my $parentID = $item->{parentID}; + my $type = $item->{type}; + my $title = $item->{title}; + my $searchable = $item->{searchable} || 0; + + if ( $type =~ /container/ ) { + $xml .= qq{} + . "${type}" + . '' . xmlEscape($title) . '' + . ''; + } + } + + $xml .= ''; + + return ($xml, $count, $total); +} + +sub _decodeSearchCriteria { + my $search = shift; + + my $cmd = 'titles'; + my $table = 'tracks'; + my $idcol = 'id'; # XXX switch to hash for audio tracks + my $tags = ''; + + if ( $search eq '*' ) { + return '1=1'; + } + + # Fix quotes and apos + $search =~ s/"/"/g; + $search =~ s/'/'/g; + + # Handle derivedfrom + if ( $search =~ s/upnp:class derivedfrom "([^"]+)"/1=1/ig ) { + my $sclass = $1; + if ( $sclass =~ /object\.item\.videoItem/i ) { + $cmd = 'video_titles'; + $table = 'videos'; + $idcol = 'hash'; + } + elsif ( $sclass =~ /object\.item\.imageItem/i ) { + $cmd = 'image_titles'; + $table = 'images'; + $idcol = 'hash'; + } + } + + # Replace 'contains "x"' and 'doesNotContain "x" with 'LIKE "%X%"' and 'NOT LIKE "%X%"' + $search =~ s/contains\s+"([^"]+)"/LIKE "%%\U$1%%"/ig; + $search =~ s/doesNotContain\s+"([^"]+)"/NOT LIKE "%%\U$1%%"/ig; + + $search =~ s/\@id/${table}.${idcol}/g; + $search =~ s/\@refID exists (?:true|false)/1=1/ig; + + # Replace 'exists true' and 'exists false' + $search =~ s/exists\s+true/IS NOT NULL/ig; + $search =~ s/exists\s+false/IS NULL/ig; + + # Replace properties + $search =~ s/dc:title/${table}.titlesearch/g; + + if ( $search =~ s/pv:lastUpdated/${table}.updated_time/g ) { + $tags .= 'U'; + } + + if ( $cmd eq 'titles' ) { + # These search params are only valid for audio + if ( $search =~ s/dc:creator/contributors.namesearch/g ) { + $tags .= 'a'; + } + + if ( $search =~ s/upnp:artist/contributors.namesearch/g ) { + $tags .= 'a'; + } + + if ( $search =~ s/upnp:album/albums.titlesearch/g ) { + $tags .= 'l'; + } + + if ( $search =~ s/upnp:genre/genres.namesearch/g ) { + $tags .= 'g'; + } + } + + return ( $cmd, $table, $search, $tags ); +} + +sub _decodeSortCriteria { + my $sort = shift; + my $table = shift; + + # Note: collate intentionally not used here, doesn't seem to work with multiple values + + my @sql; + my $tags = ''; + + # Supported SortCaps: + # + # dc:title + # dc:creator + # dc:date + # upnp:artist + # upnp:album + # upnp:genre + # upnp:originalTrackNumber + # pv:modificationTime + # pv:addedTime + # pv:lastUpdated + + for ( split /,/, $sort ) { + if ( /^([+-])(.+)/ ) { + my $dir = $1 eq '+' ? 'ASC' : 'DESC'; + + if ( $2 eq 'dc:title' ) { + push @sql, "${table}.titlesort $dir"; + } + elsif ( $2 eq 'dc:creator' || $2 eq 'upnp:artist' ) { + push @sql, "contributors.namesort $dir"; + $tags .= 'a'; + } + elsif ( $2 eq 'upnp:album' ) { + push @sql, "albums.titlesort $dir"; + $tags .= 'l'; + } + elsif ( $2 eq 'upnp:genre' ) { + push @sql, "genres.namesort $dir"; + $tags .= 'g'; + } + elsif ( $2 eq 'upnp:originalTrackNumber' ) { + push @sql, "tracks.tracknum $dir"; + } + elsif ( $2 eq 'pv:modificationTime' || $2 eq 'dc:date' ) { + if ( $table eq 'tracks' ) { + push @sql, "${table}.timestamp $dir"; + } + else { + push @sql, "${table}.mtime $dir"; + } + } + elsif ( $2 eq 'pv:addedTime' ) { + push @sql, "${table}.added_time $dir"; + } + elsif ( $2 eq 'pv:lastUpdated' ) { + push @sql, "${table}.updated_time $dir"; + } + } + } + + return ( join(', ', @sql), $tags ); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/MediaServer/MediaReceiverRegistrar.pm b/Slim/Plugin/UPnP/MediaServer/MediaReceiverRegistrar.pm new file mode 100644 index 00000000000..8e375dac7fc --- /dev/null +++ b/Slim/Plugin/UPnP/MediaServer/MediaReceiverRegistrar.pm @@ -0,0 +1,73 @@ +package Slim::Plugin::UPnP::MediaServer::MediaReceiverRegistrar; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/MediaServer/MediaReceiverRegistrar.pm 75368 2010-12-16T04:09:11.731914Z andy $ + +use strict; + +use Slim::Utils::Log; +use Slim::Web::HTTP; + +my $log = logger('plugin.upnp'); + +sub init { + my $class = shift; + + Slim::Web::Pages->addPageFunction( + 'plugins/UPnP/MediaServer/MediaReceiverRegistrar.xml', + \&description, + ); +} + +sub shutdown { } + +sub description { + my ( $client, $params ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug('MediaServer MediaReceiverRegistrar.xml requested by ' . $params->{userAgent}); + + return Slim::Web::HTTP::filltemplatefile( "plugins/UPnP/MediaServer/MediaReceiverRegistrar.xml", $params ); +} + +### Eventing + +sub subscribe { + my ( $class, $client, $uuid ) = @_; + + # Send initial notify with complete data + Slim::Plugin::UPnP::Events->notify( + service => $class, + id => $uuid, # only notify this UUID, since this is an initial notify + data => { + AuthorizationGrantedUpdateID => 0, # XXX what should these be? + AuthorizationDeniedUpdateID => 0, + ValidationSucceededUpdateID => 0, + ValidationRevokedUpdateID => 0, + }, + ); +} + +sub unsubscribe { + # Nothing to do +} + +### Action methods + +sub IsAuthorized { + return ( + SOAP::Data->name( Result => 1 ), + ); +} + +sub IsValidated { + return ( + SOAP::Data->name( Result => 1 ), + ); +} + +sub RegisterDevice { + return ( + SOAP::Data->name( RegistrationRespMsg => 1 ), + ); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/Plugin.pm b/Slim/Plugin/UPnP/Plugin.pm new file mode 100644 index 00000000000..7b616a05d90 --- /dev/null +++ b/Slim/Plugin/UPnP/Plugin.pm @@ -0,0 +1,58 @@ +package Slim::Plugin::UPnP::Plugin; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/Plugin.pm 78831 2011-07-25T16:48:09.710754Z andy $ +# +# UPnP/DLNA Media Interface +# Andy Grundman +# andy@slimdevices.com +# + +use strict; +use base qw(Slim::Plugin::Base); + +use Slim::Plugin::UPnP::Discovery; +use Slim::Plugin::UPnP::Events; +use Slim::Plugin::UPnP::MediaRenderer; +use Slim::Plugin::UPnP::MediaServer; +use Slim::Plugin::UPnP::SOAPServer; + +use Slim::Utils::Prefs; +my $prefs = preferences('server'); + +use Slim::Utils::Log; + +my $log = Slim::Utils::Log->addLogCategory( { + category => 'plugin.upnp', + defaultLevel => 'ERROR', + description => 'PLUGIN_UPNP_MODULE_NAME', +} ); + +sub initPlugin { + my $class = shift; + + if ( !defined $prefs->get('maxUPnPImageSize')) { + $prefs->set('maxUPnPImageSize', 1920); + } + + # Core UPnP function + Slim::Plugin::UPnP::Discovery->init || return shutdownPlugin(); + Slim::Plugin::UPnP::Events->init || return shutdownPlugin(); + Slim::Plugin::UPnP::SOAPServer->init; + + # Devices + Slim::Plugin::UPnP::MediaServer->init; + Slim::Plugin::UPnP::MediaRenderer->init; +} + +sub shutdownPlugin { + my $class = shift; + + Slim::Plugin::UPnP::MediaServer->shutdown; + Slim::Plugin::UPnP::MediaRenderer->shutdown; + + Slim::Plugin::UPnP::SOAPServer->shutdown; + Slim::Plugin::UPnP::Discovery->shutdown; + Slim::Plugin::UPnP::Events->shutdown; +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/SOAPServer.pm b/Slim/Plugin/UPnP/SOAPServer.pm new file mode 100644 index 00000000000..e6dc98a8158 --- /dev/null +++ b/Slim/Plugin/UPnP/SOAPServer.pm @@ -0,0 +1,234 @@ +package Slim::Plugin::UPnP::SOAPServer; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/SOAPServer.pm 76276 2011-02-01T19:44:19.488696Z andy $ +# +# SOAP handling functions. +# Note that SOAP::Lite is only used for parsing requests and generating responses, +# it does not send or receive directly from the network. +# +# This module is based in part on POE::Component::Server::SOAP + +use strict; + +use HTTP::Date; +use SOAP::Lite; +use URI::QueryParam; + +use Slim::Utils::Log; +use Slim::Web::HTTP; + +use Slim::Plugin::UPnP::Common::Utils qw(xmlUnescape); + +my $log = logger('plugin.upnp'); + +# UPnP Errors +my %ERRORS = ( + 401 => 'Invalid Action', + 402 => 'Invalid Args', + 501 => 'Action Failed', + 600 => 'Argument Value Invalid', + 601 => 'Argument Value Out of Range', + 605 => 'String Argument Too Long', +); + +sub init { + my $class = shift; + + Slim::Web::Pages->addRawFunction( + qr{plugins/UPnP/.+/control}, + \&processControl, + ); +} + +sub shutdown { } + +# Receive a raw SOAP control request, verify and process it, +# returning to the caller a data structure containing the +# actual method call and arguments +sub processControl { + my ( $httpClient, $response ) = @_; + + use bytes; + + return unless $httpClient->connected; + + my $request = $response->request; + + # We only handle text/xml content + if ( !$request->header('Content-Type') || $request->header('Content-Type') !~ m{^text/xml}i ) { + $log->warn( 'SOAPServer: Invalid content-type for request: ' . $request->header('Content-Type') ); + fault( $httpClient, $response, 401 ); + return; + } + + # We need the method name + my $soap_method_name = $request->header('SOAPAction'); + if ( !defined $soap_method_name || !length( $soap_method_name ) ) { + $log->warn('SOAPServer: Missing SOAPAction header'); + fault( $httpClient, $response, 401 ); + return; + } + + # Get the method name + if ( $soap_method_name !~ /^([\"\']?)(\S+)\#(\S+)\1$/ ) { + $log->warn('SOAPServer: Missing method name'); + fault( $httpClient, $response, 401 ); + return; + } + + # Get the uri + method + my $soapuri = $2; + my $method = $3; + + # Get service from URL, check for method existence + my ($service) = $request->uri->path =~ m{plugins/UPnP/(.+)/control}; + $service =~ s{/}{::}g; + my $serviceClass = "Slim::Plugin::UPnP::$service"; + + if ( !$serviceClass->can($method) ) { + $log->warn("SOAPServer: $serviceClass does not implement $method"); + fault( $httpClient, $response, 401 ); + return; + } + + # Get client id from URL + my $client; + my $id = $request->uri->query_param('player'); + + if ( $id ) { + $client = Slim::Player::Client::getClient($id); + } + + # JRiver Media Center appends invalid null bytes to its HTTP requests + $request->{_content} =~ s/\0+$//; + + # Parse the request + my $som_object; + eval { $som_object = SOAP::Deserializer->deserialize( $request->content ) }; + + if ( $@ ) { + $log->warn( "SOAPServer: Error parsing request: $@\n" . $request->content ); + fault( $httpClient, $response, 401 ); + return; + } + + # Extract the body + my $body = $som_object->body(); + + # Remove the top-level method name in the body + $body = $body->{ $method }; + + # If it is an empty string, turn it into undef + if ( defined $body and !ref( $body ) and $body eq '' ) { + $body = undef; + } + + main::INFOLOG && $log->is_info && $log->info( "Invoking ${serviceClass}->${method}( " . Data::Dump::dump($body) . ' )' ); + + # Invoke the method + my @result = eval { $serviceClass->$method( $client, $body || {}, $request->headers ) }; + + #warn Data::Dump::dump(\@result) . "\n"; + + if ( $@ ) { + $log->warn( "SOAPServer: Error invoking ${serviceClass}->${method}: $@" ); + fault( $httpClient, $response, 501, $@ ); + return; + } + + # Check if the method set error values, this is known + # if the only return value is an array ref + if ( ref $result[0] eq 'ARRAY' ) { + $log->warn( "SOAPServer: ${serviceClass}->${method} returned error: " . Data::Dump::dump(\@result) ); + fault( $httpClient, $response, $result[0]->[0], $result[0]->[1] ); + return; + } + + # Return response + my $s = SOAP::Serializer->new( + envprefix => 's', + ); + + my $content = $s->envelope( + 'response', + SOAP::Data->new( + name => $method . 'Response', + uri => $soapuri, + prefix => 'u', + ), + @result, + ); + + if ( main::DEBUGLOG && $log->is_debug ) { + $log->debug( "Result: $content" ); + } + + if ( !defined $response->code ) { + $response->code( $SOAP::Constants::HTTP_ON_SUCCESS_CODE ); + } + + $response->header( 'Content-Type' => 'text/xml; charset="utf-8"' ); + $response->header( Ext => '' ); + + $response->remove_header('Server'); + $response->header( Server => Slim::Plugin::UPnP::Discovery->server() ); + $response->header( Date => time2str( time() ) ); + $response->header( 'Content-Length' => length($content) ); + + Slim::Web::HTTP::addHTTPResponse( $httpClient, $response, \$content ); +} + +# Construct and send back a fault message +sub fault { + my ( $httpClient, $response, $error_code, $error_desc ) = @_; + + use bytes; + + my $s = SOAP::Serializer->new( + envprefix => 's', + ); + + my $desc = $ERRORS{ $error_code }; + if ( $error_desc ) { + if ( $desc ) { + $desc .= " ($error_desc)"; + } + else { + $desc = $error_desc; + } + } + $desc ||= 'Unknown Error'; + + + my $content = $s->envelope( + 'fault', + $SOAP::Constants::FAULT_CLIENT, + 'UPnPError', + SOAP::Data->value( + SOAP::Data->name( + errorCode => $error_code + )->type('int'), + SOAP::Data->name( + errorDescription => $desc + )->type('string'), + ), + ); + + $response->code( 500 ); + $response->header( 'Content-Type' => 'text/xml; charset="utf-8"' ); + $response->header( Ext => '' ); + + $response->remove_header('Server'); + $response->header( Server => Slim::Plugin::UPnP::Discovery->server() ); + $response->header( Date => time2str( time() ) ); + $response->header( 'Content-Length' => length($content) ); + + if ( main::DEBUGLOG && $log->is_debug ) { + $log->debug( "UPnP fault: $error_code / " . ( $error_desc || $ERRORS{ $error_code } || 'Unknown Error' ) ); + $log->debug( "Result: $content" ); + } + + Slim::Web::HTTP::addHTTPResponse( $httpClient, $response, \$content ); +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/TODO b/Slim/Plugin/UPnP/TODO new file mode 100644 index 00000000000..2a5a107a250 --- /dev/null +++ b/Slim/Plugin/UPnP/TODO @@ -0,0 +1,36 @@ +UPnP General +------------ +General tests + Discovery, various M-SEARCH types + Eventing + Description XML files + HTTP protocol stuff (DLNA requires various things) + +DLNA +---- +Study libdlna for reference + +MediaRenderer +------------- +Change upnp:// mode playback to a single-track model: +* NextAVTransportURI is internal-only, not exposed as playlist index 2 +* Playlists are also internal, Next/Previous switch between internal tracks, Pandora-like +When not in upnp:// mode, i.e. control point connects during playback of native SBS tracks, radio, etc: +* Only return current track metadata, empty values for Next track +* NumberOfTracks = playlist size +* Next/Previous work like skip +* (is this worth worrying about? maybe should just return nothing if not in upnp:// mode) +DLNA extras +Verify list of content-types is correct +If a control point tries to have us play an item from our own MediaServer, need some special-case handling? + +MediaServer +----------- +Better icon +Proper sorting, although I'm not sure it really matters +Test suite + All menus + UpdateID changes + Eventing +DLNA extras +Cache total count values and use them for childCount attributes? diff --git a/Slim/Plugin/UPnP/install.xml b/Slim/Plugin/UPnP/install.xml new file mode 100644 index 00000000000..4431f6bf894 --- /dev/null +++ b/Slim/Plugin/UPnP/install.xml @@ -0,0 +1,18 @@ + + + C5282612-483D-4B22-8FBF-19F166B1887E + PLUGIN_UPNP_MODULE_NAME + Slim::Plugin::UPnP::Plugin + 1.0 + PLUGIN_UPNP_MODULE_NAME_DESC + Andy Grundman + andy@slimdevices.com + enabled + http://www.slimdevices.com/ + 2 + + Logitech Media Server + 7.6 + * + + diff --git a/Slim/Plugin/UPnP/lib/SOAP/Constants.pm b/Slim/Plugin/UPnP/lib/SOAP/Constants.pm new file mode 100644 index 00000000000..02fdc6e9829 --- /dev/null +++ b/Slim/Plugin/UPnP/lib/SOAP/Constants.pm @@ -0,0 +1,186 @@ +# ====================================================================== +# +# Copyright (C) 2000-2004 Paul Kulchenko (paulclinger@yahoo.com) +# +# SOAP::Lite is free software; you can redistribute it +# and/or modify it under the same terms as Perl itself. +# +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/lib/SOAP/Constants.pm 75368 2010-12-16T04:09:11.731914Z andy $ +# +# ====================================================================== +package SOAP::Constants; +use strict; +use SOAP::Lite; + +our $VERSION = 0.712; + +use constant URI_1999_SCHEMA_XSD => "http://www.w3.org/1999/XMLSchema"; +use constant URI_1999_SCHEMA_XSI => "http://www.w3.org/1999/XMLSchema-instance"; +use constant URI_2000_SCHEMA_XSD => "http://www.w3.org/2000/10/XMLSchema"; +use constant URI_2000_SCHEMA_XSI => "http://www.w3.org/2000/10/XMLSchema-instance"; +use constant URI_2001_SCHEMA_XSD => "http://www.w3.org/2001/XMLSchema"; +use constant URI_2001_SCHEMA_XSI => "http://www.w3.org/2001/XMLSchema-instance"; +use constant URI_LITERAL_ENC => ""; +use constant URI_SOAP11_ENC => "http://schemas.xmlsoap.org/soap/encoding/"; +use constant URI_SOAP11_ENV => "http://schemas.xmlsoap.org/soap/envelope/"; +use constant URI_SOAP11_NEXT_ACTOR => "http://schemas.xmlsoap.org/soap/actor/next"; +use constant URI_SOAP12_ENC => "http://www.w3.org/2003/05/soap-encoding"; +use constant URI_SOAP12_ENV => "http://www.w3.org/2003/05/soap-envelope"; +use constant URI_SOAP12_NOENC => "http://www.w3.org/2003/05/soap-envelope/encoding/none"; +use constant URI_SOAP12_NEXT_ACTOR => "http://www.w3.org/2003/05/soap-envelope/role/next"; + +use vars qw($NSMASK $ELMASK); + +$NSMASK = '[a-zA-Z_:][\w.\-:]*'; +$ELMASK = '^(?![xX][mM][lL])[a-zA-Z_][\w.\-]*$'; + +use vars qw($NEXT_ACTOR $NS_ENV $NS_ENC $NS_APS + $FAULT_CLIENT $FAULT_SERVER $FAULT_VERSION_MISMATCH + $HTTP_ON_FAULT_CODE $HTTP_ON_SUCCESS_CODE $FAULT_MUST_UNDERSTAND + $NS_XSI_ALL $NS_XSI_NILS %XML_SCHEMAS $DEFAULT_XML_SCHEMA + $DEFAULT_HTTP_CONTENT_TYPE + $SOAP_VERSION %SOAP_VERSIONS $WRONG_VERSION + $NS_SL_HEADER $NS_SL_PERLTYPE $PREFIX_ENV $PREFIX_ENC + $DO_NOT_USE_XML_PARSER $DO_NOT_CHECK_MUSTUNDERSTAND + $DO_NOT_USE_CHARSET $DO_NOT_PROCESS_XML_IN_MIME + $DO_NOT_USE_LWP_LENGTH_HACK $DO_NOT_CHECK_CONTENT_TYPE + $MAX_CONTENT_SIZE $PATCH_HTTP_KEEPALIVE $DEFAULT_PACKAGER + @SUPPORTED_ENCODING_STYLES $OBJS_BY_REF_KEEPALIVE + $DEFAULT_CACHE_TTL + %XML_SCHEMA_OF +); + +$FAULT_CLIENT = 'Client'; +$FAULT_SERVER = 'Server'; +$FAULT_VERSION_MISMATCH = 'VersionMismatch'; +$FAULT_MUST_UNDERSTAND = 'MustUnderstand'; + +$HTTP_ON_SUCCESS_CODE = 200; # OK +$HTTP_ON_FAULT_CODE = 500; # INTERNAL_SERVER_ERROR + +@SUPPORTED_ENCODING_STYLES = ( URI_LITERAL_ENC,URI_SOAP11_ENC,URI_SOAP12_ENC,URI_SOAP12_NOENC ); + +$WRONG_VERSION = 'Wrong SOAP version specified.'; + +$SOAP_VERSION = '1.1'; +%SOAP_VERSIONS = ( + 1.1 => { + NEXT_ACTOR => URI_SOAP11_NEXT_ACTOR, + NS_ENV => URI_SOAP11_ENV, + NS_ENC => URI_SOAP11_ENC, + DEFAULT_XML_SCHEMA => URI_2001_SCHEMA_XSD, + DEFAULT_HTTP_CONTENT_TYPE => 'text/xml', + }, + 1.2 => { + NEXT_ACTOR => URI_SOAP12_NEXT_ACTOR, + NS_ENV => URI_SOAP12_ENV, + NS_ENC => URI_SOAP12_ENC, + DEFAULT_XML_SCHEMA => URI_2001_SCHEMA_XSD, + DEFAULT_HTTP_CONTENT_TYPE => 'application/soap+xml', + }, +); + +# schema namespaces +%XML_SCHEMAS = ( # The '()' is necessary to put constants in SCALAR form + URI_1999_SCHEMA_XSD() => 'SOAP::XMLSchema1999', + URI_2001_SCHEMA_XSD() => 'SOAP::XMLSchema2001', + URI_SOAP11_ENC() => 'SOAP::XMLSchemaSOAP1_1', + URI_SOAP12_ENC() => 'SOAP::XMLSchemaSOAP1_2', +); + +# schema namespaces +%XML_SCHEMA_OF = ( # The '()' is necessary to put constants in SCALAR form + URI_1999_SCHEMA_XSD() => 'XMLSchema1999', + URI_2001_SCHEMA_XSD() => 'XMLSchema2001', + URI_SOAP11_ENC() => 'XMLSchemaSOAP1_1', + URI_SOAP12_ENC() => 'XMLSchemaSOAP1_2', +); + + +$NS_XSI_ALL = join join('|', map {"$_-instance"} grep {/XMLSchema/} keys %XML_SCHEMAS), '(?:', ')'; +$NS_XSI_NILS = join join('|', map { my $class = $XML_SCHEMAS{$_} . '::Serializer'; "\{($_)-instance\}" . $class->nilValue + } grep {/XMLSchema/} keys %XML_SCHEMAS), + '(?:', ')'; + +# ApacheSOAP namespaces +$NS_APS = 'http://xml.apache.org/xml-soap'; + +# SOAP::Lite namespace +$NS_SL_HEADER = 'http://namespaces.soaplite.com/header'; +$NS_SL_PERLTYPE = 'http://namespaces.soaplite.com/perl'; + +# default prefixes +$PREFIX_ENV = 'soap'; +$PREFIX_ENC = 'soapenc'; + +# others +$DO_NOT_USE_XML_PARSER = 0; +$DO_NOT_CHECK_MUSTUNDERSTAND = 0; +$DO_NOT_USE_CHARSET = 0; +$DO_NOT_PROCESS_XML_IN_MIME = 0; +$DO_NOT_USE_LWP_LENGTH_HACK = 0; +$DO_NOT_CHECK_CONTENT_TYPE = 0; +$PATCH_HTTP_KEEPALIVE = 1; +$OBJS_BY_REF_KEEPALIVE = 600; # seconds + +# TODO - use default packager constant somewhere +$DEFAULT_PACKAGER = "SOAP::Packager::MIME"; +$DEFAULT_CACHE_TTL = 0; + +1; + +__END__ + +=pod + +=head1 NAME + +SOAP::Constants - SOAP::Lite provides several variables to allows programmers and users to modify the behavior of SOAP::Lite in specific ways. + +=head1 DESCRIPTION + +A number of "constant" values are provided by means of this namespace. The values aren't constants in the strictest sense; the purpose of the values detailed here is to allow the application to change them if it desires to alter the specific behavior governed. + +=head1 CONSTANTS + +=head2 $DO_NOT_USE_XML_PARSER + +The SOAP::Lite package attempts to locate and use the L package, falling back on an internal, pure-Perl parser in its absence. This package is a fast parser, based on the Expat parser developed by James Clark. If the application sets this value to 1, there will be no attempt to locate or use XML::Parser. There are several reasons you might choose to do this. If the package will never be made available, there is no reason to perform the test. Setting this parameter is less time-consuming than the test for the package would be. Also, the XML::Parser code links against the Expat libraries for the C language. In some environments, this could cause a problem when mixed with other applications that may be linked against a different version of the same libraries. This was once the case with certain combinations of Apache, mod_perl and XML::Parser. + +=head2 $DO_NOT_USE_CHARSET + +Unless this parameter is set to 1, outgoing Content-Type headers will include specification of the character set used in encoding the message itself. Not all endpoints (client or server) may be able to properly deal with that data on the content header, however. If dealing with an endpoint that expects to do a more literal examination of the header as whole (as opposed to fully parsing it), this parameter may prove useful. + +=head2 $DO_NOT_CHECK_CONTENT_TYPE + +The content-type itself for a SOAP message is rather clearly defined, and in most cases, an application would have no reason to disable the testing of that header. This having been said, the content-type for SOAP 1.2 is still only a recommended draft, and badly coded endpoints might send valid messages with invalid Content-Type headers. While the "right" thing to do would be to reject such messages, that isn't always an option. Setting this parameter to 1 allows the toolkit to skip the content-type test. + +=head2 $PATCH_HTTP_KEEPALIVE + +SOAP::Lite's HTTP Transport module attempts to provide a simple patch to +LWP::Protocol to enable HTTP Keep Alive. By default, this patch is turned +off, if however you would like to turn on the experimental patch change the +constant like so: + + $SOAP::Constants::PATCH_HTTP_KEEPALIVE = 1; + +=head1 ACKNOWLEDGEMENTS + +Special thanks to O'Reilly publishing which has graciously allowed SOAP::Lite to republish and redistribute large excerpts from I, mainly the SOAP::Lite reference found in Appendix B. + +=head1 COPYRIGHT + +Copyright (C) 2000-2004 Paul Kulchenko. All rights reserved. + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=head1 AUTHORS + +Paul Kulchenko (paulclinger@yahoo.com) + +Randy J. Ray (rjray@blackperl.com) + +Byrne Reese (byrne@majordojo.com) + +=cut diff --git a/Slim/Plugin/UPnP/lib/SOAP/Lite.pm b/Slim/Plugin/UPnP/lib/SOAP/Lite.pm new file mode 100644 index 00000000000..3cc0a706c76 --- /dev/null +++ b/Slim/Plugin/UPnP/lib/SOAP/Lite.pm @@ -0,0 +1,5611 @@ +# ====================================================================== +# +# Copyright (C) 2000-2005 Paul Kulchenko (paulclinger@yahoo.com) +# SOAP::Lite is free software; you can redistribute it +# and/or modify it under the same terms as Perl itself. +# +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/lib/SOAP/Lite.pm 75368 2010-12-16T04:09:11.731914Z andy $ +# +# ====================================================================== + +# Formatting hint: +# Target is the source code format laid out in Perl Best Practices (4 spaces +# indent, opening brace on condition line, no cuddled else). +# +# October 2007, Martin Kutter + +package SOAP::Lite; + +use 5.006; #weak references require perl 5.6 +use strict; +our $VERSION = 0.712; +# ====================================================================== + +package SOAP::XMLSchemaApacheSOAP::Deserializer; + +sub as_map { + my $self = shift; + return { + map { + my $hash = ($self->decode_object($_))[1]; + ($hash->{key} => $hash->{value}) + } @{$_[3] || []} + }; +} +sub as_Map; *as_Map = \&as_map; + +# Thank to Kenneth Draper for this contribution +sub as_vector { + my $self = shift; + return [ map { scalar(($self->decode_object($_))[1]) } @{$_[3] || []} ]; +} +sub as_Vector; *as_Vector = \&as_vector; + +# ---------------------------------------------------------------------- + +package SOAP::XMLSchema::Serializer; + +use vars qw(@ISA); + +sub xmlschemaclass { + my $self = shift; + return $ISA[0] unless @_; + @ISA = (shift); + return $self; +} + +# ---------------------------------------------------------------------- + +package SOAP::XMLSchema1999::Serializer; + +use vars qw(@EXPORT $AUTOLOAD); + +sub AUTOLOAD { + local($1,$2); + my($package, $method) = $AUTOLOAD =~ m/(?:(.+)::)([^:]+)$/; + return if $method eq 'DESTROY'; + no strict 'refs'; + + my $export_var = $package . '::EXPORT'; + my @export = @$export_var; + +# Removed in 0.69 - this is a total hack. For some reason this is failing +# despite not being a fatal error condition. +# die "Type '$method' can't be found in a schema class '$package'\n" +# unless $method =~ s/^as_// && grep {$_ eq $method} @{$export_var}; + +# This was added in its place - it is still a hack, but it performs the +# necessary substitution. It just does not die. + if ($method =~ s/^as_// && grep {$_ eq $method} @{$export_var}) { +# print STDERR "method is now '$method'\n"; + } else { + return; + } + + $method =~ s/_/-/; # fix ur-type + + *$AUTOLOAD = sub { + my $self = shift; + my($value, $name, $type, $attr) = @_; + return [$name, {'xsi:type' => "xsd:$method", %$attr}, $value]; + }; + goto &$AUTOLOAD; +} + +BEGIN { + @EXPORT = qw(ur_type + float double decimal timeDuration recurringDuration uriReference + integer nonPositiveInteger negativeInteger long int short byte + nonNegativeInteger unsignedLong unsignedInt unsignedShort unsignedByte + positiveInteger timeInstant time timePeriod date month year century + recurringDate recurringDay language + base64 hex string boolean + ); + # TODO: replace by symbol table operations... + # predeclare subs, so ->can check will be positive + foreach (@EXPORT) { eval "sub as_$_" } +} + +sub nilValue { 'null' } + +sub anyTypeValue { 'ur-type' } + +sub as_base64 { + my ($self, $value, $name, $type, $attr) = @_; + + # Fixes #30271 for 5.8 and above. + # Won't fix for 5.6 and below - perl can't handle unicode before + # 5.8, and applying pack() to everything is just a slowdown. + if (eval "require Encode; 1") { + if (Encode::is_utf8($value)) { + if (Encode->can('_utf8_off')) { # the quick way, but it may change in future Perl versions. + Encode::_utf8_off($value); + } + else { + $value = pack('C*',unpack('C*',$value)); # the slow but safe way, + # but this fallback works always. + } + } + } + + require MIME::Base64; + return [ + $name, + { + 'xsi:type' => SOAP::Utils::qualify($self->encprefix => 'base64'), + %$attr + }, + MIME::Base64::encode_base64($value,'') + ]; +} + +sub as_hex { + my ($self, $value, $name, $type, $attr) = @_; + return [ + $name, + { + 'xsi:type' => 'xsd:hex', %$attr + }, + join '', map { + uc sprintf "%02x", ord + } split '', $value + ]; +} + +sub as_long { + my($self, $value, $name, $type, $attr) = @_; + return [ + $name, + {'xsi:type' => 'xsd:long', %$attr}, + $value + ]; +} + +sub as_dateTime { + my ($self, $value, $name, $type, $attr) = @_; + return [$name, {'xsi:type' => 'xsd:dateTime', %$attr}, $value]; +} + +sub as_string { + my ($self, $value, $name, $type, $attr) = @_; + die "String value expected instead of @{[ref $value]} reference\n" + if ref $value; + return [ + $name, + {'xsi:type' => 'xsd:string', %$attr}, + SOAP::Utils::encode_data($value) + ]; +} + +sub as_anyURI { + my($self, $value, $name, $type, $attr) = @_; + die "String value expected instead of @{[ref $value]} reference\n" if ref $value; + return [ + $name, + {'xsi:type' => 'xsd:anyURI', %$attr}, + SOAP::Utils::encode_data($value) + ]; +} + +sub as_undef { $_[1] ? '1' : '0' } + +sub as_boolean { + my $self = shift; + my($value, $name, $type, $attr) = @_; + # fix [ 1204279 ] Boolean serialization error + return [ + $name, + {'xsi:type' => 'xsd:boolean', %$attr}, + ( $value ne 'false' && $value ) ? 'true' : 'false' + ]; +} + +sub as_float { + my($self, $value, $name, $type, $attr) = @_; + return [ + $name, + {'xsi:type' => 'xsd:float', %$attr}, + $value + ]; +} + +# ---------------------------------------------------------------------- + +package SOAP::XMLSchema2001::Serializer; + +use vars qw(@EXPORT); + +# no more warnings about "used only once" +*AUTOLOAD if 0; + +*AUTOLOAD = \&SOAP::XMLSchema1999::Serializer::AUTOLOAD; + +BEGIN { + @EXPORT = qw(anyType anySimpleType float double decimal dateTime + timePeriod gMonth gYearMonth gYear century + gMonthDay gDay duration recurringDuration anyURI + language integer nonPositiveInteger negativeInteger + long int short byte nonNegativeInteger unsignedLong + unsignedInt unsignedShort unsignedByte positiveInteger + date time string hex base64 boolean + QName + ); + # Add QName to @EXPORT + # predeclare subs, so ->can check will be positive + foreach (@EXPORT) { eval "sub as_$_" } +} + +sub nilValue { 'nil' } + +sub anyTypeValue { 'anyType' } + +sub as_long; *as_long = \&SOAP::XMLSchema1999::Serializer::as_long; +sub as_float; *as_float = \&SOAP::XMLSchema1999::Serializer::as_float; +sub as_string; *as_string = \&SOAP::XMLSchema1999::Serializer::as_string; +sub as_anyURI; *as_anyURI = \&SOAP::XMLSchema1999::Serializer::as_anyURI; + +# TODO - QNames still don't work for 2001 schema! +sub as_QName; *as_QName = \&SOAP::XMLSchema1999::Serializer::as_string; +sub as_hex; *as_hex = \&as_hexBinary; +sub as_base64; *as_base64 = \&as_base64Binary; +sub as_timeInstant; *as_timeInstant = \&as_dateTime; + +# only 0 and 1 allowed - that's easy... +sub as_undef { + $_[1] + ? 'true' + : 'false' +} + +sub as_hexBinary { + my ($self, $value, $name, $type, $attr) = @_; + return [ + $name, + {'xsi:type' => 'xsd:hexBinary', %$attr}, + join '', map { + uc sprintf "%02x", ord + } split '', $value + ]; +} + +sub as_base64Binary { + my ($self, $value, $name, $type, $attr) = @_; + + # Fixes #30271 for 5.8 and above. + # Won't fix for 5.6 and below - perl can't handle unicode before + # 5.8, and applying pack() to everything is just a slowdown. + if (eval "require Encode; 1") { + if (Encode::is_utf8($value)) { + if (Encode->can('_utf8_off')) { # the quick way, but it may change in future Perl versions. + Encode::_utf8_off($value); + } + else { + $value = pack('C*',unpack('C*',$value)); # the slow but safe way, + # but this fallback works always. + } + } + } + + require MIME::Base64; + return [ + $name, + { + 'xsi:type' => 'xsd:base64Binary', %$attr + }, + MIME::Base64::encode_base64($value,'') + ]; +} + +sub as_boolean { + my ($self, $value, $name, $type, $attr) = @_; + # fix [ 1204279 ] Boolean serialization error + return [ + $name, + { + 'xsi:type' => 'xsd:boolean', %$attr + }, + ( $value ne 'false' && $value ) + ? 'true' + : 'false' + ]; +} + + +# ====================================================================== + +package SOAP::Utils; + +sub qualify { + $_[1] + ? $_[1] =~ /:/ + ? $_[1] + : join(':', $_[0] || (), $_[1]) + : defined $_[1] + ? $_[0] + : '' + } + +sub overqualify (&$) { + for ($_[1]) { + &{$_[0]}; + s/^:|:$//g + } +} + +sub disqualify { + (my $qname = shift) =~ s/^($SOAP::Constants::NSMASK?)://; + return $qname; +} + +sub splitqname { + local($1,$2); + $_[0] =~ /^(?:([^:]+):)?(.+)$/; + return ($1,$2) +} + +sub longname { + defined $_[0] + ? sprintf('{%s}%s', $_[0], $_[1]) + : $_[1] +} + +sub splitlongname { + local($1,$2); + $_[0] =~ /^(?:\{(.*)\})?(.+)$/; + return ($1,$2) +} + +# Q: why only '&' and '<' are encoded, but not '>'? +# A: because it is not required according to XML spec. +# +# [http://www.w3.org/TR/REC-xml#syntax] +# The ampersand character (&) and the left angle bracket (<) may appear in +# their literal form only when used as markup delimiters, or within a comment, +# a processing instruction, or a CDATA section. If they are needed elsewhere, +# they must be escaped using either numeric character references or the +# strings "&" and "<" respectively. The right angle bracket (>) may be +# represented using the string ">", and must, for compatibility, be +# escaped using ">" or a character reference when it appears in the +# string "]]>" in content, when that string is not marking the end of a +# CDATA section. + +my %encode_attribute = ('&' => '&', '>' => '>', '<' => '<', '"' => '"'); +sub encode_attribute { (my $e = $_[0]) =~ s/([&<>\"])/$encode_attribute{$1}/g; $e } + +my %encode_data = ('&' => '&', '>' => '>', '<' => '<', "\xd" => ' '); +sub encode_data { + my $e = $_[0]; + if ($e) { + $e =~ s/([&<>\015])/$encode_data{$1}/g; + $e =~ s/\]\]>/\]\]>/g; + } + $e +} + +# methods for internal tree (SOAP::Deserializer, SOAP::SOM and SOAP::Serializer) + +sub o_qname { $_[0]->[0] } +sub o_attr { $_[0]->[1] } +sub o_child { ref $_[0]->[2] ? $_[0]->[2] : undef } +sub o_chars { ref $_[0]->[2] ? undef : $_[0]->[2] } + # $_[0]->[3] is not used. Serializer stores object ID there +sub o_value { $_[0]->[4] } +sub o_lname { $_[0]->[5] } +sub o_lattr { $_[0]->[6] } + +sub format_datetime { + my ($s,$m,$h,$D,$M,$Y) = (@_)[0,1,2,3,4,5]; + my $time = sprintf("%04d-%02d-%02dT%02d:%02d:%02d",($Y+1900),($M+1),$D,$h,$m,$s); + return $time; +} + +# make bytelength that calculates length in bytes regardless of utf/byte settings +# either we can do 'use bytes' or length will count bytes already +BEGIN { + sub bytelength; + *bytelength = eval('use bytes; 1') # 5.6.0 and later? + ? sub { use bytes; length(@_ ? $_[0] : $_) } + : sub { length(@_ ? $_[0] : $_) }; +} + +# ====================================================================== + +package SOAP::Cloneable; + +sub clone { + my $self = shift; + + return unless ref $self && UNIVERSAL::isa($self => __PACKAGE__); + + my $clone = bless {} => ref($self) || $self; + for (keys %$self) { + my $value = $self->{$_}; + $clone->{$_} = ref $value && UNIVERSAL::isa($value => __PACKAGE__) ? $value->clone : $value; + } + return $clone; +} + +# ====================================================================== + +package SOAP::Transport; + +use vars qw($AUTOLOAD @ISA); +@ISA = qw(SOAP::Cloneable); + +use Class::Inspector; + + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + return $self if ref $self; + my $class = ref($self) || $self; + + SOAP::Trace::objects('()'); + return bless {} => $class; +} + +sub proxy { + my $self = shift; + $self = $self->new() if not ref $self; + + my $class = ref $self; + + return $self->{_proxy} unless @_; + + $_[0] =~ /^(\w+):/ or die "proxy: transport protocol not specified\n"; + my $protocol = uc "$1"; # untainted now + + # HTTPS is handled by HTTP class + $protocol =~s/^HTTPS$/HTTP/; + + (my $protocol_class = "${class}::$protocol") =~ s/-/_/g; + + no strict 'refs'; + unless (Class::Inspector->loaded("$protocol_class\::Client") + && UNIVERSAL::can("$protocol_class\::Client" => 'new') + ) { + eval "require $protocol_class"; + die "Unsupported protocol '$protocol'\n" + if $@ =~ m!^Can\'t locate SOAP/Transport/!; + die if $@; + } + + $protocol_class .= "::Client"; + return $self->{_proxy} = $protocol_class->new(endpoint => shift, @_); +} + +sub AUTOLOAD { + my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); + return if $method eq 'DESTROY'; + + no strict 'refs'; + *$AUTOLOAD = sub { shift->proxy->$method(@_) }; + goto &$AUTOLOAD; +} + +# ====================================================================== + +package SOAP::Fault; + +use Carp (); + +use overload fallback => 1, '""' => "stringify"; + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + + unless (ref $self) { + my $class = $self; + $self = bless {} => $class; + SOAP::Trace::objects('()'); + } + + Carp::carp "Odd (wrong?) number of parameters in new()" + if $^W && (@_ & 1); + + no strict qw(refs); + while (@_) { + my $method = shift; + $self->$method(shift) + if $self->can($method) + } + + return $self; +} + +sub stringify { + my $self = shift; + return join ': ', $self->faultcode, $self->faultstring; +} + +sub BEGIN { + no strict 'refs'; + for my $method (qw(faultcode faultstring faultactor faultdetail)) { + my $field = '_' . $method; + *$method = sub { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new + : __PACKAGE__->new; + if (@_) { + $self->{$field} = shift; + return $self + } + return $self->{$field}; + } + } + *detail = \&faultdetail; +} + +# ====================================================================== + +package SOAP::Data; + +use vars qw(@ISA @EXPORT_OK); +use Exporter; +use Carp (); +use SOAP::Lite::Deserializer::XMLSchemaSOAP1_2; + +@ISA = qw(Exporter); +@EXPORT_OK = qw(name type attr value uri); + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + + unless (ref $self) { + my $class = $self; + $self = bless {_attr => {}, _value => [], _signature => []} => $class; + SOAP::Trace::objects('()'); + } + no strict qw(refs); + Carp::carp "Odd (wrong?) number of parameters in new()" if $^W && (@_ & 1); + while (@_) { + my $method = shift; + $self->$method(shift) if $self->can($method) + } + + return $self; +} + +sub name { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) ? shift->new : __PACKAGE__->new; + if (@_) { + my ($name, $uri, $prefix) = shift; + if ($name) { + ($uri, $name) = SOAP::Utils::splitlongname($name); + unless (defined $uri) { + ($prefix, $name) = SOAP::Utils::splitqname($name); + $self->prefix($prefix) if defined $prefix; + } else { + $self->uri($uri); + } + } + $self->{_name} = $name; + + $self->value(@_) if @_; + return $self; + } + return $self->{_name}; +} + +sub attr { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + if (@_) { + $self->{_attr} = shift; + $self->value(@_) if @_; + return $self + } + return $self->{_attr}; +} + +sub type { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + if (@_) { + $self->{_type} = shift; + $self->value(@_) if @_; + return $self; + } + if (!defined $self->{_type} && (my @types = grep {/^\{$SOAP::Constants::NS_XSI_ALL}type$/o} keys %{$self->{_attr}})) { + $self->{_type} = (SOAP::Utils::splitlongname(delete $self->{_attr}->{shift(@types)}))[1]; + } + return $self->{_type}; +} + +BEGIN { + no strict 'refs'; + for my $method (qw(root mustUnderstand)) { + my $field = '_' . $method; + *$method = sub { + my $attr = $method eq 'root' + ? "{$SOAP::Constants::NS_ENC}$method" + : "{$SOAP::Constants::NS_ENV}$method"; + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new + : __PACKAGE__->new; + if (@_) { + $self->{_attr}->{$attr} = $self->{$field} = shift() ? 1 : 0; + $self->value(@_) if @_; + return $self; + } + $self->{$field} = SOAP::Lite::Deserializer::XMLSchemaSOAP1_2->as_boolean($self->{_attr}->{$attr}) + if !defined $self->{$field} && defined $self->{_attr}->{$attr}; + return $self->{$field}; + } + } + + for my $method (qw(actor encodingStyle)) { + my $field = '_' . $method; + *$method = sub { + my $attr = "{$SOAP::Constants::NS_ENV}$method"; + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + if (@_) { + $self->{_attr}->{$attr} = $self->{$field} = shift; + $self->value(@_) if @_; + return $self; + } + $self->{$field} = $self->{_attr}->{$attr} + if !defined $self->{$field} && defined $self->{_attr}->{$attr}; + return $self->{$field}; + } + } +} + +sub prefix { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + return $self->{_prefix} unless @_; + $self->{_prefix} = shift; + $self->value(@_) if @_; + return $self; +} + +sub uri { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + return $self->{_uri} unless @_; + my $uri = $self->{_uri} = shift; + warn "Usage of '::' in URI ($uri) deprecated. Use '/' instead\n" + if defined $uri && $^W && $uri =~ /::/; + $self->value(@_) if @_; + return $self; +} + +sub set_value { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + $self->{_value} = [@_]; + return $self; +} + +sub value { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new; + (@_) + ? ($self->set_value(@_), return $self) + : wantarray + ? return @{$self->{_value}} + : return $self->{_value}->[0]; +} + +sub signature { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? shift->new() + : __PACKAGE__->new(); + (@_) + ? ($self->{_signature} = shift, return $self) + : (return $self->{_signature}); +} + +# ====================================================================== + +package SOAP::Header; + +use vars qw(@ISA); +@ISA = qw(SOAP::Data); + +# ====================================================================== + +package SOAP::Serializer; +use SOAP::Lite::Utils; +use Carp (); +use vars qw(@ISA); + +@ISA = qw(SOAP::Cloneable SOAP::XMLSchema::Serializer); + +BEGIN { + # namespaces and anonymous data structures + my $ns = 0; + my $name = 0; + my $prefix = 'c-'; + sub gen_ns { 'namesp' . ++$ns } + sub gen_name { join '', $prefix, 'gensym', ++$name } + sub prefix { $prefix =~ s/^[^\-]+-/$_[1]-/; $_[0]; } +} + +sub BEGIN { + no strict 'refs'; + + __PACKAGE__->__mk_accessors(qw(readable level seen autotype typelookup attr maptype + namespaces multirefinplace encoding signature on_nonserialized context + ns_uri ns_prefix use_default_ns)); + + for my $method (qw(method fault freeform)) { # aliases for envelope + *$method = sub { shift->envelope($method => @_) } + } + # Is this necessary? Seems like work for nothing when a user could just use + # SOAP::Utils directly. + # for my $method (qw(qualify overqualify disqualify)) { # import from SOAP::Utils + # *$method = \&{'SOAP::Utils::'.$method}; + # } +} + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + return $self if ref $self; + + my $class = $self; + $self = bless { + _level => 0, + _autotype => 1, + _readable => 0, + _ns_uri => '', + _ns_prefix => '', + _use_default_ns => 1, + _multirefinplace => 0, + _seen => {}, + _typelookup => { + # this breaks UPnP -Andy + # 'base64Binary' => + # [10, sub {$_[0] =~ /[^\x09\x0a\x0d\x20-\x7f]/ }, 'as_base64Binary'], + 'zerostring' => + [12, sub { $_[0] =~ /^0\d+$/ }, 'as_string'], + # int (and actually long too) are subtle: the negative range is one greater... + 'int' => + [20, sub {$_[0] =~ /^([+-]?\d+)$/ && ($1 <= 2147483647) && ($1 >= -2147483648); }, 'as_int'], + 'long' => + [25, sub {$_[0] =~ /^([+-]?\d+)$/ && $1 <= 9223372036854775807;}, 'as_long'], + 'float' => + [30, sub {$_[0] =~ /^(-?(?:\d+(?:\.\d*)?|\.\d+|NaN|INF)|([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)$/}, 'as_float'], + 'gMonth' => + [35, sub { $_[0] =~ /^--\d\d--(-\d\d:\d\d)?$/; }, 'as_gMonth'], + 'gDay' => + [40, sub { $_[0] =~ /^---\d\d(-\d\d:\d\d)?$/; }, 'as_gDay'], + 'gYear' => + [45, sub { $_[0] =~ /^-?\d\d\d\d(-\d\d:\d\d)?$/; }, 'as_gYear'], + 'gMonthDay' => + [50, sub { $_[0] =~ /^-\d\d-\d\d(-\d\d:\d\d)?$/; }, 'as_gMonthDay'], + 'gYearMonth' => + [55, sub { $_[0] =~ /^-?\d\d\d\d-\d\d(Z|([+-]\d\d:\d\d))?$/; }, 'as_gYearMonth'], + 'date' => + [60, sub { $_[0] =~ /^-?\d\d\d\d-\d\d-\d\d(Z|([+-]\d\d:\d\d))?$/; }, 'as_date'], + 'time' => + [70, sub { $_[0] =~ /^\d\d:\d\d:\d\d(\.\d\d\d)?(Z|([+-]\d\d:\d\d))?$/; }, 'as_time'], + 'dateTime' => + [75, sub { $_[0] =~ /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\d)?(Z|([+-]\d\d:\d\d))?$/; }, 'as_dateTime'], + 'duration' => + [80, sub { $_[0] !~m{^-?PT?$} && $_[0] =~ m{^ + -? # a optional - sign + P + (:? \d+Y )? + (:? \d+M )? + (:? \d+D )? + (:? + T(:?\d+H)? + (:?\d+M)? + (:?\d+S)? + )? + $ + }x; + }, 'as_duration'], + 'boolean' => + [90, sub { $_[0] =~ /^(true|false)$/i; }, 'as_boolean'], + 'anyURI' => + [95, sub { $_[0] =~ /^(urn:|http:\/\/)/i; }, 'as_anyURI'], + 'string' => + [100, sub {1}, 'as_string'], + }, + _encoding => 'UTF-8', + _objectstack => {}, + _signature => [], + _maptype => {}, + _on_nonserialized => sub {Carp::carp "Cannot marshall @{[ref shift]} reference" if $^W; return}, + _encodingStyle => $SOAP::Constants::NS_ENC, + _attr => { + "{$SOAP::Constants::NS_ENV}encodingStyle" => $SOAP::Constants::NS_ENC, + }, + _namespaces => {}, + _soapversion => SOAP::Lite->soapversion, + } => $class; + $self->register_ns($SOAP::Constants::NS_ENC,$SOAP::Constants::PREFIX_ENC); + $self->register_ns($SOAP::Constants::NS_ENV,$SOAP::Constants::PREFIX_ENV) + if $SOAP::Constants::PREFIX_ENV; + $self->xmlschema($SOAP::Constants::DEFAULT_XML_SCHEMA); + SOAP::Trace::objects('()'); + + no strict qw(refs); + Carp::carp "Odd (wrong?) number of parameters in new()" if $^W && (@_ & 1); + while (@_) { my $method = shift; $self->$method(shift) if $self->can($method) } + + return $self; +} + +sub ns { + my $self = shift; + $self = $self->new() if not ref $self; + if (@_) { + my ($u,$p) = @_; + my $prefix; + + if ($p) { + $prefix = $p; + } + elsif (!$p && !($prefix = $self->find_prefix($u))) { + $prefix = gen_ns; + } + + $self->{'_ns_uri'} = $u; + $self->{'_ns_prefix'} = $prefix; + $self->{'_use_default_ns'} = 0; + # $self->register_ns($u,$prefix); + $self->{'_namespaces'}->{$u} = $prefix; + return $self; + } + return $self->{'_ns_uri'}; +} + +sub default_ns { + my $self = shift; + $self = $self->new() if not ref $self; + if (@_) { + my ($u) = @_; + $self->{'_ns_uri'} = $u; + $self->{'_ns_prefix'} = ''; + $self->{'_use_default_ns'} = 1; + return $self; + } + return $self->{'_ns_uri'}; +} + +sub use_prefix { + my $self = shift; + $self = $self->new() if not ref $self; + warn 'use_prefix has been deprecated. if you wish to turn off or on the ' + . 'use of a default namespace, then please use either ns(uri) or default_ns(uri)'; + if (@_) { + my $use = shift; + $self->{'_use_default_ns'} = !$use || 0; + return $self; + } else { + return $self->{'_use_default_ns'}; + } +} +sub uri { + my $self = shift; + $self = $self->new() if not ref $self; +# warn 'uri has been deprecated. if you wish to set the namespace for the request, then please use either ns(uri) or default_ns(uri)'; + if (@_) { + my $ns = shift; + if ($self->{_use_default_ns}) { + $self->default_ns($ns); + } + else { + $self->ns($ns); + } +# $self->{'_ns_uri'} = $ns; +# $self->register_ns($self->{'_ns_uri'}) if (!$self->{_use_default_ns}); + return $self; + } + return $self->{'_ns_uri'}; +} + +sub encodingStyle { + my $self = shift; + $self = $self->new() if not ref $self; + return $self->{'_encodingStyle'} unless @_; + + my $cur_style = $self->{'_encodingStyle'}; + delete($self->{'_namespaces'}->{$cur_style}); + + my $new_style = shift; + if ($new_style eq "") { + delete($self->{'_attr'}->{"{$SOAP::Constants::NS_ENV}encodingStyle"}); + } + else { + $self->{'_attr'}->{"{$SOAP::Constants::NS_ENV}encodingStyle"} = $new_style; + $self->{'_namespaces'}->{$new_style} = $SOAP::Constants::PREFIX_ENC; + } +} + +# TODO - changing SOAP version can affect previously set encodingStyle +sub soapversion { + my $self = shift; + return $self->{_soapversion} unless @_; + return $self if $self->{_soapversion} eq SOAP::Lite->soapversion; + $self->{_soapversion} = shift; + + $self->attr({ + "{$SOAP::Constants::NS_ENV}encodingStyle" => $SOAP::Constants::NS_ENC, + }); + $self->namespaces({ + $SOAP::Constants::NS_ENC => $SOAP::Constants::PREFIX_ENC, + $SOAP::Constants::PREFIX_ENV ? ($SOAP::Constants::NS_ENV => $SOAP::Constants::PREFIX_ENV) : (), + }); + $self->xmlschema($SOAP::Constants::DEFAULT_XML_SCHEMA); + + return $self; +} + +sub xmlschema { + my $self = shift->new; + return $self->{_xmlschema} unless @_; + + my @schema; + if ($_[0]) { + @schema = grep {/XMLSchema/ && /$_[0]/} keys %SOAP::Constants::XML_SCHEMAS; + Carp::croak "More than one schema match parameter '$_[0]': @{[join ', ', @schema]}" if @schema > 1; + Carp::croak "No schema match parameter '$_[0]'" if @schema != 1; + } + + # do nothing if current schema is the same as new + return $self if $self->{_xmlschema} && $self->{_xmlschema} eq $schema[0]; + + my $ns = $self->namespaces; + + # delete current schema from namespaces + if (my $schema = $self->{_xmlschema}) { + delete $ns->{$schema}; + delete $ns->{"$schema-instance"}; + } + + # add new schema into namespaces + if (my $schema = $self->{_xmlschema} = shift @schema) { + $ns->{$schema} = 'xsd'; + $ns->{"$schema-instance"} = 'xsi'; + } + + # and here is the class serializer should work with + my $class = exists $SOAP::Constants::XML_SCHEMAS{$self->{_xmlschema}} + ? $SOAP::Constants::XML_SCHEMAS{$self->{_xmlschema}} . '::Serializer' + : $self; + + $self->xmlschemaclass($class); + + return $self; +} + +sub envprefix { + my $self = shift->new(); + return $self->namespaces->{$SOAP::Constants::NS_ENV} unless @_; + $self->namespaces->{$SOAP::Constants::NS_ENV} = shift; + return $self; +} + +sub encprefix { + my $self = shift->new(); + return $self->namespaces->{$SOAP::Constants::NS_ENC} unless @_; + $self->namespaces->{$SOAP::Constants::NS_ENC} = shift; + return $self; +} + +sub gen_id { sprintf "%U", $_[1] } + +sub multiref_object { + my ($self, $object) = @_; + my $id = $self->gen_id($object); + my $seen = $self->seen; + $seen->{$id}->{count}++; + $seen->{$id}->{multiref} ||= $seen->{$id}->{count} > 1; + $seen->{$id}->{value} = $object; + $seen->{$id}->{recursive} ||= 0; + return $id; +} + +sub recursive_object { + my $self = shift; + $self->seen->{$self->gen_id(shift)}->{recursive} = 1; +} + +sub is_href { + my $self = shift; + my $seen = $self->seen->{shift || return} or return; + return 1 if $seen->{id}; + return $seen->{multiref} + && !($seen->{id} = (shift + || $seen->{recursive} + || $seen->{multiref} && $self->multirefinplace)); +} + +sub multiref_anchor { + my $seen = shift->seen->{my $id = shift || return undef}; + return $seen->{multiref} ? "ref-$id" : undef; +} + +sub encode_multirefs { + my $self = shift; + return if $self->multirefinplace(); + + my $seen = $self->seen(); + map { $_->[1]->{_id} = 1; $_ } + map { $self->encode_object($seen->{$_}->{value}) } + grep { $seen->{$_}->{multiref} && !$seen->{$_}->{recursive} } + keys %$seen; +} + +sub maptypetouri { + my($self, $type, $simple) = @_; + + return $type unless defined $type; + my($prefix, $name) = SOAP::Utils::splitqname($type); + + unless (defined $prefix) { + $name =~ s/__|\./::/g; + $self->maptype->{$name} = $simple + ? die "Schema/namespace for type '$type' is not specified\n" + : $SOAP::Constants::NS_SL_PERLTYPE + unless exists $self->maptype->{$name}; + $type = $self->maptype->{$name} + ? SOAP::Utils::qualify($self->namespaces->{$self->maptype->{$name}} ||= gen_ns, $type) + : undef; + } + return $type; +} + +sub encode_object { + my($self, $object, $name, $type, $attr) = @_; + + $attr ||= {}; + return $self->encode_scalar($object, $name, $type, $attr) + unless ref $object; + + my $id = $self->multiref_object($object); + + use vars '%objectstack'; # we'll play with symbol table + local %objectstack = %objectstack; # want to see objects ONLY in the current tree + # did we see this object in current tree? Seems to be recursive refs + $self->recursive_object($object) if ++$objectstack{$id} > 1; + # return if we already saw it twice. It should be already properly serialized + return if $objectstack{$id} > 2; + + if (UNIVERSAL::isa($object => 'SOAP::Data')) { + # use $object->SOAP::Data:: to enable overriding name() and others in inherited classes + $object->SOAP::Data::name($name) + unless defined $object->SOAP::Data::name; + + # apply ->uri() and ->prefix() which can modify name and attributes of + # element, but do not modify SOAP::Data itself + my($name, $attr) = $self->fixattrs($object); + $attr = $self->attrstoqname($attr); + + my @realvalues = $object->SOAP::Data::value; + return [$name || gen_name, $attr] unless @realvalues; + + my $method = "as_" . ($object->SOAP::Data::type || '-'); # dummy type if not defined + # try to call method specified for this type + no strict qw(refs); + my @values = map { + # store null/nil attribute if value is undef + local $attr->{SOAP::Utils::qualify(xsi => $self->xmlschemaclass->nilValue)} = $self->xmlschemaclass->as_undef(1) + unless defined; + $self->can($method) && $self->$method($_, $name || gen_name, $object->SOAP::Data::type, $attr) + || $self->typecast($_, $name || gen_name, $object->SOAP::Data::type, $attr) + || $self->encode_object($_, $name, $object->SOAP::Data::type, $attr) + } @realvalues; + $object->SOAP::Data::signature([map {join $;, $_->[0], SOAP::Utils::disqualify($_->[1]->{'xsi:type'} || '')} @values]) if @values; + return wantarray ? @values : $values[0]; + } + + my $class = ref $object; + + if ($class !~ /^(?:SCALAR|ARRAY|HASH|REF)$/o) { + # we could also check for CODE|GLOB|LVALUE, but we cannot serialize + # them anyway, so they'll be cought by check below + $class =~ s/::/__/g; + + $name = $class if !defined $name; + $type = $class if !defined $type && $self->autotype; + + my $method = 'as_' . $class; + if ($self->can($method)) { + no strict qw(refs); + my $encoded = $self->$method($object, $name, $type, $attr); + return $encoded if ref $encoded; + # return only if handled, otherwise handle with default handlers + } + } + + if (UNIVERSAL::isa($object => 'REF') || UNIVERSAL::isa($object => 'SCALAR')) { + return $self->encode_scalar($object, $name, $type, $attr); + } + elsif (UNIVERSAL::isa($object => 'ARRAY')) { + # Added in SOAP::Lite 0.65_6 to fix an XMLRPC bug + return $self->encodingStyle eq "" + || $self->isa('XMLRPC::Serializer') + ? $self->encode_array($object, $name, $type, $attr) + : $self->encode_literal_array($object, $name, $type, $attr); + } + elsif (UNIVERSAL::isa($object => 'HASH')) { + return $self->encode_hash($object, $name, $type, $attr); + } + else { + return $self->on_nonserialized->($object); + } +} + +sub encode_scalar { + my($self, $value, $name, $type, $attr) = @_; + $name ||= gen_name; + + my $schemaclass = $self->xmlschemaclass; + + # null reference + return [$name, {%$attr, SOAP::Utils::qualify(xsi => $schemaclass->nilValue) => $schemaclass->as_undef(1)}] unless defined $value; + + # object reference + return [$name, {'xsi:type' => $self->maptypetouri($type), %$attr}, [$self->encode_object($$value)], $self->gen_id($value)] if ref $value; + + # autodefined type + if ($self->autotype) { + my $lookup = $self->typelookup(); + no strict qw(refs); + for (sort {$lookup->{$a}->[0] <=> $lookup->{$b}->[0]} keys %$lookup) { + my $method = $lookup->{$_}->[2]; + return $self->can($method) && $self->$method($value, $name, $type, $attr) + || $method->($value, $name, $type, $attr) + if $lookup->{$_}->[1]->($value); + } + } + + # invariant + return [$name, $attr, $value]; +} + +sub encode_array { + my($self, $array, $name, $type, $attr) = @_; + my $items = 'item'; + + # If typing is disabled, just serialize each of the array items + # with no type information, each using the specified name, + # and do not crete a wrapper array tag. + if (!$self->autotype) { + $name ||= gen_name; + return map {$self->encode_object($_, $name)} @$array; + } + + # TODO: add support for multidimensional, partially transmitted and sparse arrays + my @items = map {$self->encode_object($_, $items)} @$array; + my $num = @items; + my($arraytype, %types) = '-'; + for (@items) { $arraytype = $_->[1]->{'xsi:type'} || '-'; $types{$arraytype}++ } + $arraytype = sprintf "%s\[$num]", keys %types > 1 || $arraytype eq '-' ? SOAP::Utils::qualify(xsd => $self->xmlschemaclass->anyTypeValue) : $arraytype; + + # $type = SOAP::Utils::qualify($self->encprefix => 'Array') if $self->autotype && !defined $type; + $type = qualify($self->encprefix => 'Array') if !defined $type; + return [$name || SOAP::Utils::qualify($self->encprefix => 'Array'), + { + SOAP::Utils::qualify($self->encprefix => 'arrayType') => $arraytype, + 'xsi:type' => $self->maptypetouri($type), %$attr + }, + [@items], + $self->gen_id($array) + ]; +} + +# Will encode arrays using doc-literal style +sub encode_literal_array { + my($self, $array, $name, $type, $attr) = @_; + + if ($self->autotype) { + my $items = 'item'; + + # TODO: add support for multidimensional, partially transmitted and sparse arrays + my @items = map {$self->encode_object($_, $items)} @$array; + + + my $num = @items; + my($arraytype, %types) = '-'; + for (@items) { + $arraytype = $_->[1]->{'xsi:type'} || '-'; + $types{$arraytype}++ + } + $arraytype = sprintf "%s\[$num]", keys %types > 1 || $arraytype eq '-' + ? SOAP::Utils::qualify(xsd => $self->xmlschemaclass->anyTypeValue) + : $arraytype; + + $type = SOAP::Utils::qualify($self->encprefix => 'Array') + if !defined $type; + + return [$name || SOAP::Utils::qualify($self->encprefix => 'Array'), + { + SOAP::Utils::qualify($self->encprefix => 'arrayType') => $arraytype, + 'xsi:type' => $self->maptypetouri($type), %$attr + }, + [ @items ], + $self->gen_id($array) + ]; + } + else { + # + # literal arrays are different - { array => [ 5,6 ] } + # results in 56 + # This means that if there's a literal inside the array (not a + # reference), we have to encode it this way. If there's only + # nested tags, encode as + # 12 + # + + my $literal = undef; + my @items = map { + ref $_ + ? $self->encode_object($_) + : do { + $literal++; + $_ + } + + } @$array; + + if ($literal) { + return map { [ $name , $attr , $_, $self->gen_id($array) ] } @items; + } + else { + return [$name || SOAP::Utils::qualify($self->encprefix => 'Array'), + $attr, + [ @items ], + $self->gen_id($array) + ]; + } + } +} + +sub encode_hash { + my($self, $hash, $name, $type, $attr) = @_; + + if ($self->autotype && grep {!/$SOAP::Constants::ELMASK/o} keys %$hash) { + warn qq!Cannot encode @{[$name ? "'$name'" : 'unnamed']} element as 'hash'. Will be encoded as 'map' instead\n! if $^W; + return $self->as_map($hash, $name || gen_name, $type, $attr); + } + + $type = 'SOAPStruct' + if $self->autotype && !defined($type) && exists $self->maptype->{SOAPStruct}; + return [$name || gen_name, + $self->autotype ? {'xsi:type' => $self->maptypetouri($type), %$attr} : { %$attr }, + [map {$self->encode_object($hash->{$_}, $_)} keys %$hash], + $self->gen_id($hash) + ]; +} + +sub as_ordered_hash { + my ($self, $value, $name, $type, $attr) = @_; + die "Not an ARRAY reference for 'ordered_hash' type" unless UNIVERSAL::isa($value => 'ARRAY'); + return [ $name, $attr, + [map{$self->encode_object(@{$value}[2*$_+1,2*$_])} 0..$#$value/2 ], + $self->gen_id($value) + ]; +} + +sub as_map { + my ($self, $value, $name, $type, $attr) = @_; + die "Not a HASH reference for 'map' type" unless UNIVERSAL::isa($value => 'HASH'); + my $prefix = ($self->namespaces->{$SOAP::Constants::NS_APS} ||= 'apachens'); + my @items = map { + $self->encode_object( + SOAP::Data->type( + ordered_hash => [ + key => $_, + value => $value->{$_} + ] + ), + 'item', + '' + )} keys %$value; + return [ + $name, + {'xsi:type' => "$prefix:Map", %$attr}, + [@items], + $self->gen_id($value) + ]; +} + +sub as_xml { + my $self = shift; + my($value, $name, $type, $attr) = @_; + return [$name, {'_xml' => 1}, $value]; +} + +sub typecast { + my $self = shift; + my($value, $name, $type, $attr) = @_; + return if ref $value; # skip complex object, caller knows how to deal with it + return if $self->autotype && !defined $type; # we don't know, autotype knows + return [$name, + {(defined $type && $type gt '' ? ('xsi:type' => $self->maptypetouri($type, 'simple type')) : ()), %$attr}, + $value + ]; +} + +sub register_ns { + my $self = shift->new(); + my ($ns,$prefix) = @_; + $prefix = gen_ns if !$prefix; + $self->{'_namespaces'}->{$ns} = $prefix if $ns; +} + +sub find_prefix { + my ($self, $ns) = @_; + return (exists $self->{'_namespaces'}->{$ns}) + ? $self->{'_namespaces'}->{$ns} + : (); +} + +sub fixattrs { + my $self = shift; + my $data = shift; + my($name, $attr) = ($data->SOAP::Data::name, {%{$data->SOAP::Data::attr}}); + my($xmlns, $prefix) = ($data->uri, $data->prefix); + unless (defined($xmlns) || defined($prefix)) { + $self->register_ns($xmlns,$prefix) unless ($self->use_default_ns); + return ($name, $attr); + } + $name ||= gen_name; # local name + $prefix = gen_ns if !defined $prefix && $xmlns gt ''; + $prefix = '' + if defined $xmlns && $xmlns eq '' + || defined $prefix && $prefix eq ''; + + $attr->{join ':', xmlns => $prefix || ()} = $xmlns if defined $xmlns; + $name = join ':', $prefix, $name if $prefix; + + $self->register_ns($xmlns,$prefix) unless ($self->use_default_ns); + + return ($name, $attr); + +} + +sub toqname { + my $self = shift; + my $long = shift; + + return $long unless $long =~ /^\{(.*)\}(.+)$/; + return SOAP::Utils::qualify $self->namespaces->{$1} ||= gen_ns, $2; +} + +sub attrstoqname { + my $self = shift; + my $attrs = shift; + + return { + map { /^\{(.*)\}(.+)$/ + ? ($self->toqname($_) => $2 eq 'type' + || $2 eq 'arrayType' + ? $self->toqname($attrs->{$_}) + : $attrs->{$_}) + : ($_ => $attrs->{$_}) + } keys %$attrs + }; +} + +sub tag { + my ($self, $tag, $attrs, @values) = @_; + my $value = join '', @values; + my $level = $self->level; + my $indent = $self->readable ? ' ' x (($level-1)*2) : ''; + + # check for special attribute + return "$indent$value" if exists $attrs->{_xml} && delete $attrs->{_xml}; + + die "Element '$tag' can't be allowed in valid XML message. Died." + if $tag !~ /^(?![xX][mM][lL])$SOAP::Constants::NSMASK$/o; + + my $prolog = $self->readable ? "\n" : ""; + my $epilog = $self->readable ? "\n" : ""; + my $tagjoiner = " "; + if ($level == 1) { + my $namespaces = $self->namespaces; + foreach (keys %$namespaces) { + $attrs->{SOAP::Utils::qualify(xmlns => $namespaces->{$_})} = $_ + } + $prolog = qq!encoding]}"?>! + if defined $self->encoding; + $prolog .= "\n" if $self->readable; + $tagjoiner = " \n".(' ' x (($level+1) * 2)) if $self->readable; + } + my $tagattrs = join($tagjoiner, '', + map { sprintf '%s="%s"', $_, SOAP::Utils::encode_attribute($attrs->{$_}) } + grep { $_ && defined $attrs->{$_} && ($_ ne 'xsi:type' || $attrs->{$_} ne '') } + keys %$attrs); + + if ($value gt '') { + return sprintf("$prolog$indent<%s%s>%s%s$epilog",$tag,$tagattrs,$value,($value =~ /^\s*$epilog$indent",$tag,$tagattrs); + } +} + +sub xmlize { + my $self = shift; + my($name, $attrs, $values, $id) = @{+shift}; + $attrs ||= {}; + + local $self->{_level} = $self->{_level} + 1; + return $self->tag($name, $attrs) + unless defined $values; + return $self->tag($name, $attrs, $values) + unless UNIVERSAL::isa($values => 'ARRAY'); + return $self->tag($name, {%$attrs, href => '#'.$self->multiref_anchor($id)}) + if $self->is_href($id, delete($attrs->{_id})); + return $self->tag($name, + { + %$attrs, id => $self->multiref_anchor($id) + }, + map {$self->xmlize($_)} @$values + ); +} + +sub uriformethod { + my $self = shift; + + my $method_is_data = ref $_[0] && UNIVERSAL::isa($_[0] => 'SOAP::Data'); + + # drop prefix from method that could be string or SOAP::Data object + my($prefix, $method) = $method_is_data + ? ($_[0]->prefix, $_[0]->name) + : SOAP::Utils::splitqname($_[0]); + + my $attr = {reverse %{$self->namespaces}}; + # try to define namespace that could be stored as + # a) method is SOAP::Data + # ? attribute in method's element as xmlns= or xmlns:${prefix}= + # : uri + # b) attribute in Envelope element as xmlns= or xmlns:${prefix}= + # c) no prefix or prefix equal serializer->envprefix + # ? '', but see coment below + # : die with error message + my $uri = $method_is_data + ? ref $_[0]->attr && ($_[0]->attr->{$prefix ? "xmlns:$prefix" : 'xmlns'} || $_[0]->uri) + : $self->uri; + + defined $uri or $uri = $attr->{$prefix || ''}; + + defined $uri or $uri = !$prefix || $prefix eq $self->envprefix + # still in doubts what should namespace be in this case + # but will keep it like this for now and be compatible with our server + ? ( $method_is_data + && $^W + && warn("URI is not provided as an attribute for method ($method)\n"), + '' + ) + : die "Can't find namespace for method ($prefix:$method)\n"; + + return ($uri, $method); +} + +sub serialize { SOAP::Trace::trace('()'); + my $self = shift->new; + @_ == 1 or Carp::croak "serialize() method accepts one parameter"; + + $self->seen({}); # reinitialize multiref table + my($encoded) = $self->encode_object($_[0]); + + # now encode multirefs if any + # v -------------- subelements of Envelope + push(@{$encoded->[2]}, $self->encode_multirefs) if ref $encoded->[2]; + return $self->xmlize($encoded); +} + +sub envelope { + SOAP::Trace::trace('()'); + my $self = shift->new; + my $type = shift; + my(@parameters, @header); + for (@_) { + # Find all the SOAP Headers + if (defined($_) && ref($_) && UNIVERSAL::isa($_ => 'SOAP::Header')) { + push(@header, $_); + } + # Find all the SOAP Message Parts (attachments) + elsif (defined($_) && ref($_) && $self->context + && $self->context->packager->is_supported_part($_) + ) { + $self->context->packager->push_part($_); + } + # Find all the SOAP Body elements + else { + # proposed resolution for [ 1700326 ] encode_data called incorrectly in envelope + push(@parameters, $_); + # push (@parameters, SOAP::Utils::encode_data($_)); + } + } + my $header = @header ? SOAP::Data->set_value(@header) : undef; + my($body,$parameters); + if ($type eq 'method' || $type eq 'response') { + SOAP::Trace::method(@parameters); + + my $method = shift(@parameters); + # or die "Unspecified method for SOAP call\n"; + + $parameters = @parameters ? SOAP::Data->set_value(@parameters) : undef; + if (!defined($method)) {} + elsif (UNIVERSAL::isa($method => 'SOAP::Data')) { + $body = $method; + } + elsif ($self->use_default_ns) { + if ($self->{'_ns_uri'}) { + $body = SOAP::Data->name($method) + ->attr({'xmlns' => $self->{'_ns_uri'} } ); + } + else { + $body = SOAP::Data->name($method); + } + } + else { + # Commented out by Byrne on 1/4/2006 - to address default namespace problems + # $body = SOAP::Data->name($method)->uri($self->{'_ns_uri'}); + # $body = $body->prefix($self->{'_ns_prefix'}) if ($self->{'_ns_prefix'}); + + # Added by Byrne on 1/4/2006 - to avoid the unnecessary creation of a new + # namespace + # Begin New Code (replaces code commented out above) + $body = SOAP::Data->name($method); + my $pre = $self->find_prefix($self->{'_ns_uri'}); + $body = $body->prefix($pre) if ($self->{'_ns_prefix'}); + # End new code + } + + # This is breaking a unit test right now... + # proposed resolution for [ 1700326 ] encode_data called incorrectly in envelope + # $body->set_value(SOAP::Utils::encode_data($parameters ? \$parameters : ())) + # if $body; + # must call encode_data on nothing to enforce xsi:nil="true" to be set. + $body->set_value($parameters ? \$parameters : SOAP::Utils::encode_data()) if $body; + } + elsif ($type eq 'fault') { + SOAP::Trace::fault(@parameters); + # -> attr({'xmlns' => ''}) + # Parameter order fixed thanks to Tom Fischer + $body = SOAP::Data-> name(SOAP::Utils::qualify($self->envprefix => 'Fault')) + -> value(\SOAP::Data->set_value( + SOAP::Data->name(faultcode => SOAP::Utils::qualify($self->envprefix => $parameters[0]))->type(""), + SOAP::Data->name(faultstring => SOAP::Utils::encode_data($parameters[1]))->type(""), + defined($parameters[3]) + ? SOAP::Data->name(faultactor => $parameters[3])->type("") + : (), + defined($parameters[2]) + ? SOAP::Data->name(detail => do{ + my $detail = $parameters[2]; + ref $detail + ? \$detail + : SOAP::Utils::encode_data($detail) + }) + : (), + )); + } + elsif ($type eq 'freeform') { + SOAP::Trace::freeform(@parameters); + $body = SOAP::Data->set_value(@parameters); + } + elsif (!defined($type)) { + # This occurs when the Body is intended to be null. When no method has been + # passed in of any kind. + } + else { + die "Wrong type of envelope ($type) for SOAP call\n"; + } + + $self->seen({}); # reinitialize multiref table + # Build the envelope + # Right now it is possible for $body to be a SOAP::Data element that has not + # XML escaped any values. How do you remedy this? + my($encoded) = $self->encode_object( + SOAP::Data->name( + SOAP::Utils::qualify($self->envprefix => 'Envelope') => \SOAP::Data->value( + ($header + ? SOAP::Data->name( SOAP::Utils::qualify($self->envprefix => 'Header') => \$header) + : () + ), + ($body + ? SOAP::Data->name(SOAP::Utils::qualify($self->envprefix => 'Body') => \$body) + : SOAP::Data->name(SOAP::Utils::qualify($self->envprefix => 'Body')) ), + ) + )->attr($self->attr) + ); + + $self->signature($parameters->signature) if ref $parameters; + + # IMHO multirefs should be encoded after Body, but only some + # toolkits understand this encoding, so we'll keep them for now (04/15/2001) + # as the last element inside the Body + # v -------------- subelements of Envelope + # vv -------- last of them (Body) + # v --- subelements + push(@{$encoded->[2]->[-1]->[2]}, $self->encode_multirefs) if ref $encoded->[2]->[-1]->[2]; + + # Sometimes SOAP::Serializer is invoked statically when there is no context. + # So first check to see if a context exists. + # TODO - a context needs to be initialized by a constructor? + if ($self->context && $self->context->packager->parts) { + # TODO - this needs to be called! Calling it though wraps the payload twice! + # return $self->context->packager->package($self->xmlize($encoded)); + } + + return $self->xmlize($encoded); +} + +# ====================================================================== + +package SOAP::Parser; + +sub DESTROY { SOAP::Trace::objects('()') } + +sub xmlparser { + my $self = shift; + return eval { + $SOAP::Constants::DO_NOT_USE_XML_PARSER + ? undef + : do { + require XML::Parser; + XML::Parser->new() } + } + || eval { require XML::Parser::Lite; XML::Parser::Lite->new } + || die "XML::Parser is not @{[$SOAP::Constants::DO_NOT_USE_XML_PARSER ? 'used' : 'available']} and ", $@; +} + +sub parser { + my $self = shift->new; + @_ + ? do { + $self->{'_parser'} = shift; + return $self; + } + : return ($self->{'_parser'} ||= $self->xmlparser); +} + +sub new { + my $self = shift; + return $self if ref $self; + my $class = $self; + SOAP::Trace::objects('()'); + return bless {_parser => shift}, $class; +} + +sub decode { SOAP::Trace::trace('()'); + my $self = shift; + + $self->parser->setHandlers( + Final => sub { shift; $self->final(@_) }, + Start => sub { shift; $self->start(@_) }, + End => sub { shift; $self->end(@_) }, + Char => sub { shift; $self->char(@_) }, + ExternEnt => sub { shift; die "External entity (pointing to '$_[1]') is not allowed" }, + ); + # my $parsed = $self->parser->parse($_[0]); + # return $parsed; + # + my $ret = undef; + eval { + $ret = $self->parser->parse($_[0]); + }; + if ($@) { + $self->final; # Clean up in the event of an error + die $@; # Pass back the error + } + return $ret; +} + +sub final { + my $self = shift; + + # clean handlers, otherwise SOAP::Parser won't be deleted: + # it refers to XML::Parser which refers to subs from SOAP::Parser + # Thanks to Ryan Adams + # and Craig Johnston + # checked by number of tests in t/02-payload.t + + undef $self->{_values}; + $self->parser->setHandlers( + Final => undef, + Start => undef, + End => undef, + Char => undef, + ExternEnt => undef, + ); + $self->{_done}; +} + +sub start { push @{shift->{_values}}, [shift, {@_}] } + +# string concatenation changed to arrays which should improve performance +# for strings with many entity-encoded elements. +# Thanks to Mathieu Longtin +sub char { push @{shift->{_values}->[-1]->[3]}, shift } + +sub end { + my $self = shift; + my $done = pop @{$self->{_values}}; + $done->[2] = defined $done->[3] + ? join('',@{$done->[3]}) + : '' unless ref $done->[2]; + undef $done->[3]; + @{$self->{_values}} + ? (push @{$self->{_values}->[-1]->[2]}, $done) + : ($self->{_done} = $done); +} + +# ====================================================================== + +package SOAP::SOM; + +use Carp (); +use SOAP::Lite::Utils; + +sub BEGIN { + no strict 'refs'; + my %path = ( + root => '/', + envelope => '/Envelope', + body => '/Envelope/Body', + header => '/Envelope/Header', + headers => '/Envelope/Header/[>0]', + fault => '/Envelope/Body/Fault', + faultcode => '/Envelope/Body/Fault/faultcode', + faultstring => '/Envelope/Body/Fault/faultstring', + faultactor => '/Envelope/Body/Fault/faultactor', + faultdetail => '/Envelope/Body/Fault/detail', + ); + for my $method (keys %path) { + *$method = sub { + my $self = shift; + ref $self or return $path{$method}; + Carp::croak "Method '$method' is readonly and doesn't accept any parameters" if @_; + return $self->valueof($path{$method}); + }; + } + my %results = ( + method => '/Envelope/Body/[1]', + result => '/Envelope/Body/[1]/[1]', + freeform => '/Envelope/Body/[>0]', + paramsin => '/Envelope/Body/[1]/[>0]', + paramsall => '/Envelope/Body/[1]/[>0]', + paramsout => '/Envelope/Body/[1]/[>1]' + ); + for my $method (keys %results) { + *$method = sub { + my $self = shift; + ref $self or return $results{$method}; + Carp::croak "Method '$method' is readonly and doesn't accept any parameters" if @_; + defined $self->fault ? return : return $self->valueof($results{$method}); + }; + } + + for my $method (qw(o_child o_value o_lname o_lattr o_qname)) { # import from SOAP::Utils + *$method = \&{'SOAP::Utils::'.$method}; + } + + __PACKAGE__->__mk_accessors('context'); + +} + +# use object in boolean context return true/false on last match +# Ex.: $som->match('//Fault') ? 'SOAP call failed' : 'success'; +use overload fallback => 1, 'bool' => sub { @{shift->{_current}} > 0 }; + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + my $class = ref($self) || $self; + my $content = shift; + SOAP::Trace::objects('()'); + return bless { _content => $content, _current => [$content] } => $class; +} + +sub parts { + my $self = shift; + if (@_) { + $self->context->packager->parts(@_); + return $self; + } + else { + return $self->context->packager->parts; + } +} + +sub is_multipart { + my $self = shift; + return defined($self->parts); +} + +sub current { + my $self = shift; + $self->{_current} = [@_], return $self if @_; + return wantarray ? @{$self->{_current}} : $self->{_current}->[0]; +} + +sub valueof { + my $self = shift; + local $self->{_current} = $self->{_current}; + $self->match(shift) if @_; + return wantarray + ? map {o_value($_)} @{$self->{_current}} + : @{$self->{_current}} ? o_value($self->{_current}->[0]) : undef; +} + +sub headerof { # SOAP::Header is the same as SOAP::Data, so just rebless it + wantarray + ? map { bless $_ => 'SOAP::Header' } shift->dataof(@_) + : do { # header returned by ->dataof can be undef in scalar context + my $header = shift->dataof(@_); + ref $header ? bless($header => 'SOAP::Header') : undef; + }; +} + +sub dataof { + my $self = shift; + local $self->{_current} = $self->{_current}; + $self->match(shift) if @_; + return wantarray + ? map {$self->_as_data($_)} @{$self->{_current}} + : @{$self->{_current}} + ? $self->_as_data($self->{_current}->[0]) + : undef; +} + +sub namespaceuriof { + my $self = shift; + local $self->{_current} = $self->{_current}; + $self->match(shift) if @_; + return wantarray + ? map {(SOAP::Utils::splitlongname(o_lname($_)))[0]} @{$self->{_current}} + : @{$self->{_current}} ? (SOAP::Utils::splitlongname(o_lname($self->{_current}->[0])))[0] : undef; +} + +#sub _as_data { +# my $self = shift; +# my $pointer = shift; +# +# SOAP::Data +# -> new(prefix => '', name => o_qname($pointer), name => o_lname($pointer), attr => o_lattr($pointer)) +# -> set_value(o_value($pointer)); +#} + +sub _as_data { + my $self = shift; + my $node = shift; + + my $data = SOAP::Data->new( prefix => '', + # name => o_qname has side effect: sets namespace ! + name => o_qname($node), + name => o_lname($node), + attr => o_lattr($node) ); + + if ( defined o_child($node) ) { + my @children; + foreach my $child ( @{ o_child($node) } ) { + push( @children, $self->_as_data($child) ); + } + $data->set_value( \SOAP::Data->value(@children) ); + } + else { + $data->set_value( o_value($node) ); + } + + return $data; +} + + +sub match { + my $self = shift; + my $path = shift; + $self->{_current} = [ + $path =~ s!^/!! || !@{$self->{_current}} + ? $self->_traverse($self->{_content}, 1 => split '/' => $path) + : map {$self->_traverse_tree(o_child($_), split '/' => $path)} @{$self->{_current}} + ]; + return $self; +} + +sub _traverse { + my $self = shift; + my ($pointer, $itself, $path, @path) = @_; + + die "Incorrect parameter" unless $itself =~ /^\d*$/; + + if ($path && substr($path, 0, 1) eq '{') { + $path = join '/', $path, shift @path while @path && $path !~ /}/; + } + + my($op, $num) = $path =~ /^\[(<=|<|>=|>|=|!=?)?(\d+)\]$/ if defined $path; + + return $pointer unless defined $path; + + $op = '==' unless $op; $op .= '=' if $op eq '=' || $op eq '!'; + my $numok = defined $num && eval "$itself $op $num"; + my $nameok = (o_lname($pointer) || '') =~ /(?:^|\})$path$/ if defined $path; # name can be with namespace + + my $anynode = $path eq ''; + unless ($anynode) { + if (@path) { + return if defined $num && !$numok || !defined $num && !$nameok; + } + else { + return $pointer if defined $num && $numok || !defined $num && $nameok; + return; + } + } + + my @walk; + push @walk, $self->_traverse_tree([$pointer], @path) if $anynode; + push @walk, $self->_traverse_tree(o_child($pointer), $anynode ? ($path, @path) : @path); + return @walk; +} + +sub _traverse_tree { + my $self = shift; + my($pointer, @path) = @_; + + # can be list of children or value itself. Traverse only children + return unless ref $pointer eq 'ARRAY'; + + my $itself = 1; + + grep {defined} + map {$self->_traverse($_, $itself++, @path)} + grep {!ref o_lattr($_) || + !exists o_lattr($_)->{"{$SOAP::Constants::NS_ENC}root"} || + o_lattr($_)->{"{$SOAP::Constants::NS_ENC}root"} ne '0'} + @$pointer; +} + +# ====================================================================== + +package SOAP::Deserializer; + +use vars qw(@ISA); +use SOAP::Lite::Utils; +use Class::Inspector; + +@ISA = qw(SOAP::Cloneable); + +sub DESTROY { SOAP::Trace::objects('()') } + +sub BEGIN { + __PACKAGE__->__mk_accessors( qw(ids hrefs parts parser + base xmlschemas xmlschema context) ); +} + +sub new { + my $self = shift; + return $self if ref $self; + my $class = $self; + SOAP::Trace::objects('()'); + return bless { + '_ids' => {}, + '_hrefs' => {}, + '_parser' => SOAP::Parser->new, + '_xmlschemas' => { + $SOAP::Constants::NS_APS => 'SOAP::XMLSchemaApacheSOAP::Deserializer', +# map { +# $_ => $SOAP::Constants::XML_SCHEMAS{$_} . '::Deserializer' +# } keys %SOAP::Constants::XML_SCHEMAS + map { + $_ => 'SOAP::Lite::Deserializer::' . $SOAP::Constants::XML_SCHEMA_OF{$_} + } keys %SOAP::Constants::XML_SCHEMA_OF + + }, + }, $class; +} + +sub is_xml { + # Added check for envelope delivery. Fairly standard with MMDF and sendmail + # Thanks to Chris Davies + $_[1] =~ /^\s*new($location); + # make absolute location if relative + $location = $uri->abs($self->base || 'thismessage:/')->as_string unless $uri->scheme; + } + return $location; +} + +# Returns the envelope and populates SOAP::Packager with parts +sub decode_parts { + my $self = shift; + my $env = $self->context->packager->unpackage($_[0],$self->context); + my $body = $self->parser->decode($env); + # TODO - This shouldn't be here! This is packager specific! + # However this does need to pull out all the cid's + # to populate ids hash with. + foreach (@{$self->context->packager->parts}) { + my $data = $_->bodyhandle->as_string; + my $type = $_->head->mime_attr('Content-Type'); + my $location = $_->head->mime_attr('Content-Location'); + my $id = $_->head->mime_attr('Content-Id'); + $location = $self->baselocation($location); + my $part = lc($type) eq 'text/xml' && !$SOAP::Constants::DO_NOT_PROCESS_XML_IN_MIME + ? $self->parser->decode($data) + : ['mimepart', {}, $data]; + # This below looks like unnecessary bloat!!! + # I should probably dereference the mimepart, provide a callback to get the string data + $id =~ s/^<([^>]*)>$/$1/; # string any leading and trailing brackets + $self->ids->{$id} = $part if $id; + $self->ids->{$location} = $part if $location; + } + return $body; +} + +# decode returns a parsed body in the form of an ARRAY +# each element of the ARRAY is a HASH, ARRAY or SCALAR +sub decode { + my $self = shift->new; # this actually is important + return $self->is_xml($_[0]) + ? $self->parser->decode($_[0]) + : $self->decode_parts($_[0]); +} + +# deserialize returns a SOAP::SOM object and parses straight +# text as input +sub deserialize { + SOAP::Trace::trace('()'); + my $self = shift->new; + + # initialize + $self->hrefs({}); + $self->ids({}); + + # If the document is XML, then ids will be empty + # If the document is MIME, then ids will hold a list of cids + my $parsed = $self->decode($_[0]); + + # Having this code here makes multirefs in the Body work, but multirefs + # that reference XML fragments in a MIME part do not work. + if (keys %{$self->ids()}) { + $self->traverse_ids($parsed); + } + else { + # delay - set ids to be traversed later in decode_object, they only get + # traversed if an href is found that is referencing an id. + $self->ids($parsed); + } + $self->decode_object($parsed); + my $som = SOAP::SOM->new($parsed); + $som->context($self->context); # TODO - try removing this and see if it works! + return $som; +} + +sub traverse_ids { + my $self = shift; + my $ref = shift; + my($undef, $attrs, $children) = @$ref; + # ^^^^^^ to fix nasty error on Mac platform (Carl K. Cunningham) + $self->ids->{$attrs->{'id'}} = $ref if exists $attrs->{'id'}; + return unless ref $children; + for (@$children) { + $self->traverse_ids($_) + }; +} + +use constant _ATTRS => 6; +use constant _NAME => 5; + +sub decode_object { + my $self = shift; + my $ref = shift; + my($name, $attrs, $children, $value) = @$ref; + + $ref->[ _ATTRS ] = $attrs = {%$attrs}; # make a copy for long attributes + + use vars qw(%uris); + local %uris = (%uris, map { + do { (my $ns = $_) =~ s/^xmlns:?//; $ns } => delete $attrs->{$_} + } grep {/^xmlns(:|$)/} keys %$attrs); + + foreach (keys %$attrs) { + next unless m/^($SOAP::Constants::NSMASK?):($SOAP::Constants::NSMASK)$/; + + $1 =~ /^[xX][mM][lL]/ || + $uris{$1} && + do { + $attrs->{SOAP::Utils::longname($uris{$1}, $2)} = do { + my $value = $attrs->{$_}; + $2 ne 'type' && $2 ne 'arrayType' + ? $value + : SOAP::Utils::longname($value =~ m/^($SOAP::Constants::NSMASK?):(${SOAP::Constants::NSMASK}(?:\[[\d,]*\])*)/ + ? ($uris{$1} || die("Unresolved prefix '$1' for attribute value '$value'\n"), $2) + : ($uris{''} || die("Unspecified namespace for type '$value'\n"), $value) + ); + }; + 1; + } + || die "Unresolved prefix '$1' for attribute '$_'\n"; + } + + # and now check the element + my $ns = ($name =~ s/^($SOAP::Constants::NSMASK?):// ? $1 : ''); + $ref->[ _NAME ] = SOAP::Utils::longname( + $ns + ? ($uris{$ns} || die "Unresolved prefix '$ns' for element '$name'\n") + : (defined $uris{''} ? $uris{''} : undef), + $name + ); + + ($children, $value) = (undef, $children) unless ref $children; + + return $name => ($ref->[4] = $self->decode_value( + [$ref->[ _NAME ], $attrs, $children, $value] + )); +} + +sub decode_value { + my $self = shift; + my $ref = shift; + my($name, $attrs, $children, $value) = @$ref; + + # check SOAP version if applicable + use vars '$level'; local $level = $level || 0; + if (++$level == 1) { + my($namespace, $envelope) = SOAP::Utils::splitlongname($name); + SOAP::Lite->soapversion($namespace) if $envelope eq 'Envelope' && $namespace; + } + + # check encodingStyle + # future versions may bind deserializer to encodingStyle + my $encodingStyle = $attrs->{"{$SOAP::Constants::NS_ENV}encodingStyle"} || ""; + my (%union,%isect); + # TODO - SOAP 1.2 and 1.1 have different rules about valid encodingStyle values + # For example, in 1.1 - any http://schemas.xmlsoap.org/soap/encoding/* + # value is valid + # Find intersection of declared and supported encoding styles + foreach my $e (@SOAP::Constants::SUPPORTED_ENCODING_STYLES, split(/ +/,$encodingStyle)) { + $union{$e}++ && $isect{$e}++; + } + die "Unrecognized/unsupported value of encodingStyle attribute '$encodingStyle'" + if defined($encodingStyle) && length($encodingStyle) > 0 && !%isect && + !(SOAP::Lite->soapversion == 1.1 && $encodingStyle =~ /(?:^|\b)$SOAP::Constants::NS_ENC/); + + # removed to provide literal support in 0.65 + #$encodingStyle !~ /(?:^|\b)$SOAP::Constants::NS_ENC/; + # # ^^^^^^^^ \b causing problems (!?) on some systems + # # as reported by David Dyck + # # so use (?:^|\b) instead + + use vars '$arraytype'; # type of Array element specified on Array itself + # either specified with xsi:type, or or array element + my ($type) = grep { defined } + map($attrs->{$_}, sort grep {/^\{$SOAP::Constants::NS_XSI_ALL\}type$/o} keys %$attrs), + $name =~ /^\{$SOAP::Constants::NS_ENC\}/ ? $name : $arraytype; + local $arraytype; # it's used only for one level, we don't need it anymore + + # $name is not used here since type should be encoded as type, not as name + my ($schema, $class) = SOAP::Utils::splitlongname($type) if $type; + my $schemaclass = defined($schema) && $self->xmlschemas->{$schema} + || $self; + + { + no strict qw(refs); + if (! Class::Inspector->loaded($schemaclass) ) { + eval "require $schemaclass" or die $@ if not ref $schemaclass; + } + } + + # store schema that is used in parsed message + $self->xmlschema($schema) if $schema && $schema =~ /XMLSchema/; + + # don't use class/type if anyType/ur-type is specified on wire + undef $class + if $schemaclass->can('anyTypeValue') + && $schemaclass->anyTypeValue eq $class; + + my $method = 'as_' . ($class || '-'); # dummy type if not defined + $class =~ s/__|\./::/g if $class; + + my $id = $attrs->{id}; + if (defined $id && exists $self->hrefs->{$id}) { + return $self->hrefs->{$id}; + } + elsif (exists $attrs->{href}) { + (my $id = delete $attrs->{href}) =~ s/^(#|cid:|uuid:)?//; + # convert to absolute if not internal '#' or 'cid:' + $id = $self->baselocation($id) unless $1; + return $self->hrefs->{$id} if exists $self->hrefs->{$id}; + # First time optimization. we don't traverse IDs unless asked for it. + # This is where traversing id's is delayed from before + # - the first time through - ids should contain a copy of the parsed XML + # structure! seems silly to make so many copies + my $ids = $self->ids; + if (ref($ids) ne 'HASH') { + $self->ids({}); # reset list of ids first time through + $self->traverse_ids($ids); + } + if (exists($self->ids->{$id})) { + my $obj = ($self->decode_object(delete($self->ids->{$id})))[1]; + return $self->hrefs->{$id} = $obj; + } + else { + die "Unresolved (wrong?) href ($id) in element '$name'\n"; + } + } + + return undef if grep { + /^$SOAP::Constants::NS_XSI_NILS$/ && do { + my $class = $self->xmlschemas->{ $1 || $2 }; + eval "require $class" or die @$;; + $class->as_undef($attrs->{$_}) + } + } keys %$attrs; + + # try to handle with typecasting + my $res = $self->typecast($value, $name, $attrs, $children, $type); + return $res if defined $res; + + # ok, continue with others + if (exists $attrs->{"{$SOAP::Constants::NS_ENC}arrayType"}) { + my $res = []; + $self->hrefs->{$id} = $res if defined $id; + + # check for arrayType which could be [1], [,2][5] or [] + # [,][1] will NOT be allowed right now (multidimensional sparse array) + my($type, $multisize) = $attrs->{"{$SOAP::Constants::NS_ENC}arrayType"} + =~ /^(.+)\[(\d*(?:,\d+)*)\](?:\[(?:\d+(?:,\d+)*)\])*$/ + or die qq!Unrecognized/unsupported format of arrayType attribute '@{[$attrs->{"{$SOAP::Constants::NS_ENC}arrayType"}]}'\n!; + + my @dimensions = map { $_ || undef } split /,/, $multisize; + my $size = 1; + foreach (@dimensions) { $size *= $_ || 0 } + + # TODO ähm, shouldn't this local be my? + local $arraytype = $type; + + # multidimensional + if ($multisize =~ /,/) { + @$res = splitarray( + [@dimensions], + [map { scalar(($self->decode_object($_))[1]) } @{$children || []}] + ); + } + # normal + else { + @$res = map { scalar(($self->decode_object($_))[1]) } @{$children || []}; + } + + # sparse (position) + if (ref $children && exists SOAP::Utils::o_lattr($children->[0])->{"{$SOAP::Constants::NS_ENC}position"}) { + my @new; + for (my $pos = 0; $pos < @$children; $pos++) { + # TBD implement position in multidimensional array + my($position) = SOAP::Utils::o_lattr($children->[$pos])->{"{$SOAP::Constants::NS_ENC}position"} =~ /^\[(\d+)\]$/ + or die "Position must be specified for all elements of sparse array\n"; + $new[$position] = $res->[$pos]; + } + @$res = @new; + } + + # partially transmitted (offset) + # TBD implement offset in multidimensional array + my($offset) = $attrs->{"{$SOAP::Constants::NS_ENC}offset"} =~ /^\[(\d+)\]$/ + if exists $attrs->{"{$SOAP::Constants::NS_ENC}offset"}; + unshift(@$res, (undef) x $offset) if $offset; + + die "Too many elements in array. @{[scalar@$res]} instead of claimed $multisize ($size)\n" + if $multisize && $size < @$res; + + # extend the array if number of elements is specified + $#$res = $dimensions[0]-1 if defined $dimensions[0] && @$res < $dimensions[0]; + + return defined $class && $class ne 'Array' ? bless($res => $class) : $res; + + } + elsif ($name =~ /^\{$SOAP::Constants::NS_ENC\}Struct$/ + || !$schemaclass->can($method) + && (ref $children || defined $class && $value =~ /^\s*$/)) { + my $res = {}; + $self->hrefs->{$id} = $res if defined $id; + + # Patch code introduced in 0.65 - deserializes array properly + # Decode each element of the struct. + my %child_count_of = (); + foreach my $child (@{$children || []}) { + my ($child_name, $child_value) = $self->decode_object($child); + # Store the decoded element in the struct. If the element name is + # repeated, replace the previous scalar value with a new array + # containing both values. + if (not $child_count_of{$child_name}) { + # first time to see this value: use scalar + $res->{$child_name} = $child_value; + } + elsif ($child_count_of{$child_name} == 1) { + # second time to see this value: convert scalar to array + $res->{$child_name} = [ $res->{$child_name}, $child_value ]; + } + else { + # already have an array: append to it + push @{$res->{$child_name}}, $child_value; + } + $child_count_of{$child_name}++; + } + # End patch code + + return defined $class && $class ne 'SOAPStruct' ? bless($res => $class) : $res; + } + else { + my $res; + if (my $method_ref = $schemaclass->can($method)) { + $res = $method_ref->($self, $value, $name, $attrs, $children, $type); + } + else { + $res = $self->typecast($value, $name, $attrs, $children, $type); + $res = $class ? die "Unrecognized type '$type'\n" : $value + unless defined $res; + } + $self->hrefs->{$id} = $res if defined $id; + return $res; + } +} + +sub splitarray { + my @sizes = @{+shift}; + my $size = shift @sizes; + my $array = shift; + + return splice(@$array, 0, $size) unless @sizes; + my @array = (); + push @array, [ + splitarray([@sizes], $array) + ] while @$array && (!defined $size || $size--); + return @array; +} + +sub typecast { } # typecast is called for both objects AND scalar types + # check ref of the second parameter (first is the object) + # return undef if you don't want to handle it + +# ====================================================================== + +package SOAP::Client; + + +use SOAP::Lite::Utils; + +$VERSION = $SOAP::Lite::VERSION; +sub BEGIN { + __PACKAGE__->__mk_accessors(qw(endpoint code message + is_success status options)); +} + +# ====================================================================== + +package SOAP::Server::Object; + +sub gen_id; *gen_id = \&SOAP::Serializer::gen_id; + +my %alive; +my %objects; + +sub objects_by_reference { + shift; + while (@_) { + @alive{shift()} = ref $_[0] + ? shift + : sub { + $_[1]-$_[$_[5] ? 5 : 4] > $SOAP::Constants::OBJS_BY_REF_KEEPALIVE + } + } + keys %alive; +} + +sub reference { + my $self = shift; + my $stamp = time; + my $object = shift; + my $id = $stamp . $self->gen_id($object); + + # this is code for garbage collection + my $time = time; + my $type = ref $object; + my @objects = grep { $objects{$_}->[1] eq $type } keys %objects; + for (grep { $alive{$type}->(scalar @objects, $time, @{$objects{$_}}) } @objects) { + delete $objects{$_}; + } + + $objects{$id} = [$object, $type, $stamp]; + bless { id => $id } => ref $object; +} + +sub references { + my $self = shift; + return @_ unless %alive; # small optimization + return map { + ref($_) && exists $alive{ref $_} + ? $self->reference($_) + : $_ + } @_; +} + +sub object { + my $self = shift; + my $class = ref($self) || $self; + my $object = shift; + return $object unless ref($object) && $alive{ref $object} && exists $object->{id}; + + my $reference = $objects{$object->{id}}; + die "Object with specified id couldn't be found\n" unless ref $reference->[0]; + + $reference->[3] = time; # last access time + return $reference->[0]; # reference to actual object +} + +sub objects { + my $self = shift; + return @_ unless %alive; # small optimization + return map { + ref($_) && exists $alive{ref $_} && exists $_->{id} + ? $self->object($_) + : $_ + } @_; +} + +# ====================================================================== + +package SOAP::Server::Parameters; + +sub byNameOrOrder { + unless (UNIVERSAL::isa($_[-1] => 'SOAP::SOM')) { + warn "Last parameter is expected to be envelope\n" if $^W; + pop; + return @_; + } + my $params = pop->method; + my @mandatory = ref $_[0] eq 'ARRAY' + ? @{shift()} + : die "list of parameters expected as the first parameter for byName"; + my $byname = 0; + my @res = map { $byname += exists $params->{$_}; $params->{$_} } @mandatory; + return $byname + ? @res + : @_; +} + +sub byName { + unless (UNIVERSAL::isa($_[-1] => 'SOAP::SOM')) { + warn "Last parameter is expected to be envelope\n" if $^W; + pop; + return @_; + } + return @{pop->method}{ref $_[0] eq 'ARRAY' ? @{shift()} : die "list of parameters expected as the first parameter for byName"}; +} + +# ====================================================================== + +package SOAP::Server; + +use Carp (); +use Scalar::Util qw(weaken); +sub DESTROY { SOAP::Trace::objects('()') } + +sub initialize { + return ( + packager => SOAP::Packager::MIME->new, + transport => SOAP::Transport->new, + serializer => SOAP::Serializer->new, + deserializer => SOAP::Deserializer->new, + on_action => sub { ; }, + on_dispatch => sub { + return; + }, + ); +} + +sub new { + my $self = shift; + return $self if ref $self; + + unless (ref $self) { + my $class = $self; + my(@params, @methods); + + while (@_) { + my($method, $params) = splice(@_,0,2); + $class->can($method) + ? push(@methods, $method, $params) + : $^W && Carp::carp "Unrecognized parameter '$method' in new()"; + } + + $self = bless { + _dispatch_to => [], + _dispatch_with => {}, + _dispatched => [], + _action => '', + _options => {}, + } => $class; + unshift(@methods, $self->initialize); + no strict qw(refs); + while (@methods) { + my($method, $params) = splice(@methods,0,2); + $self->$method(ref $params eq 'ARRAY' ? @$params : $params) + } + SOAP::Trace::objects('()'); + } + + Carp::carp "Odd (wrong?) number of parameters in new()" + if $^W && (@_ & 1); + + no strict qw(refs); + while (@_) { + my($method, $params) = splice(@_,0,2); + $self->can($method) + ? $self->$method(ref $params eq 'ARRAY' ? @$params : $params) + : $^W && Carp::carp "Unrecognized parameter '$method' in new()" + } + + return $self; +} + +sub init_context { + my $self = shift; + $self->{'_deserializer'}->{'_context'} = $self; + # weaken circular reference to avoid a memory hole + weaken($self->{'_deserializer'}->{'_context'}); + + $self->{'_serializer'}->{'_context'} = $self; + # weaken circular reference to avoid a memory hole + weaken($self->{'_serializer'}->{'_context'}); +} + +sub BEGIN { + no strict 'refs'; + for my $method (qw(serializer deserializer transport)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new(); + if (@_) { + my $context = $self->{$field}->{'_context'}; # save the old context + $self->{$field} = shift; + $self->{$field}->{'_context'} = $context; # restore the old context + return $self; + } + else { + return $self->{$field}; + } + } + } + + for my $method (qw(action myuri options dispatch_with packager)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new(); + (@_) + ? do { + $self->{$field} = shift; + return $self; + } + : return $self->{$field}; + } + } + for my $method (qw(on_action on_dispatch)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + # my $self = shift; + return $self->{$field} unless @_; + local $@; + # commented out because that 'eval' was unsecure + # > ref $_[0] eq 'CODE' ? shift : eval shift; + # Am I paranoid enough? + $self->{$field} = shift; + Carp::croak $@ if $@; + Carp::croak "$method() expects subroutine (CODE) or string that evaluates into subroutine (CODE)" + unless ref $self->{$field} eq 'CODE'; + return $self; + } + } + + # __PACKAGE__->__mk_accessors( qw(dispatch_to) ); + for my $method (qw(dispatch_to)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + # my $self = shift; + (@_) + ? do { + $self->{$field} = [@_]; + return $self; + } + : return @{ $self->{$field} }; + } + } +} + +sub objects_by_reference { + my $self = shift; + $self = $self->new() if not ref $self; + @_ + ? (SOAP::Server::Object->objects_by_reference(@_), return $self) + : SOAP::Server::Object->objects_by_reference; +} + +sub dispatched { + my $self = shift; + $self = $self->new() if not ref $self; + @_ + ? (push(@{$self->{_dispatched}}, @_), return $self) + : return @{$self->{_dispatched}}; +} + +sub find_target { + my $self = shift; + my $request = shift; + + # try to find URI/method from on_dispatch call first + my($method_uri, $method_name) = $self->on_dispatch->($request); + + # if nothing there, then get it from envelope itself + $request->match((ref $request)->method); + ($method_uri, $method_name) = ($request->namespaceuriof || '', $request->dataof->name) + unless $method_name; + + $self->on_action->(my $action = $self->action, $method_uri, $method_name); + + # check to avoid security vulnerability: Protected->Unprotected::method(@parameters) + # see for more details: http://www.phrack.org/phrack/58/p58-0x09 + die "Denied access to method ($method_name)\n" unless $method_name =~ /^\w+$/; + + my ($class, $static); + # try to bind directly + if (defined($class = $self->dispatch_with->{$method_uri} + || $self->dispatch_with->{$action || ''} + || ($action =~ /^"(.+)"$/ + ? $self->dispatch_with->{$1} + : undef))) { + # return object, nothing else to do here + return ($class, $method_uri, $method_name) if ref $class; + $static = 1; + } + else { + die "URI path shall map to class" unless defined ($class = URI->new($method_uri)->path); + + for ($class) { s!^/|/$!!g; s!/!::!g; s/^$/main/; } + die "Failed to access class ($class)" unless $class =~ /^(\w[\w:]*)$/; + + my $fullname = "$class\::$method_name"; + foreach ($self->dispatch_to) { + return ($_, $method_uri, $method_name) if ref eq $class; # $OBJECT + next if ref; # skip other objects + # will ignore errors, because it may complain on + # d:\foo\bar, which is PATH and not regexp + eval { + $static ||= $class =~ /^$_$/ # MODULE + || $fullname =~ /^$_$/ # MODULE::method + || $method_name =~ /^$_$/ && ($class eq 'main'); # method ('main' assumed) + }; + } + } + + no strict 'refs'; + +# TODO - sort this mess out: +# The task is to test whether the class in question has already been loaded. +# +# SOAP::Lite 0.60: +# unless (defined %{"${class}::"}) { +# Patch to SOAP::Lite 0.60: +# The following patch does not work for packages defined within a BEGIN block +# unless (exists($INC{join '/', split /::/, $class.'.pm'})) { +# Combination of 0.60 and patch did not work reliably, either. +# +# Now we do the following: Check whether the class is main (always loaded) +# or the class implements the method in question +# or the package exists as file in %INC. +# +# This is still sort of a hack - but I don't know anything better +# If you have some idea, please help me out... +# + unless (($class eq 'main') || $class->can($method_name) + || exists($INC{join '/', split /::/, $class . '.pm'})) { + + # allow all for static and only specified path for dynamic bindings + local @INC = (($static ? @INC : ()), grep {!ref && m![/\\.]!} $self->dispatch_to()); + eval 'local $^W; ' . "require $class"; + die "Failed to access class ($class): $@" if $@; + $self->dispatched($class) unless $static; + } + + die "Denied access to method ($method_name) in class ($class)" + unless $static || grep {/^$class$/} $self->dispatched; + + return ($class, $method_uri, $method_name); +} + +sub handle { + SOAP::Trace::trace('()'); + my $self = shift; + $self = $self->new if !ref $self; # inits the server when called in a static context + $self->init_context(); + # we want to restore it when we are done + local $SOAP::Constants::DEFAULT_XML_SCHEMA + = $SOAP::Constants::DEFAULT_XML_SCHEMA; + + # SOAP version WILL NOT be restored when we are done. + # is it problem? + + my $result = eval { + local $SIG{__DIE__}; + # why is this here: + $self->serializer->soapversion(1.1); + my $request = eval { $self->deserializer->deserialize($_[0]) }; + + die SOAP::Fault + ->faultcode($SOAP::Constants::FAULT_VERSION_MISMATCH) + ->faultstring($@) + if $@ && $@ =~ /^$SOAP::Constants::WRONG_VERSION/; + + die "Application failed during request deserialization: $@" if $@; + my $som = ref $request; + die "Can't find root element in the message" + unless $request->match($som->envelope); + $self->serializer->soapversion(SOAP::Lite->soapversion); + $self->serializer->xmlschema($SOAP::Constants::DEFAULT_XML_SCHEMA + = $self->deserializer->xmlschema) + if $self->deserializer->xmlschema; + + die SOAP::Fault + ->faultcode($SOAP::Constants::FAULT_MUST_UNDERSTAND) + ->faultstring("Unrecognized header has mustUnderstand attribute set to 'true'") + if !$SOAP::Constants::DO_NOT_CHECK_MUSTUNDERSTAND && + grep { + $_->mustUnderstand + && (!$_->actor || $_->actor eq $SOAP::Constants::NEXT_ACTOR) + } $request->dataof($som->headers); + + die "Can't find method element in the message" + unless $request->match($som->method); + # TODO - SOAP::Dispatcher plugs in here + # my $handler = $self->dispatcher->find_handler($request); + my($class, $method_uri, $method_name) = $self->find_target($request); + my @results = eval { + local $^W; + my @parameters = $request->paramsin; + + # SOAP::Trace::dispatch($fullname); + SOAP::Trace::parameters(@parameters); + + push @parameters, $request + if UNIVERSAL::isa($class => 'SOAP::Server::Parameters'); + + no strict qw(refs); + SOAP::Server::Object->references( + defined $parameters[0] + && ref $parameters[0] + && UNIVERSAL::isa($parameters[0] => $class) + ? do { + my $object = shift @parameters; + SOAP::Server::Object->object(ref $class + ? $class + : $object + )->$method_name(SOAP::Server::Object->objects(@parameters)), + + # send object back as a header + # preserve name, specify URI + SOAP::Header + ->uri($SOAP::Constants::NS_SL_HEADER => $object) + ->name($request->dataof($som->method.'/[1]')->name) + } # end do block + + # SOAP::Dispatcher will plug-in here as well + # $handler->dispatch(SOAP::Server::Object->objects(@parameters) + : $class->$method_name(SOAP::Server::Object->objects(@parameters)) ); + }; # end eval block + SOAP::Trace::result(@results); + + # let application errors pass through with 'Server' code + die ref $@ + ? $@ + : $@ =~ /^Can\'t locate object method "$method_name"/ + ? "Failed to locate method ($method_name) in class ($class)" + : SOAP::Fault->faultcode($SOAP::Constants::FAULT_SERVER)->faultstring($@) + if $@; + + my $result = $self->serializer + ->prefix('s') # distinguish generated element names between client and server + ->uri($method_uri) + ->envelope(response => $method_name . 'Response', @results); + return $result; + }; + + # void context + return unless defined wantarray; + + # normal result + return $result unless $@; + + # check fails, something wrong with message + return $self->make_fault($SOAP::Constants::FAULT_CLIENT, $@) unless ref $@; + + # died with SOAP::Fault + return $self->make_fault($@->faultcode || $SOAP::Constants::FAULT_SERVER, + $@->faultstring || 'Application error', + $@->faultdetail, $@->faultactor) + if UNIVERSAL::isa($@ => 'SOAP::Fault'); + + # died with complex detail + return $self->make_fault($SOAP::Constants::FAULT_SERVER, 'Application error' => $@); + +} # end of handle() + +sub make_fault { + my $self = shift; + my($code, $string, $detail, $actor) = @_; + $self->serializer->fault($code, $string, $detail, $actor || $self->myuri); +} + +# ====================================================================== + +package SOAP::Trace; + +use Carp (); + +my @list = qw( + transport dispatch result + parameters headers objects + method fault freeform + trace debug); +{ + no strict 'refs'; + for (@list) { + *$_ = sub {} + } +} + +sub defaultlog { + my $caller = (caller(1))[3]; # the 4th element returned by caller is the subroutine namea + $caller = (caller(2))[3] if $caller =~ /eval/; + chomp(my $msg = join ' ', @_); + printf STDERR "%s: %s\n", $caller, $msg; +} + +sub import { + no strict 'refs'; + local $^W; + my $pack = shift; + my(@notrace, @symbols); + for (@_) { + if (ref eq 'CODE') { + my $call = $_; + foreach (@symbols) { *$_ = sub { $call->(@_) } } + @symbols = (); + } + else { + local $_ = $_; + my $minus = s/^-//; + my $all = $_ eq 'all'; + Carp::carp "Illegal symbol for tracing ($_)" unless $all || $pack->can($_); + $minus ? push(@notrace, $all ? @list : $_) : push(@symbols, $all ? @list : $_); + } + } + # TODO - I am getting a warning here about redefining a subroutine + foreach (@symbols) { *$_ = \&defaultlog } + foreach (@notrace) { *$_ = sub {} } +} + +# ====================================================================== + +package SOAP::Custom::XML::Data; + +use vars qw(@ISA $AUTOLOAD); +@ISA = qw(SOAP::Data); + +use overload fallback => 1, '""' => sub { shift->value }; + +sub _compileit { + no strict 'refs'; + my $method = shift; + *$method = sub { + return __PACKAGE__->SUPER::name($method => $_[0]->attr->{$method}) + if exists $_[0]->attr->{$method}; + my @elems = grep { + ref $_ && UNIVERSAL::isa($_ => __PACKAGE__) + && $_->SUPER::name =~ /(^|:)$method$/ + } $_[0]->value; + return wantarray? @elems : $elems[0]; + }; +} + +sub BEGIN { foreach (qw(name type import use)) { _compileit($_) } } + +sub AUTOLOAD { + my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); + return if $method eq 'DESTROY'; + + _compileit($method); + goto &$AUTOLOAD; +} + +# ====================================================================== + +package SOAP::Custom::XML::Deserializer; + +use vars qw(@ISA); +@ISA = qw(SOAP::Deserializer); + +sub decode_value { + my $self = shift; + my $ref = shift; + my($name, $attrs, $children, $value) = @$ref; + # base class knows what to do with it + return $self->SUPER::decode_value($ref) if exists $attrs->{href}; + + SOAP::Custom::XML::Data + -> SOAP::Data::name($name) + -> attr($attrs) + -> set_value(ref $children && @$children + ? map(scalar(($self->decode_object($_))[1]), @$children) + : $value); +} + +# ====================================================================== + +package SOAP::Schema::Deserializer; + +use vars qw(@ISA); +@ISA = qw(SOAP::Custom::XML::Deserializer); + +# ====================================================================== + +package SOAP::Schema::WSDL; + +use vars qw(%imported @ISA); +@ISA = qw(SOAP::Schema); + +sub new { + my $self = shift; + + unless (ref $self) { + my $class = $self; + $self = $class->SUPER::new(@_); + } + return $self; +} + +sub base { + my $self = shift->new; + @_ + ? ($self->{_base} = shift, return $self) + : return $self->{_base}; +} + +sub import { + my $self = shift->new; + my $s = shift; + my $base = shift || $self->base || die "Missing base argument for ", __PACKAGE__, "\n"; + + my @a = $s->import; + local %imported = %imported; + foreach (@a) { + next unless $_->location; + my $location = URI->new_abs($_->location->value, $base)->as_string; + if ($imported{$location}++) { + warn "Recursion loop detected in service description from '$location'. Ignored\n" if $^W; + return $s; + } + my $root = $self->import( + $self->deserializer->deserialize( + $self->access($location) + )->root, $location); + + $root->SOAP::Data::name eq 'definitions' ? $s->set_value($s->value, $root->value) : + $root->SOAP::Data::name eq 'schema' ? do { # add element if there is no one + $s->set_value($s->value, $self->deserializer->deserialize('')->root) unless $s->types; + $s->types->set_value($s->types->value, $root) } : + die "Don't know what to do with '@{[$root->SOAP::Data::name]}' in schema imported from '$location'\n"; + } + + # return the parsed WSDL file + $s; +} + +# TODO - This is woefully incomplete! +sub parse_schema_element { + my $element = shift; + # Current element is a complex type + if (defined($element->complexType)) { + my @elements = (); + if (defined($element->complexType->sequence)) { + + foreach my $e ($element->complexType->sequence->element) { + push @elements,parse_schema_element($e); + } + } + return @elements; + } + elsif ($element->simpleType) { + } + else { + return $element; + } +} + +sub parse { + my $self = shift->new; + my($s, $service, $port) = @_; + my @result; + + # handle imports + $self->import($s); + + # handle descriptions without , aka tModel-type descriptions + my @services = $s->service; + my $tns = $s->{'_attr'}->{'targetNamespace'}; + # if there is no element we'll provide it + @services = $self->deserializer->deserialize(<<"FAKE")->root->service unless @services; + + + + + +FAKE + + my $has_warned = 0; + foreach (@services) { + my $name = $_->name; + next if $service && $service ne $name; + my %services; + foreach ($_->port) { + next if $port && $port ne $_->name; + my $binding = SOAP::Utils::disqualify($_->binding); + my $endpoint = ref $_->address ? $_->address->location : undef; + foreach ($s->binding) { + # is this a SOAP binding? + next unless grep { $_->uri eq 'http://schemas.xmlsoap.org/wsdl/soap/' } $_->binding; + next unless $_->name eq $binding; + my $default_style = $_->binding->style; + my $porttype = SOAP::Utils::disqualify($_->type); + foreach ($_->operation) { + my $opername = $_->name; + $services{$opername} = {}; # should be initialized in 5.7 and after + my $soapaction = $_->operation->soapAction; + my $invocationStyle = $_->operation->style || $default_style || "rpc"; + my $encodingStyle = $_->input->body->use || "encoded"; + my $namespace = $_->input->body->namespace || $tns; + my @parts; + foreach ($s->portType) { + next unless $_->name eq $porttype; + foreach ($_->operation) { + next unless $_->name eq $opername; + my $inputmessage = SOAP::Utils::disqualify($_->input->message); + foreach my $msg ($s->message) { + next unless $msg->name eq $inputmessage; + if ($invocationStyle eq "document" && $encodingStyle eq "literal") { +# warn "document/literal support is EXPERIMENTAL in SOAP::Lite" +# if !$has_warned && ($has_warned = 1); + my ($input_ns,$input_name) = SOAP::Utils::splitqname($msg->part->element); + foreach my $schema ($s->types->schema) { + foreach my $element ($schema->element) { + next unless $element->name eq $input_name; + push @parts,parse_schema_element($element); + } + $services{$opername}->{parameters} = [ @parts ]; + } + } + else { + # TODO - support all combinations of doc|rpc/lit|enc. + #warn "$invocationStyle/$encodingStyle is not supported in this version of SOAP::Lite"; + @parts = $msg->part; + $services{$opername}->{parameters} = [ @parts ]; + } + } + } + + for ($services{$opername}) { + $_->{endpoint} = $endpoint; + $_->{soapaction} = $soapaction; + $_->{namespace} = $namespace; + # $_->{parameters} = [@parts]; + } + } + } + } + } + # fix nonallowed characters in package name, and add 's' if started with digit + for ($name) { s/\W+/_/g; s/^(\d)/s$1/ } + push @result, $name => \%services; + } + return @result; +} + +# ====================================================================== + +# Naming? SOAP::Service::Schema? +package SOAP::Schema; + +use Carp (); + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + return $self if ref $self; + unless (ref $self) { + my $class = $self; + require LWP::UserAgent; + $self = bless { + '_deserializer' => SOAP::Schema::Deserializer->new, + '_useragent' => LWP::UserAgent->new, + }, $class; + + SOAP::Trace::objects('()'); + } + + Carp::carp "Odd (wrong?) number of parameters in new()" if $^W && (@_ & 1); + no strict qw(refs); + while (@_) { + my $method = shift; + $self->$method(shift) if $self->can($method) + } + + return $self; +} + +sub schema { + warn "SOAP::Schema->schema has been deprecated. " + . "Please use SOAP::Schema->schema_url instead."; + return shift->schema_url(@_); +} + +sub BEGIN { + no strict 'refs'; + for my $method (qw(deserializer schema_url services useragent stub cache_dir cache_ttl)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + @_ ? ($self->{$field} = shift, return $self) : return $self->{$field}; + } + } +} + +sub parse { + my $self = shift; + my $s = $self->deserializer->deserialize($self->access)->root; + # here should be something that defines what schema description we want to use + $self->services({SOAP::Schema::WSDL->base($self->schema_url)->parse($s, @_)}); +} + +sub refresh_cache { + my $self = shift; + my ($filename,$contents) = @_; + open CACHE,">$filename" or Carp::croak "Could not open cache file for writing: $!"; + print CACHE $contents; + close CACHE; +} + +sub load { + my $self = shift->new; + local $^W; # supress warnings about redefining + foreach (keys %{$self->services || Carp::croak 'Nothing to load. Schema is not specified'}) { + # TODO - check age of cached file, and delete if older than configured amount + if ($self->cache_dir) { + my $cached_file = File::Spec->catfile($self->cache_dir,$_.".pm"); + my $ttl = $self->cache_ttl || $SOAP::Constants::DEFAULT_CACHE_TTL; + open (CACHE, "<$cached_file"); + my @stat = stat($cached_file) unless eof(CACHE); + close CACHE; + if (@stat) { + # Cache exists + my $cache_lived = time() - $stat[9]; + if ($ttl > 0 && $cache_lived > $ttl) { + $self->refresh_cache($cached_file,$self->generate_stub($_)); + } + } + else { + # Cache doesn't exist + $self->refresh_cache($cached_file,$self->generate_stub($_)); + } + push @INC,$self->cache_dir; + eval "require $_" or Carp::croak "Could not load cached file: $@"; + } + else { + eval $self->generate_stub($_) or Carp::croak "Bad stub: $@"; + } + } + $self; +} + +sub access { + my $self = shift->new; + my $url = shift || $self->schema_url || Carp::croak 'Nothing to access. URL is not specified'; + $self->useragent->env_proxy if $ENV{'HTTP_proxy'}; + + my $req = HTTP::Request->new(GET => $url); + $req->proxy_authorization_basic($ENV{'HTTP_proxy_user'}, $ENV{'HTTP_proxy_pass'}) + if ($ENV{'HTTP_proxy_user'} && $ENV{'HTTP_proxy_pass'}); + + my $resp = $self->useragent->request($req); + $resp->is_success ? $resp->content : die "Service description '$url' can't be loaded: ", $resp->status_line, "\n"; +} + +sub generate_stub { + my $self = shift->new; + my $package = shift; + my $services = $self->services->{$package}; + my $schema_url = $self->schema_url; + + $self->{'_stub'} = <<"EOP"; +package $package; +# Generated by SOAP::Lite (v$SOAP::Lite::VERSION) for Perl -- soaplite.com +# Copyright (C) 2000-2006 Paul Kulchenko, Byrne Reese +# -- generated at [@{[scalar localtime]}] +EOP + $self->{'_stub'} .= "# -- generated from $schema_url\n" if $schema_url; + $self->{'_stub'} .= 'my %methods = ('."\n"; + foreach my $service (keys %$services) { + $self->{'_stub'} .= "$service => {\n"; + foreach (qw(endpoint soapaction namespace)) { + $self->{'_stub'} .= " $_ => '".$services->{$service}{$_}."',\n"; + } + $self->{'_stub'} .= " parameters => [\n"; + foreach (@{$services->{$service}{parameters}}) { + # This is a workaround for https://sourceforge.net/tracker/index.php?func=detail&aid=2001592&group_id=66000&atid=513017 + next unless ref $_; + $self->{'_stub'} .= " SOAP::Data->new(name => '".$_->name."', type => '".$_->type."', attr => {"; + $self->{'_stub'} .= do { + my %attr = %{$_->attr}; + join(', ', map {"'$_' => '$attr{$_}'"} + grep {/^xmlns:(?!-)/} + keys %attr); + }; + $self->{'_stub'} .= "}),\n"; + } + $self->{'_stub'} .= " ], # end parameters\n"; + $self->{'_stub'} .= " }, # end $service\n"; + } + $self->{'_stub'} .= "); # end my %methods\n"; + $self->{'_stub'} .= <<'EOP'; + +use SOAP::Lite; +use Exporter; +use Carp (); + +use vars qw(@ISA $AUTOLOAD @EXPORT_OK %EXPORT_TAGS); +@ISA = qw(Exporter SOAP::Lite); +@EXPORT_OK = (keys %methods); +%EXPORT_TAGS = ('all' => [@EXPORT_OK]); + +sub _call { + my ($self, $method) = (shift, shift); + my $name = UNIVERSAL::isa($method => 'SOAP::Data') ? $method->name : $method; + my %method = %{$methods{$name}}; + $self->proxy($method{endpoint} || Carp::croak "No server address (proxy) specified") + unless $self->proxy; + my @templates = @{$method{parameters}}; + my @parameters = (); + foreach my $param (@_) { + if (@templates) { + my $template = shift @templates; + my ($prefix,$typename) = SOAP::Utils::splitqname($template->type); + my $method = 'as_'.$typename; + # TODO - if can('as_'.$typename) {...} + my $result = $self->serializer->$method($param, $template->name, $template->type, $template->attr); + push(@parameters, $template->value($result->[2])); + } + else { + push(@parameters, $param); + } + } + $self->endpoint($method{endpoint}) + ->ns($method{namespace}) + ->on_action(sub{qq!"$method{soapaction}"!}); +EOP + my $namespaces = $self->deserializer->ids->[1]; + foreach my $key (keys %{$namespaces}) { + my ($ns,$prefix) = SOAP::Utils::splitqname($key); + $self->{'_stub'} .= ' $self->serializer->register_ns("'.$namespaces->{$key}.'","'.$prefix.'");'."\n" + if ($ns eq "xmlns"); + } + $self->{'_stub'} .= <<'EOP'; + my $som = $self->SUPER::call($method => @parameters); + if ($self->want_som) { + return $som; + } + UNIVERSAL::isa($som => 'SOAP::SOM') ? wantarray ? $som->paramsall : $som->result : $som; +} + +sub BEGIN { + no strict 'refs'; + for my $method (qw(want_som)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + @_ ? ($self->{$field} = shift, return $self) : return $self->{$field}; + } + } +} +no strict 'refs'; +for my $method (@EXPORT_OK) { + my %method = %{$methods{$method}}; + *$method = sub { + my $self = UNIVERSAL::isa($_[0] => __PACKAGE__) + ? ref $_[0] + ? shift # OBJECT + # CLASS, either get self or create new and assign to self + : (shift->self || __PACKAGE__->self(__PACKAGE__->new)) + # function call, either get self or create new and assign to self + : (__PACKAGE__->self || __PACKAGE__->self(__PACKAGE__->new)); + $self->_call($method, @_); + } +} + +sub AUTOLOAD { + my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); + return if $method eq 'DESTROY' || $method eq 'want_som'; + die "Unrecognized method '$method'. List of available method(s): @EXPORT_OK\n"; +} + +1; +EOP + return $self->stub; +} + +# ====================================================================== + +package SOAP; + +use vars qw($AUTOLOAD); +require URI; + +my $soap; # shared between SOAP and SOAP::Lite packages + +{ + no strict 'refs'; + *AUTOLOAD = sub { + local($1,$2); + my($package, $method) = $AUTOLOAD =~ m/(?:(.+)::)([^:]+)$/; + return if $method eq 'DESTROY'; + + my $soap = ref $_[0] && UNIVERSAL::isa($_[0] => 'SOAP::Lite') + ? $_[0] + : $soap + || die "SOAP:: prefix shall only be used in combination with +autodispatch option\n"; + + my $uri = URI->new($soap->uri); + my $currenturi = $uri->path; + $package = ref $_[0] && UNIVERSAL::isa($_[0] => 'SOAP::Lite') + ? $currenturi + : $package eq 'SOAP' + ? ref $_[0] || ($_[0] eq 'SOAP' + ? $currenturi || Carp::croak "URI is not specified for method call" + : $_[0]) + : $package eq 'main' + ? $currenturi || $package + : $package; + + # drop first parameter if it's a class name + { + my $pack = $package; + for ($pack) { s!^/!!; s!/!::!g; } + shift @_ if @_ && !ref $_[0] && ($_[0] eq $pack || $_[0] eq 'SOAP') + || ref $_[0] && UNIVERSAL::isa($_[0] => 'SOAP::Lite'); + } + + for ($package) { s!::!/!g; s!^/?!/!; } + $uri->path($package); + + my $som = $soap->uri($uri->as_string)->call($method => @_); + UNIVERSAL::isa($som => 'SOAP::SOM') + ? wantarray + ? $som->paramsall + : $som->result + : $som; + }; +} + +# ====================================================================== + +package SOAP::Lite; + +use vars qw($AUTOLOAD @ISA); +use Carp (); + +use SOAP::Lite::Utils; +use SOAP::Constants; +use SOAP::Packager; + +use Scalar::Util qw(weaken); + +@ISA = qw(SOAP::Cloneable); + +# provide access to global/autodispatched object +sub self { + @_ > 1 + ? $soap = $_[1] + : $soap +} + +# no more warnings about "used only once" +*UNIVERSAL::AUTOLOAD if 0; + +sub autodispatched { \&{*UNIVERSAL::AUTOLOAD} eq \&{*SOAP::AUTOLOAD} }; + +sub soapversion { + my $self = shift; + my $version = shift or return $SOAP::Constants::SOAP_VERSION; + + ($version) = grep { + $SOAP::Constants::SOAP_VERSIONS{$_}->{NS_ENV} eq $version + } keys %SOAP::Constants::SOAP_VERSIONS + unless exists $SOAP::Constants::SOAP_VERSIONS{$version}; + + die qq!$SOAP::Constants::WRONG_VERSION Supported versions:\n@{[ + join "\n", map {" $_ ($SOAP::Constants::SOAP_VERSIONS{$_}->{NS_ENV})"} keys %SOAP::Constants::SOAP_VERSIONS + ]}\n! + unless defined($version) && defined(my $def = $SOAP::Constants::SOAP_VERSIONS{$version}); + + foreach (keys %$def) { + eval "\$SOAP::Constants::$_ = '$SOAP::Constants::SOAP_VERSIONS{$version}->{$_}'"; + } + + $SOAP::Constants::SOAP_VERSION = $version; + + return $self; +} + +BEGIN { SOAP::Lite->soapversion(1.1) } + +sub import { + my $pkg = shift; + my $caller = caller; + no strict 'refs'; + # emulate 'use SOAP::Lite 0.99' behavior + $pkg->require_version(shift) if defined $_[0] && $_[0] =~ /^\d/; + + while (@_) { + my $command = shift; + + my @parameters = UNIVERSAL::isa($_[0] => 'ARRAY') + ? @{shift()} + : shift + if @_ && $command ne 'autodispatch'; + + if ($command eq 'autodispatch' || $command eq 'dispatch_from') { + $soap = ($soap||$pkg)->new; + no strict 'refs'; + foreach ($command eq 'autodispatch' + ? 'UNIVERSAL' + : @parameters + ) { + my $sub = "${_}::AUTOLOAD"; + defined &{*$sub} + ? (\&{*$sub} eq \&{*SOAP::AUTOLOAD} + ? () + : Carp::croak "$sub already assigned and won't work with DISPATCH. Died") + : (*$sub = *SOAP::AUTOLOAD); + } + } + elsif ($command eq 'service') { + foreach (keys %{SOAP::Schema->schema_url(shift(@parameters))->parse(@parameters)->load->services}) { + $_->export_to_level(1, undef, ':all'); + } + } + elsif ($command eq 'debug' || $command eq 'trace') { + SOAP::Trace->import(@parameters ? @parameters : 'all'); + } + elsif ($command eq 'import') { + local $^W; # supress warnings about redefining + my $package = shift(@parameters); + $package->export_to_level(1, undef, @parameters ? @parameters : ':all') if $package; + } + else { + Carp::carp "Odd (wrong?) number of parameters in import(), still continue" if $^W && !(@parameters & 1); + $soap = ($soap||$pkg)->$command(@parameters); + } + } +} + +sub DESTROY { SOAP::Trace::objects('()') } + +sub new { + my $self = shift; + return $self if ref $self; + unless (ref $self) { + my $class = $self; + # Check whether we can clone. Only the SAME class allowed, no inheritance + $self = ref($soap) eq $class ? $soap->clone : { + _transport => SOAP::Transport->new, + _serializer => SOAP::Serializer->new, + _deserializer => SOAP::Deserializer->new, + _packager => SOAP::Packager::MIME->new, + _schema => undef, + _autoresult => 0, + _on_action => sub { sprintf '"%s#%s"', shift || '', shift }, + _on_fault => sub {ref $_[1] ? return $_[1] : Carp::croak $_[0]->transport->is_success ? $_[1] : $_[0]->transport->status}, + }; + bless $self => $class; + $self->on_nonserialized($self->on_nonserialized || $self->serializer->on_nonserialized); + SOAP::Trace::objects('()'); + } + + Carp::carp "Odd (wrong?) number of parameters in new()" if $^W && (@_ & 1); + no strict qw(refs); + while (@_) { + my($method, $params) = splice(@_,0,2); + $self->can($method) + ? $self->$method(ref $params eq 'ARRAY' ? @$params : $params) + : $^W && Carp::carp "Unrecognized parameter '$method' in new()" + } + + return $self; +} + +sub init_context { + my $self = shift->new; + $self->{'_deserializer'}->{'_context'} = $self; + # weaken circular reference to avoid a memory hole + weaken $self->{'_deserializer'}->{'_context'}; + + $self->{'_serializer'}->{'_context'} = $self; + # weaken circular reference to avoid a memory hole + weaken $self->{'_serializer'}->{'_context'}; +} + +# Naming? wsdl_parser +sub schema { + my $self = shift; + if (@_) { + $self->{'_schema'} = shift; + return $self; + } + else { + if (!defined $self->{'_schema'}) { + $self->{'_schema'} = SOAP::Schema->new; + } + return $self->{'_schema'}; + } +} + +sub BEGIN { + no strict 'refs'; + for my $method (qw(serializer deserializer)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + if (@_) { + my $context = $self->{$field}->{'_context'}; # save the old context + $self->{$field} = shift; + $self->{$field}->{'_context'} = $context; # restore the old context + return $self; + } + else { + return $self->{$field}; + } + } + } + + __PACKAGE__->__mk_accessors( + qw(endpoint transport outputxml autoresult packager) + ); + # for my $method () { + # my $field = '_' . $method; + # *$method = sub { + # my $self = shift->new; + # @_ ? ($self->{$field} = shift, return $self) : return $self->{$field}; + # } + # } + for my $method (qw(on_action on_fault on_nonserialized)) { + my $field = '_' . $method; + *$method = sub { + my $self = shift->new; + return $self->{$field} unless @_; + local $@; + # commented out because that 'eval' was unsecure + # > ref $_[0] eq 'CODE' ? shift : eval shift; + # Am I paranoid enough? + $self->{$field} = shift; + Carp::croak $@ if $@; + Carp::croak "$method() expects subroutine (CODE) or string that evaluates into subroutine (CODE)" + unless ref $self->{$field} eq 'CODE'; + return $self; + } + } + # SOAP::Transport Shortcuts + # TODO - deprecate proxy() in favor of new language endpoint_url() + no strict qw(refs); + for my $method (qw(proxy)) { + *$method = sub { + my $self = shift->new; + @_ ? ($self->transport->$method(@_), return $self) : return $self->transport->$method(); + } + } + + # SOAP::Seriailizer Shortcuts + for my $method (qw(autotype readable envprefix encodingStyle + encprefix multirefinplace encoding + typelookup header maptype xmlschema + uri ns_prefix ns_uri use_prefix use_default_ns + ns default_ns)) { + *$method = sub { + my $self = shift->new; + @_ ? ($self->serializer->$method(@_), return $self) : return $self->serializer->$method(); + } + } + + # SOAP::Schema Shortcuts + for my $method (qw(cache_dir cache_ttl)) { + *$method = sub { + my $self = shift->new; + @_ ? ($self->schema->$method(@_), return $self) : return $self->schema->$method(); + } + } +} + +sub parts { + my $self = shift; + $self->packager->parts(@_); + return $self; +} + +# Naming? wsdl +sub service { + my $self = shift->new; + return $self->{'_service'} unless @_; + $self->schema->schema_url($self->{'_service'} = shift); + my %services = %{$self->schema->parse(@_)->load->services}; + + Carp::croak "More than one service in service description. Service and port names have to be specified\n" + if keys %services > 1; + my $service = (keys %services)[0]->new; + return $service; +} + +sub AUTOLOAD { + my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::') + 2); + return if $method eq 'DESTROY'; + + ref $_[0] or Carp::croak qq!Can\'t locate class method "$method" via package \"! . __PACKAGE__ .'\"'; + + no strict 'refs'; + *$AUTOLOAD = sub { + my $self = shift; + my $som = $self->call($method => @_); + return $self->autoresult && UNIVERSAL::isa($som => 'SOAP::SOM') + ? wantarray ? $som->paramsall : $som->result + : $som; + }; + goto &$AUTOLOAD; +} + +sub call { + SOAP::Trace::trace('()'); + my $self = shift; + + die "A service address has not been specified either by using SOAP::Lite->proxy() or a service description)\n" + unless defined $self->proxy && UNIVERSAL::isa($self->proxy => 'SOAP::Client'); + + $self->init_context(); + + my $serializer = $self->serializer; + $serializer->on_nonserialized($self->on_nonserialized); + + my $response = $self->transport->send_receive( + context => $self, # this is provided for context + endpoint => $self->endpoint, + action => scalar($self->on_action->($serializer->uriformethod($_[0]))), + # leave only parameters so we can later update them if required + envelope => $serializer->envelope(method => shift, @_), + encoding => $serializer->encoding, + parts => @{$self->packager->parts} ? $self->packager->parts : undef, + ); + + return $response if $self->outputxml; + + my $result = eval { $self->deserializer->deserialize($response) } + if $response; + + if (!$self->transport->is_success || # transport fault + $@ || # not deserializible + # fault message even if transport OK + # or no transport error (for example, fo TCP, POP3, IO implementations) + UNIVERSAL::isa($result => 'SOAP::SOM') && $result->fault) { + return ($self->on_fault->($self, $@ + ? $@ . ($response || '') + : $result) + || $result + ); + # ? # trick editors + } + # this might be trouble for connection close... + return unless $response; # nothing to do for one-ways + + # little bit tricky part that binds in/out parameters + if (UNIVERSAL::isa($result => 'SOAP::SOM') + && ($result->paramsout || $result->headers) + && $serializer->signature) { + my $num = 0; + my %signatures = map {$_ => $num++} @{$serializer->signature}; + for ($result->dataof(SOAP::SOM::paramsout), $result->dataof(SOAP::SOM::headers)) { + my $signature = join $;, $_->name, $_->type || ''; + if (exists $signatures{$signature}) { + my $param = $signatures{$signature}; + my($value) = $_->value; # take first value + + # fillup parameters + UNIVERSAL::isa($_[$param] => 'SOAP::Data') + ? $_[$param]->SOAP::Data::value($value) + : UNIVERSAL::isa($_[$param] => 'ARRAY') + ? (@{$_[$param]} = @$value) + : UNIVERSAL::isa($_[$param] => 'HASH') + ? (%{$_[$param]} = %$value) + : UNIVERSAL::isa($_[$param] => 'SCALAR') + ? (${$_[$param]} = $$value) + : ($_[$param] = $value) + } + } + } + return $result; +} # end of call() + +# ====================================================================== + +package SOAP::Lite::COM; + +require SOAP::Lite; + +sub required { + foreach (qw( + URI::_foreign URI::http URI::https + LWP::Protocol::http LWP::Protocol::https LWP::Authen::Basic LWP::Authen::Digest + HTTP::Daemon Compress::Zlib SOAP::Transport::HTTP + XMLRPC::Lite XMLRPC::Transport::HTTP + )) { + eval join ';', 'local $SIG{__DIE__}', "require $_"; + } +} + +sub new { required; SOAP::Lite->new(@_) } + +sub create; *create = \&new; # make alias. Somewhere 'new' is registered keyword + +sub soap; *soap = \&new; # also alias. Just to be consistent with .xmlrpc call + +sub xmlrpc { required; XMLRPC::Lite->new(@_) } + +sub server { required; shift->new(@_) } + +sub data { SOAP::Data->new(@_) } + +sub header { SOAP::Header->new(@_) } + +sub hash { +{@_} } + +sub instanceof { + my $class = shift; + die "Incorrect class name" unless $class =~ /^(\w[\w:]*)$/; + eval "require $class"; + $class->new(@_); +} + +# ====================================================================== + +1; + +__END__ + +=pod + +=head1 NAME + +SOAP::Lite - Perl's Web Services Toolkit + +=head1 DESCRIPTION + +SOAP::Lite is a collection of Perl modules which provides a simple and +lightweight interface to the Simple Object Access Protocol (SOAP) both on +client and server side. + +=head1 PERL VERSION WARNING + +SOAP::Lite 0.71 will be the last version of SOAP::Lite running on perl 5.005 + +Future versions of SOAP::Lite will require at least perl 5.6.0 + +If you have not had the time to upgrad your perl, you should consider this +now. + +=head1 OVERVIEW OF CLASSES AND PACKAGES + +=over + +=item F + +L - Main class provides all logic + +L - Transport backend + +L - Data objects + +L - Header Data Objects + +L - Serializes data structures to SOAP messages + +L - Deserializes SOAP messages into SOAP::SOM objects + +L - SOAP Message objects + +L - Provides access to common constants and defaults + +L - Tracing facilities + +L - Provides access and stub(s) for schema(s) + +L - WSDL implementation for SOAP::Schema + +L - Handles requests on server side + +SOAP::Server::Object - Handles objects-by-reference + +L - Provides support for Faults on server side + +L - A set of private and public utility subroutines + +=item F + +L - Provides an abstract class for implementing custom packagers. + +L - Provides MIME support to SOAP::Lite + +L - Provides DIME support to SOAP::Lite + +=item F + +L - Client interface to HTTP transport + +L - Server interface to HTTP transport + +L - CGI implementation of server interface + +L - Daemon implementation of server interface + +L - mod_perl implementation of server interface + +=item F + +L - Server interface to POP3 protocol + +=item F + +L - Client interface to SMTP/sendmail + +=item F + +L - Client interface to local transport + +=item F + +L - Server interface to TCP protocol + +L - Client interface to TCP protocol + +=item F + +L - Server interface to IO transport + +=back + +=head1 METHODS + +All accessor methods return the current value when called with no arguments, +while returning the object reference itself when called with a new value. +This allows the set-attribute calls to be chained together. + +=over + +=item new(optional key/value pairs) + + $client = SOAP::Lite->new(proxy => $endpoint) + +Constructor. Many of the accessor methods defined here may be initialized at +creation by providing their name as a key, followed by the desired value. +The example provides the value for the proxy element of the client. + +=item transport(optional transport object) + + $transp = $client->transport( ); + +Gets or sets the transport object used for sending/receiving SOAP messages. + +See L for details. + +=item serializer(optional serializer object) + + $serial = $client->serializer( ) + +Gets or sets the serializer object used for creating XML messages. + +See L for details. + +=item packager(optional packager object) + + $packager = $client->packager( ) + +Provides access to the C object that the client uses to manage +the use of attachments. The default packager is a MIME packager, but unless +you specify parts to send, no MIME formatting will be done. + +See also: L. + +=item proxy(endpoint, optional extra arguments) + + $client->proxy('http://soap.xml.info/ endPoint'); + +The proxy is the server or endpoint to which the client is going to connect. +This method allows the setting of the endpoint, along with any extra +information that the transport object may need when communicating the request. + +This method is actually an alias to the proxy method of L. +It is the same as typing: + + $client->transport( )->proxy(...arguments); + +Extra parameters can be passed to proxy() - see below. + +=over + +=item compress_threshold + +See L in L. + +=item All initialization options from the underlying transport layer + +The options for HTTP(S) are the same as for LWP::UserAgent's new() method. + +A common option is to create a instance of HTTP::Cookies and pass it as +cookie_jar option: + + my $cookie_jar = HTTP::Cookies->new() + $client->proxy('http://www.example.org/webservice', + cookie_jar => $cookie_jar, + ); + +=back + +For example, if you wish to set the HTTP timeout for a SOAP::Lite client to 5 +seconds, use the following code: + + my $soap = SOAP::Lite + ->uri($uri) + ->proxy($proxyUrl, timeout => 5 ); + +See L. + +=item endpoint(optional new endpoint address) + + $client->endpoint('http://soap.xml.info/ newPoint') + +It may be preferable to set a new endpoint without the additional work of +examining the new address for protocol information and checking to ensure the +support code is loaded and available. This method allows the caller to change +the endpoint that the client is currently set to connect to, without +reloading the relevant transport code. Note that the proxy method must have +been called before this method is used. + +=item service(service URL) + + $client->service('http://svc.perl.org/Svc.wsdl'); + +C offers some support for creating method stubs from service +descriptions. At present, only WSDL support is in place. This method loads +the specified WSDL schema and uses it as the basis for generating stubs. + +=item outputxml(boolean) + + $client->outputxml('true'); + +When set to a true value, the raw XML is returned by the call to a remote +method. + +The default is to return the a L object (false). + +=item autotype(boolean) + + $client->autotype(0); + +This method is a shortcut for: + + $client->serializer->autotype(boolean); + +By default, the serializer tries to automatically deduce types for the data +being sent in a message. Setting a false value with this method disables the +behavior. + +=item readable(boolean) + + $client->readable(1); + +This method is a shortcut for: + + $client->serializer->readable(boolean); + +When this is used to set a true value for this property, the generated XML +sent to the endpoint has extra characters (spaces and new lines) added in to +make the XML itself more readable to human eyes (presumably for debugging). +The default is to not send any additional characters. + +=item default_ns($uri) + +Sets the default namespace for the request to the specified uri. This +overrides any previous namespace declaration that may have been set using a +previous call to C or C. Setting the default namespace +causes elements to be serialized without a namespace prefix, like this: + + + + + + + + + +Some .NET web services have been reported to require this XML namespace idiom. + +=item ns($uri,$prefix=undef) + +Sets the namespace uri and optionally the namespace prefix for the request to +the specified values. This overrides any previous namespace declaration that +may have been set using a previous call to C or C. + +If a prefix is not specified, one will be generated for you automatically. +Setting the namespace causes elements to be serialized with a declared +namespace prefix, like this: + + + + + + + + + +=item use_prefix(boolean) + +Deprecated. Use the C and C methods described above. + +Shortcut for C<< serializer->use_prefix() >>. This lets you turn on/off the +use of a namespace prefix for the children of the /Envelope/Body element. +Default is 'true'. + +When use_prefix is set to 'true', serialized XML will look like this: + + + + + + + +When use_prefix is set to 'false', serialized XML will look like this: + + + + + + + +Some .NET web services have been reported to require this XML namespace idiom. + +=item soapversion(optional value) + + $client->soapversion('1.2'); + +If no parameter is given, returns the current version of SOAP that is being +used by the client object to encode requests. If a parameter is given, the +method attempts to set that as the version of SOAP being used. + +The value should be either 1.1 or 1.2. + +=item envprefix(QName) + + $client->envprefix('env'); + +This method is a shortcut for: + + $client->serializer->envprefix(QName); + +Gets or sets the namespace prefix for the SOAP namespace. The default is +SOAP. + +The prefix itself has no meaning, but applications may wish to chose one +explicitly to denote different versions of SOAP or the like. + +=item encprefix(QName) + + $client->encprefix('enc'); + +This method is a shortcut for: + + $client->serializer->encprefix(QName); + +Gets or sets the namespace prefix for the encoding rules namespace. +The default value is SOAP-ENC. + +=back + +While it may seem to be an unnecessary operation to set a value that isn't +relevant to the message, such as the namespace labels for the envelope and +encoding URNs, the ability to set these labels explicitly can prove to be a +great aid in distinguishing and debugging messages on the server side of +operations. + +=over + +=item encoding(encoding URN) + + $client->encoding($soap_12_encoding_URN); + +This method is a shortcut for: + + $client->serializer->encoding(args); + +Where the earlier method dealt with the label used for the attributes related +to the SOAP encoding scheme, this method actually sets the URN to be specified +as the encoding scheme for the message. The default is to specify the encoding +for SOAP 1.1, so this is handy for applications that need to encode according +to SOAP 1.2 rules. + +=item typelookup + + $client->typelookup; + +This method is a shortcut for: + + $client->serializer->typelookup; + +Gives the application access to the type-lookup table from the serializer +object. See the section on L. + +=item uri(service specifier) + +Deprecated - the C subroutine is deprecated in order to provide a more +intuitive naming scheme for subroutines that set namespaces. In the future, +you will be required to use either the C or C subroutines +instead of C. + + $client->uri($service_uri); + +This method is a shortcut for: + + $client->serializer->uri(service); + +The URI associated with this accessor on a client object is the +service-specifier for the request, often encoded for HTTP-based requests as +the SOAPAction header. While the names may seem confusing, this method +doesn't specify the endpoint itself. In most circumstances, the C refers +to the namespace used for the request. + +Often times, the value may look like a valid URL. Despite this, it doesn't +have to point to an existing resource (and often doesn't). This method sets +and retrieves this value from the object. Note that no transport code is +triggered by this because it has no direct effect on the transport of the +object. + +=item multirefinplace(boolean) + + $client->multirefinplace(1); + +This method is a shortcut for: + + $client->serializer->multirefinplace(boolean); + +Controls how the serializer handles values that have multiple references to +them. Recall from previous SOAP chapters that a value may be tagged with an +identifier, then referred to in several places. When this is the case for a +value, the serializer defaults to putting the data element towards the top of +the message, right after the opening tag of the method-specification. It is +serialized as a standalone entity with an ID that is then referenced at the +relevant places later on. If this method is used to set a true value, the +behavior is different. When the multirefinplace attribute is true, the data +is serialized at the first place that references it, rather than as a separate +element higher up in the body. This is more compact but may be harder to read +or trace in a debugging environment. + +=item parts( ARRAY ) + +Used to specify an array of L's to be attached to the +transmitted SOAP message. Attachments that are returned in a response can be +accessed by C. + +=item self + + $ref = SOAP::Lite->self; + +Returns an object reference to the default global object the C +package maintains. This is the object that processes many of the arguments +when provided on the use line. + +=back + +The following method isn't an accessor style of method but neither does it fit +with the group that immediately follows it: + +=over + +=item call(arguments) + + $client->call($method => @arguments); + +As has been illustrated in previous chapters, the C client objects +can manage remote calls with auto-dispatching using some of Perl's more +elaborate features. call is used when the application wants a greater degree +of control over the details of the call itself. The method may be built up +from a L object, so as to allow full control over the namespace +associated with the tag, as well as other attributes like encoding. This is +also important for calling methods that contain characters not allowable in +Perl function names, such as A.B.C. + +=back + +The next four methods used in the C class are geared towards +handling the types of events than can occur during the message lifecycle. Each +of these sets up a callback for the event in question: + +=over + +=item on_action(callback) + + $client->on_action(sub { qq("$_[0]") }); + +Triggered when the transport object sets up the SOAPAction header for an +HTTP-based call. The default is to set the header to the string, uri#method, +in which URI is the value set by the uri method described earlier, and method +is the name of the method being called. When called, the routine referenced +(or the closure, if specified as in the example) is given two arguments, uri +and method, in that order. + +.NET web services usually expect C as separator for C and C. +To change SOAP::Lite's behaviour to use uri/method as SOAPAction header, use +the following code: + + $client->on_action( sub { join '/', @_ } ); +=item on_fault(callback) + + $client->on_fault(sub { popup_dialog($_[1]) }); + +Triggered when a method call results in a fault response from the server. +When it is called, the argument list is first the client object itself, +followed by the object that encapsulates the fault. In the example, the fault +object is passed (without the client object) to a hypothetical GUI function +that presents an error dialog with the text of fault extracted from the object +(which is covered shortly under the L methods). + +=item on_nonserialized(callback) + + $client->on_nonserialized(sub { die "$_[0]?!?" }); + +Occasionally, the serializer may be given data it can't turn into SOAP-savvy +XML; for example, if a program bug results in a code reference or something +similar being passed in as a parameter to method call. When that happens, this +callback is activated, with one argument. That argument is the data item that +could not be understood. It will be the only argument. If the routine returns, +the return value is pasted into the message as the serialization. Generally, +an error is in order, and this callback allows for control over signaling that +error. + +=item on_debug(callback) + + $client->on_debug(sub { print @_ }); + +Deprecated. Use the global +debug and +trace facilities described in +L + +Note that this method will not work as expected: Instead of affecting the +debugging behaviour of the object called on, it will globally affect the +debugging behaviour for all objects of that class. + +=back + +=head1 WRITING A SOAP CLIENT + +This chapter guides you to writing a SOAP client by example. + +The SOAP service to be accessed is a simple variation of the well-known +hello world program. It accepts two parameters, a name and a given name, +and returns "Hello $given_name $name". + +We will use "Martin Kutter" as the name for the call, so all variants will +print the following message on success: + + Hello Martin Kutter! + +=head2 SOAP message styles + +There are three common (and one less common) variants of SOAP messages. + +These address the message style (positional parameters vs. specified message +documents) and encoding (as-is vs. typed). + +The different message styles are: + +=over + +=item * rpc/encoded + +Typed, positional parameters. Widely used in scripting languages. +The type of the arguments is included in the message. +Arrays and the like may be encoded using SOAP encoding rules (or others). + +=item * rpc/literal + +As-is, positional parameters. The type of arguments is defined by some +pre-exchanged interface definition. + +=item * document/encoded + +Specified message with typed elements. Rarely used. + +=item * document/literal + +Specified message with as-is elements. The message specification and +element types are defined by some pre-exchanged interface definition. + +=back + +As of 2008, document/literal has become the predominant SOAP message +variant. rpc/literal and rpc/encoded are still in use, mainly with scripting +languages, while document/encoded is hardly used at all. + +You will see clients for the rpc/encoded and document/literal SOAP variants in +this section. + +=head2 Example implementations + +=head3 RPC/ENCODED + +Rpc/encoded is most popular with scripting languages like perl, php and python +without the use of a WSDL. Usual method descriptions look like this: + + Method: sayHello(string, string) + Parameters: + name: string + givenName: string + +Such a description usually means that you can call a method named "sayHello" +with two positional parameters, "name" and "givenName", which both are +strings. + +The message corresponding to this description looks somewhat like this: + + + Kutter + Martin + + +Any XML tag names may be used instead of the "s-gensym01" stuff - parameters +are positional, the tag names have no meaning. + +A client producing such a call is implemented like this: + + use SOAP::Lite; + my $soap = SOAP::Lite->new( proxy => 'http://localhost:81/soap-wsdl-test/helloworld.pl'); + $soap->default_ns('urn:HelloWorld'); + my $som = $soap->call('sayHello', 'Kutter', 'Martin'); + die $som->faultstring if ($som->fault); + print $som->result, "\n"; + +You can of course use a one-liner, too... + +Sometimes, rpc/encoded interfaces are described with WSDL definitions. +A WSDL accepting "named" parameters with rpc/encoded looks like this: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The message corresponding to this schema looks like this: + + + Kutter + Martin + + +A web service client using this schema looks like this: + + use SOAP::Lite; + my $soap = SOAP::Lite->service("file:say_hello_rpcenc.wsdl"); + eval { my $result = $soap->sayHello('Kutter', 'Martin'); }; + if ($@) { + die $@; + } + print $som->result(); + +You may of course also use the following one-liner: + + perl -MSOAP::Lite -e 'print SOAP::Lite->service("file:say_hello_rpcenc.wsdl")\ + ->sayHello('Kutter', 'Martin'), "\n";' + +A web service client (without a service description) looks like this. + + use SOAP::Lite; + my $soap = SOAP::Lite->new( proxy => 'http://localhost:81/soap-wsdl-test/helloworld.pl'); + $soap->default_ns('urn:HelloWorld'); + my $som = $soap->call('sayHello', + SOAP::Data->name('name')->value('Kutter'), + SOAP::Data->name('givenName')->value('Martin') + ); + die $som->faultstring if ($som->fault); + print $som->result, "\n"; + +=head3 RPC/LITERAL + +SOAP web services using the document/literal message encoding are usually +described by some Web Service Definition. Our web service has the following +WSDL description: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The XML message (inside the SOAP Envelope) look like this: + + + + + Kutter + Martin + + + + + + Hello Martin Kutter! + + + +This is the SOAP::Lite implementation for the web service client: + + use SOAP::Lite +trace; + my $soap = SOAP::Lite->new( proxy => 'http://localhost:80/helloworld.pl'); + + $soap->on_action( sub { "urn:HelloWorld#sayHello" }); + $soap->autotype(0)->readable(1); + $soap->default_ns('urn:HelloWorld'); + + my $som = $soap->call('sayHello', SOAP::Data->name('parameters')->value( + \SOAP::Data->value([ + SOAP::Data->name('name')->value( 'Kutter' ), + SOAP::Data->name('givenName')->value('Martin'), + ])) +); + + die $som->fault->{ faultstring } if ($som->fault); + print $som->result, "\n"; + +=head3 DOCUMENT/LITERAL + +SOAP web services using the document/literal message encoding are usually +described by some Web Service Definition. Our web service has the following +WSDL description: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The XML message (inside the SOAP Envelope) look like this: + + + Kutter + Martin + + + + Hello Martin Kutter! + + +You can call this web service with the following client code: + + use SOAP::Lite; + my $soap = SOAP::Lite->new( proxy => 'http://localhost:80/helloworld.pl'); + + $soap->on_action( sub { "urn:HelloWorld#sayHello" }); + $soap->autotype(0); + $soap->default_ns('urn:HelloWorld'); + + my $som = $soap->call("sayHello", + SOAP::Data->name('name')->value( 'Kutter' ), + SOAP::Data->name('givenName')->value('Martin'), +); + + die $som->fault->{ faultstring } if ($som->fault); + print $som->result, "\n"; + +=head2 Differences between the implementations + +You may have noticed that there's little difference between the rpc/encoded, +rpc/literal and the document/literal example's implementation. In fact, from +SOAP::Lite's point of view, the only differences between rpc/literal and +document/literal that parameters are always named. + +In our example, the rpc/encoded variant already used named parameters (by +using two messages), so there's no difference at all. + +You may have noticed the somewhat strange idiom for passing a list of named +paraneters in the rpc/literal example: + + my $som = $soap->call('sayHello', SOAP::Data->name('parameters')->value( + \SOAP::Data->value([ + SOAP::Data->name('name')->value( 'Kutter' ), + SOAP::Data->name('givenName')->value('Martin'), + ])) + ); + +While SOAP::Data provides full control over the XML generated, passing +hash-like structures require additional coding. + +=head1 WRITING A SOAP SERVER + +See L, or L. + +=head1 FEATURES + +=head2 ATTACHMENTS + +C features support for the SOAP with Attachments specification. +Currently, SOAP::Lite only supports MIME based attachments. DIME based +attachments are yet to be fully functional. + +=head3 EXAMPLES + +=head4 Client sending an attachment + +C clients can specify attachments to be sent along with a request +by using the C method, which takes as an argument an +ARRAY of C's. + + use SOAP::Lite; + use MIME::Entity; + my $ent = build MIME::Entity + Type => "image/gif", + Encoding => "base64", + Path => "somefile.gif", + Filename => "saveme.gif", + Disposition => "attachment"; + my $som = SOAP::Lite + ->uri($SOME_NAMESPACE) + ->parts([ $ent ]) + ->proxy($SOME_HOST) + ->some_method(SOAP::Data->name("foo" => "bar")); + +=head4 Client retrieving an attachment + +A client accessing attachments that were returned in a response by using the +C accessor. + + use SOAP::Lite; + use MIME::Entity; + my $soap = SOAP::Lite + ->uri($NS) + ->proxy($HOST); + my $som = $soap->foo(); + foreach my $part (${$som->parts}) { + print $part->stringify; + } + +=head4 Server receiving an attachment + +Servers, like clients, use the S module to access attachments +transmitted to it. + + package Attachment; + use SOAP::Lite; + use MIME::Entity; + use strict; + use vars qw(@ISA); + @ISA = qw(SOAP::Server::Parameters); + sub someMethod { + my $self = shift; + my $envelope = pop; + foreach my $part (@{$envelope->parts}) { + print "AttachmentService: attachment found! (".ref($part).")\n"; + } + # do something + } + +=head4 Server responding with an attachment + +Servers wishing to return an attachment to the calling client need only return +C objects along with SOAP::Data elements, or any other data +intended for the response. + + package Attachment; + use SOAP::Lite; + use MIME::Entity; + use strict; + use vars qw(@ISA); + @ISA = qw(SOAP::Server::Parameters); + sub someMethod { + my $self = shift; + my $envelope = pop; + my $ent = build MIME::Entity + 'Id' => "<1234>", + 'Type' => "text/xml", + 'Path' => "some.xml", + 'Filename' => "some.xml", + 'Disposition' => "attachment"; + return SOAP::Data->name("foo" => "blah blah blah"),$ent; + } + +=head2 DEFAULT SETTINGS + +Though this feature looks similar to +L they have (almost) +nothing in common. This capability allows you specify default settings so that +all objects created after that will be initialized with the proper default +settings. + +If you wish to provide common C or C settings for all +C objects in your application you may do: + + use SOAP::Lite + proxy => 'http://localhost/cgi-bin/soap.cgi', + uri => 'http://my.own.com/My/Examples'; + + my $soap1 = new SOAP::Lite; # will get the same proxy()/uri() as above + print $soap1->getStateName(1)->result; + + my $soap2 = SOAP::Lite->new; # same thing as above + print $soap2->getStateName(2)->result; + + # or you may override any settings you want + my $soap3 = SOAP::Lite->proxy('http://localhost/'); + print $soap3->getStateName(1)->result; + +B C properties can be propagated this way. Changes in object +copies will not affect global settings and you may still change global +settings with C<< SOAP::Lite->self >> call which returns reference to global +object. Provided parameter will update this object and you can even set it to +C: + + SOAP::Lite->self(undef); + +The C syntax also lets you specify default event handlers for +your code. If you have different SOAP objects and want to share the same +C (or C for that matter) handler. You can specify +C during initialization for every object, but you may also do: + + use SOAP::Lite + on_action => sub {sprintf '%s#%s', @_}; + +and this handler will be the default handler for all your SOAP objects. You +can override it if you specify a handler for a particular object. See F +for example of on_fault() handler. + +Be warned, that since C is executed at compile time B C +statements will be executed B script execution that can make +unexpected results. Consider code: + + use SOAP::Lite proxy => 'http://localhost/'; + print SOAP::Lite->getStateName(1)->result; + + use SOAP::Lite proxy => 'http://localhost/cgi-bin/soap.cgi'; + print SOAP::Lite->getStateName(1)->result; + +B SOAP calls will go to C<'http://localhost/cgi-bin/soap.cgi'>. If you +want to execute C at run-time, put it in C: + + eval "use SOAP::Lite proxy => 'http://localhost/cgi-bin/soap.cgi'; 1" or die; + +Or alternatively, + + SOAP::Lite->self->proxy('http://localhost/cgi-bin/soap.cgi'); + +=head2 SETTING MAXIMUM MESSAGE SIZE + +One feature of C is the ability to control the maximum size of a +message a SOAP::Lite server will be allowed to process. To control this +feature simply define C<$SOAP::Constants::MAX_CONTENT_SIZE> in your code like +so: + + use SOAP::Transport::HTTP; + use MIME::Entity; + $SOAP::Constants::MAX_CONTENT_SIZE = 10000; + SOAP::Transport::HTTP::CGI + ->dispatch_to('TemperatureService') + ->handle; + +=head2 IN/OUT, OUT PARAMETERS AND AUTOBINDING + +C gives you access to all parameters (both in/out and out) and +also does some additional work for you. Lets consider following example: + + + name1 + name2 + name3 + + +In that case: + + $result = $r->result; # gives you 'name1' + $paramout1 = $r->paramsout; # gives you 'name2', because of scalar context + $paramout1 = ($r->paramsout)[0]; # gives you 'name2' also + $paramout2 = ($r->paramsout)[1]; # gives you 'name3' + +or + + @paramsout = $r->paramsout; # gives you ARRAY of out parameters + $paramout1 = $paramsout[0]; # gives you 'res2', same as ($r->paramsout)[0] + $paramout2 = $paramsout[1]; # gives you 'res3', same as ($r->paramsout)[1] + +Generally, if server returns C you will get C<1> as the result +and C<2> and C<3> as out parameters. + +If the server returns C you will get an ARRAY reference from +C and C from C. + +Results can be arbitrary complex: they can be an array references, they can be +objects, they can be anything and still be returned by C . If only +one parameter is returned, C will return C. + +Furthermore, if you have in your output parameters a parameter with the same +signature (name+type) as in the input parameters this parameter will be mapped +into your input automatically. For example: + +B: + + sub mymethod { + shift; # object/class reference + my $param1 = shift; + my $param2 = SOAP::Data->name('myparam' => shift() * 2); + return $param1, $param2; + } + +B: + + $a = 10; + $b = SOAP::Data->name('myparam' => 12); + $result = $soap->mymethod($a, $b); + +After that, C<< $result == 10 and $b->value == 24 >>! Magic? Sort of. + +Autobinding gives it to you. That will work with objects also with one +difference: you do not need to worry about the name and the type of object +parameter. Consider the C example (F +and F): + +B: + + package My::PingPong; + + sub new { + my $self = shift; + my $class = ref($self) || $self; + bless {_num=>shift} => $class; + } + + sub next { + my $self = shift; + $self->{_num}++; + } + +B: + + use SOAP::Lite +autodispatch => + uri => 'urn:', + proxy => 'http://localhost/'; + + my $p = My::PingPong->new(10); # $p->{_num} is 10 now, real object returned + print $p->next, "\n"; # $p->{_num} is 11 now!, object autobinded + +=head2 STATIC AND DYNAMIC SERVICE DEPLOYMENT + +Let us scrutinize the deployment process. When designing your SOAP server you +can consider two kind of deployment: B and B. For both, +static and dynamic, you should specify C, C, +C or C when creating Cing the SOAP::Lite module. The +difference between static and dynamic deployment is that in case of 'dynamic', +any module which is not present will be loaded on demand. See the +L section for detailed description. + +When statically deploying a SOAP Server, you need to know all modules handling +SOAP requests before. + +Dynamic deployment allows extending your SOAP Server's interface by just +installing another module into the dispatch_to path (see below). + +=head3 STATIC DEPLOYMENT EXAMPLE + + use SOAP::Transport::HTTP; + use My::Examples; # module is preloaded + + SOAP::Transport::HTTP::CGI + # deployed module should be present here or client will get + # 'access denied' + -> dispatch_to('My::Examples') + -> handle; + +For static deployment you should specify the MODULE name directly. + +You should also use static binding when you have several different classes in +one file and want to make them available for SOAP calls. + +=head3 DYNAMIC DEPLOYMENT EXAMPLE + + use SOAP::Transport::HTTP; + # name is unknown, module will be loaded on demand + + SOAP::Transport::HTTP::CGI + # deployed module should be present here or client will get 'access denied' + -> dispatch_to('/Your/Path/To/Deployed/Modules', 'My::Examples') + -> handle; + +For dynamic deployment you can specify the name either directly (in that case +it will be Cd without any restriction) or indirectly, with a PATH. In +that case, the ONLY path that will be available will be the PATH given to the +dispatch_to() method). For information how to handle this situation see +L section. + +=head3 SUMMARY + + dispatch_to( + # dynamic dispatch that allows access to ALL modules in specified directory + PATH/TO/MODULES + # 1. specifies directory + # -- AND -- + # 2. gives access to ALL modules in this directory without limits + + # static dispatch that allows access to ALL methods in particular MODULE + MODULE + # 1. gives access to particular module (all available methods) + # PREREQUISITES: + # module should be loaded manually (for example with 'use ...') + # -- OR -- + # you can still specify it in PATH/TO/MODULES + + # static dispatch that allows access to particular method ONLY + MODULE::method + # same as MODULE, but gives access to ONLY particular method, + # so there is not much sense to use both MODULE and MODULE::method + # for the same MODULE + ); + +In addition to this C also supports an experimental syntax that +allows you to bind a specific URL or SOAPAction to a CLASS/MODULE or object. + +For example: + + dispatch_with({ + URI => MODULE, # 'http://www.soaplite.com/' => 'My::Class', + SOAPAction => MODULE, # 'http://www.soaplite.com/method' => 'Another::Class', + URI => object, # 'http://www.soaplite.com/obj' => My::Class->new, + }) + +C is checked before C. You may use both the C +and C methods in the same server, but note that +C has a higher order of precedence. C will be +checked only after C and C has been checked. + +See also: +L, +L + +=head2 COMPRESSION + +C provides you option to enable transparent compression over the +wire. Compression can be enabled by specifying a threshold value (in the form +of kilobytes) for compression on both the client and server sides: + +I + +B + + print SOAP::Lite + ->uri('http://localhost/My/Parameters') + ->proxy('http://localhost/', options => {compress_threshold => 10000}) + ->echo(1 x 10000) + ->result; + +B + + my $server = SOAP::Transport::HTTP::CGI + ->dispatch_to('My::Parameters') + ->options({compress_threshold => 10000}) + ->handle; + +For more information see L in +L. + +=head1 SECURITY + +For security reasons, the exisiting path for Perl modules (C<@INC>) will be +disabled once you have chosen dynamic deployment and specified your own +C. If you wish to access other modules in your included package you +have several options: + +=over 4 + +=item 1 + +Switch to static linking: + + use MODULE; + $server->dispatch_to('MODULE'); + +Which can also be useful when you want to import something specific from the +deployed modules: + + use MODULE qw(import_list); + +=item 2 + +Change C to C. The path is only unavailable during the +initialization phase. It is available once more during execution. Therefore, +if you utilize C somewhere in your package, it will work. + +=item 3 + +Wrap C in an C block: + + eval 'use MODULE qw(import_list)'; die if $@; + +=item 4 + +Set your include path in your package and then specify C. Don't forget to +put C<@INC> in a C block or it won't work. For example, + + BEGIN { @INC = qw(my_directory); use MODULE } + +=back + +=head1 INTEROPERABILITY + +=head2 Microsoft .NET client with SOAP::Lite Server + +In order to use a .NET client with a SOAP::Lite server, be sure you use fully +qualified names for your return values. For example: + + return SOAP::Data->name('myname') + ->type('string') + ->uri($MY_NAMESPACE) + ->value($output); + +In addition see comment about default incoding in .NET Web Services below. + +=head2 SOAP::Lite client with a .NET server + +If experiencing problems when using a SOAP::Lite client to call a .NET Web +service, it is recommended you check, or adhere to all of the following +recommendations: + +=over 4 + +=item Declare a proper soapAction in your call + +For example, use +C. + +=item Disable charset definition in Content-type header + +Some users have said that Microsoft .NET prefers the value of +the Content-type header to be a mimetype exclusively, but SOAP::Lite specifies +a character set in addition to the mimetype. This results in an error similar +to: + + Server found request content type to be 'text/xml; charset=utf-8', + but expected 'text/xml' + +To turn off this behavior specify use the following code: + + use SOAP::Lite; + $SOAP::Constants::DO_NOT_USE_CHARSET = 1; + # The rest of your code + +=item Use fully qualified name for method parameters + +For example, the following code is preferred: + + SOAP::Data->name(Query => 'biztalk') + ->uri('http://tempuri.org/') + +As opposed to: + + SOAP::Data->name('Query' => 'biztalk') + +=item Place method in default namespace + +For example, the following code is preferred: + + my $method = SOAP::Data->name('add') + ->attr({xmlns => 'http://tempuri.org/'}); + my @rc = $soap->call($method => @parms)->result; + +As opposed to: + + my @rc = $soap->call(add => @parms)->result; + # -- OR -- + my @rc = $soap->add(@parms)->result; + +=item Disable use of explicit namespace prefixes + +Some user's have reported that .NET will simply not parse messages that use +namespace prefixes on anything but SOAP elements themselves. For example, the +following XML would not be parsed: + + + + + + + +SOAP::Lite allows users to disable the use of explicit namespaces through the +C method. For example, the following code: + + $som = SOAP::Lite->uri('urn:MyURI') + ->proxy($HOST) + ->use_prefix(0) + ->myMethod(); + +Will result in the following XML, which is more pallatable by .NET: + + + + + + + +=item Modify your .NET server, if possible + +Stefan Pharies : + +SOAP::Lite uses the SOAP encoding (section 5 of the soap 1.1 spec), and +the default for .NET Web Services is to use a literal encoding. So +elements in the request are unqualified, but your service expects them to +be qualified. .Net Web Services has a way for you to change the expected +message format, which should allow you to get your interop working. +At the top of your class in the asmx, add this attribute (for Beta 1): + + [SoapService(Style=SoapServiceStyle.RPC)] + +Another source said it might be this attribute (for Beta 2): + + [SoapRpcService] + +Full Web Service text may look like: + + <%@ WebService Language="C#" Class="Test" %> + using System; + using System.Web.Services; + using System.Xml.Serialization; + + [SoapService(Style=SoapServiceStyle.RPC)] + public class Test : WebService { + [WebMethod] + public int add(int a, int b) { + return a + b; + } + } + +Another example from Kirill Gavrylyuk : + +"You can insert [SoapRpcService()] attribute either on your class or on +operation level". + + <%@ WebService Language=CS class="DataType.StringTest"%> + + namespace DataType { + + using System; + using System.Web.Services; + using System.Web.Services.Protocols; + using System.Web.Services.Description; + + [SoapRpcService()] + public class StringTest: WebService { + [WebMethod] + [SoapRpcMethod()] + public string RetString(string x) { + return(x); + } + } + } + +Example from Yann Christensen : + + using System; + using System.Web.Services; + using System.Web.Services.Protocols; + + namespace Currency { + [WebService(Namespace="http://www.yourdomain.com/example")] + [SoapRpcService] + public class Exchange { + [WebMethod] + public double getRate(String country, String country2) { + return 122.69; + } + } + } + +=back + +Special thanks goes to the following people for providing the above +description and details on .NET interoperability issues: + +Petr Janata , + +Stefan Pharies , + +Brian Jepson , and others + +=head1 TROUBLESHOOTING + +=over 4 + +=item SOAP::Lite serializes "18373" as an integer, but I want it to be a string! + +SOAP::Lite guesses datatypes from the content provided, using a set of +common-sense rules. These rules are not 100% reliable, though they fit for +most data. + +You may force the type by passing a SOAP::Data object with a type specified: + + my $proxy = SOAP::Lite->proxy('http://www.example.org/soapservice'); + my $som = $proxy->myMethod( + SOAP::Data->name('foo')->value(12345)->type('string') + ); + +You may also change the precedence of the type-guessing rules. Note that this +means fiddling with SOAP::Lite's internals - this may not work as +expected in future versions. + +The example above forces everything to be encoded as string (this is because +the string test is normally last and allways returns true): + + my @list = qw(-1 45 foo bar 3838); + my $proxy = SOAP::Lite->uri($uri)->proxy($proxyUrl); + $proxy->serializer->typelookup->{string}->[0] = 0; + $proxy->myMethod(\@list); + +See L for more details. + +=item C<+autodispatch> doesn't work in Perl 5.8 + +There is a bug in Perl 5.8's C functionality that +prevents the C<+autodispatch> functionality from working properly. The +workaround is to use C instead. Where you might normally do +something like this: + + use Some::Module; + use SOAP::Lite +autodispatch => + uri => 'urn:Foo' + proxy => 'http://...'; + +You would do something like this: + + use SOAP::Lite dispatch_from(Some::Module) => + uri => 'urn:Foo' + proxy => 'http://...'; + +=item Problems using SOAP::Lite's COM Interface + +=over + +=item Can't call method "server" on undefined value + +You probably did not register F using C + +=item Failed to load PerlCtrl Runtime + +It is likely that you have install Perl in two different locations and the +location of ActiveState's Perl is not the first instance of Perl specified +in your PATH. To rectify, rename the directory in which the non-ActiveState +Perl is installed, or be sure the path to ActiveState's Perl is specified +prior to any other instance of Perl in your PATH. + +=back + +=item Dynamic libraries are not found + +If you are using the Apache web server, and you are seeing something like the +following in your webserver log file: + + Can't load '/usr/local/lib/perl5/site_perl/.../XML/Parser/Expat/Expat.so' + for module XML::Parser::Expat: dynamic linker: /usr/local/bin/perl: + libexpat.so.0 is NEEDED, but object does not exist at + /usr/local/lib/perl5/.../DynaLoader.pm line 200. + +Then try placing the following into your F file and see if it +fixes your problem. + + + PassEnv LD_LIBRARY_PATH + + +=item SOAP client reports "500 unexpected EOF before status line seen + +See L + +=item Apache is crashing with segfaults + +Using C (or L) in combination with mod_perl +causes random segmentation faults in httpd processes. To fix, try configuring +Apache with the following: + + RULE_EXPAT=no + +If you are using Apache 1.3.20 and later, try configuring Apache with the +following option: + + ./configure --disable-rule=EXPAT + +See http://archive.covalent.net/modperl/2000/04/0185.xml for more details and +lot of thanks to Robert Barta for explaining this weird +behavior. + +If this doesn't address the problem, you may wish to try C<-Uusemymalloc>, +or a similar option in order to instruct Perl to use the system's own C. + +Thanks to Tim Bunce . + +=item CGI scripts do not work under Microsoft Internet Information Server (IIS) + +CGI scripts may not work under IIS unless scripts use the C<.pl> extension, +opposed to C<.cgi>. + +=item Java SAX parser unable to parse message composed by SOAP::Lite + +In some cases SOAP messages created by C may not be parsed +properly by a SAX2/Java XML parser. This is due to a known bug in +C. This bug manifests itself when an +attribute in an XML element occurs prior to the XML namespace declaration on +which it depends. However, according to the XML specification, the order of +these attributes is not significant. + +http://www.megginson.com/SAX/index.html + +Thanks to Steve Alpert (Steve_Alpert@idx.com) for pointing on it. + +=back + +=head1 PERFORMANCE + +=over 4 + +=item Processing of XML encoded fragments + +C is based on L which is basically wrapper around +James Clark's expat parser. Expat's behavior for parsing XML encoded string +can affect processing messages that have lot of encoded entities, like XML +fragments, encoded as strings. Providing low-level details, parser will call +char() callback for every portion of processed stream, but individually for +every processed entity or newline. It can lead to lot of calls and additional +memory manager expenses even for small messages. By contrast, XML messages +which are encoded as base64Binary, don't have this problem and difference in +processing time can be significant. For XML encoded string that has about 20 +lines and 30 tags, number of call could be about 100 instead of one for +the same string encoded as base64Binary. + +Since it is parser's feature there is NO fix for this behavior (let me know +if you find one), especially because you need to parse message you already +got (and you cannot control content of this message), however, if your are +in charge for both ends of processing you can switch encoding to base64 on +sender's side. It will definitely work with SOAP::Lite and it B work with +other toolkits/implementations also, but obviously I cannot guarantee that. + +If you want to encode specific string as base64, just do +C<< SOAP::Data->type(base64 => $string) >> either on client or on server +side. If you want change behavior for specific instance of SOAP::Lite, you +may subclass C, override C method that is +responsible for string encoding (take a look into C) and +specify B serializer class for your SOAP::Lite object with: + + my $soap = new SOAP::Lite + serializer => My::Serializer->new, + ..... other parameters + +or on server side: + + my $server = new SOAP::Transport::HTTP::Daemon # or any other server + serializer => My::Serializer->new, + ..... other parameters + +If you want to change this behavior for B instances of SOAP::Lite, just +substitute C method with C somewhere in your +code B C and B actual processing/sending: + + *SOAP::Serializer::as_string = \&SOAP::XMLSchema2001::Serializer::as_base64Binary; + +Be warned that last two methods will affect B strings and convert them +into base64 encoded. It doesn't make any difference for SOAP::Lite, but it +B make a difference for other toolkits. + +=back + +=head1 BUGS AND LIMITATIONS + +=over 4 + +=item * + +No support for multidimensional, partially transmitted and sparse arrays +(however arrays of arrays are supported, as well as any other data structures, +and you can add your own implementation with SOAP::Data). + +=item * + +Limited support for WSDL schema. + +=item * + +XML::Parser::Lite relies on Unicode support in Perl and doesn't do entity decoding. + +=item * + +Limited support for mustUnderstand and Actor attributes. + +=back + +=head1 PLATFORM SPECIFICS + +=over 4 + +=item MacOS + +Information about XML::Parser for MacPerl could be found here: + +http://bumppo.net/lists/macperl-modules/1999/07/msg00047.html + +Compiled XML::Parser for MacOS could be found here: + +http://www.perl.com/CPAN-local/authors/id/A/AS/ASANDSTRM/XML-Parser-2.27-bin-1-MacOS.tgz + +=back + +=head1 RELATED MODULES + +=head2 Transport Modules + +SOAP::Lite allows to add support for additional transport protocols, or +server handlers, via separate modules implementing the SOAP::Transport::* +interface. The following modules are available from CPAN: + +=over + +=item * SOAP-Transport-HTTP-Nginx + +L provides a transport module for nginx () + +=back + +=head1 AVAILABILITY + +You can download the latest version SOAP::Lite for Unix or SOAP::Lite for +Win32 from the following sources: + + * CPAN: http://search.cpan.org/search?dist=SOAP-Lite + * Sourceforge: http://sourceforge.net/projects/soaplite/ + +PPM packages are also available from sourceforge. + +You are welcome to send e-mail to the maintainers of SOAP::Lite with your +comments, suggestions, bug reports and complaints. + +=head1 ACKNOWLEDGEMENTS + +Special thanks to Randy J. Ray, author of +I, who has contributed greatly to the +documentation effort of SOAP::Lite. + +Special thanks to O'Reilly publishing which has graciously allowed SOAP::Lite +to republish and redistribute the SOAP::Lite reference manual found in +Appendix B of I. + +And special gratitude to all the developers who have contributed patches, +ideas, time, energy, and help in a million different forms to the development +of this software. + +=head1 HACKING + +SOAP::Lite's development takes place on sourceforge.net. + +There's a subversion repository set up at + + https://soaplite.svn.sourceforge.net/svnroot/soaplite/ + +=head1 REPORTING BUGS + +Please report all suspected SOAP::Lite bugs using Sourceforge. This ensures +proper tracking of the issue and allows you the reporter to know when something +gets fixed. + +http://sourceforge.net/tracker/?group_id=66000&atid=513017 + +=head1 COPYRIGHT + +Copyright (C) 2000-2007 Paul Kulchenko. All rights reserved. + +Copyright (C) 2007-2008 Martin Kutter + +=head1 LICENSE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +This text and all associated documentation for this library is made available +under the Creative Commons Attribution-NoDerivs 2.0 license. +http://creativecommons.org/licenses/by-nd/2.0/ + +=head1 AUTHORS + +Paul Kulchenko (paulclinger@yahoo.com) + +Randy J. Ray (rjray@blackperl.com) + +Byrne Reese (byrne@majordojo.com) + +Martin Kutter (martin.kutter@fen-net.de) + +=cut diff --git a/Slim/Plugin/UPnP/lib/SOAP/Lite/Deserializer/XMLSchemaSOAP1_1.pm b/Slim/Plugin/UPnP/lib/SOAP/Lite/Deserializer/XMLSchemaSOAP1_1.pm new file mode 100644 index 00000000000..42b9ff95725 --- /dev/null +++ b/Slim/Plugin/UPnP/lib/SOAP/Lite/Deserializer/XMLSchemaSOAP1_1.pm @@ -0,0 +1,33 @@ +package SOAP::Lite::Deserializer::XMLSchemaSOAP1_1; +use strict; + +sub anyTypeValue { 'ur-type' } + +sub as_boolean { + shift; + my $value = shift; + $value eq '1' || $value eq 'true' + ? 1 + : $value eq '0' || $value eq 'false' + ? 0 + : die "Wrong boolean value '$value'\n" +} + +sub as_base64 { shift; require MIME::Base64; MIME::Base64::decode_base64(shift) } + +sub as_ur_type { $_[1] } + +sub as_anyURI { $_[1] } + +BEGIN { + no strict 'refs'; + for my $method (qw( + string float double decimal timeDuration recurringDuration uriReference + integer nonPositiveInteger negativeInteger long int short byte + nonNegativeInteger unsignedLong unsignedInt unsignedShort unsignedByte + positiveInteger timeInstant time timePeriod date month year century + recurringDate recurringDay language + )) { my $name = 'as_' . $method; *$name = sub { $_[1] } } +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/lib/SOAP/Lite/Deserializer/XMLSchemaSOAP1_2.pm b/Slim/Plugin/UPnP/lib/SOAP/Lite/Deserializer/XMLSchemaSOAP1_2.pm new file mode 100644 index 00000000000..3516dd78065 --- /dev/null +++ b/Slim/Plugin/UPnP/lib/SOAP/Lite/Deserializer/XMLSchemaSOAP1_2.pm @@ -0,0 +1,24 @@ +package SOAP::Lite::Deserializer::XMLSchemaSOAP1_2; +use SOAP::Lite::Deserializer::XMLSchemaSOAP1_1; + +sub anyTypeValue { 'anyType' } + +sub as_boolean; *as_boolean = \&SOAP::Lite::Deserializer::XMLSchemaSOAP1_1::as_boolean; +sub as_base64 { shift; require MIME::Base64; MIME::Base64::decode_base64(shift) } + +BEGIN { + no strict 'refs'; + for my $method (qw( + anyType + string float double decimal dateTime timePeriod gMonth gYearMonth gYear + century gMonthDay gDay duration recurringDuration anyURI + language integer nonPositiveInteger negativeInteger long int short byte + nonNegativeInteger unsignedLong unsignedInt unsignedShort unsignedByte + positiveInteger date time dateTime + )) { + my $name = 'as_' . $method; + *$name = sub { $_[1] }; + } +} + +1; \ No newline at end of file diff --git a/Slim/Plugin/UPnP/lib/SOAP/Lite/Utils.pm b/Slim/Plugin/UPnP/lib/SOAP/Lite/Utils.pm new file mode 100644 index 00000000000..1470f1539d8 --- /dev/null +++ b/Slim/Plugin/UPnP/lib/SOAP/Lite/Utils.pm @@ -0,0 +1,29 @@ +package SOAP::Lite::Utils; +use strict; + +sub import { + my $caller = caller(); + no strict qw(refs); + *{ "$caller\::__mk_accessors" } = \&__mk_accessors; +} + +sub __mk_accessors { + my ($class, @method_from) = @_; + no strict 'refs'; + for my $method ( @method_from ) { + my $field = '_' . $method; + *{ "$class\::$method" } = sub { + my $self = ref $_[0] ? shift : shift->new(); + if (@_) { + $self->{$field} = shift; + return $self + } + return $self->{$field}; + } + } +} + + +1; + +__END__ diff --git a/Slim/Plugin/UPnP/lib/SOAP/Packager.pm b/Slim/Plugin/UPnP/lib/SOAP/Packager.pm new file mode 100644 index 00000000000..77807ef9c9c --- /dev/null +++ b/Slim/Plugin/UPnP/lib/SOAP/Packager.pm @@ -0,0 +1,554 @@ +# ====================================================================== +# +# Copyright (C) 2000-2004 Paul Kulchenko (paulclinger@yahoo.com) +# SOAP::Lite is free software; you can redistribute it +# and/or modify it under the same terms as Perl itself. +# +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Plugin/UPnP/lib/SOAP/Packager.pm 75368 2010-12-16T04:09:11.731914Z andy $ +# +# ====================================================================== + +package SOAP::Packager; + +use strict; +use vars; + +our $VERSION = 0.712; +our $SUPPORTED_TYPES = { }; + +sub BEGIN { + no strict 'refs'; + for my $method ( qw(parser headers_http persist_parts) ) { + my $field = '_' . $method; + *$method = sub { + my $self = shift; + if (@_) { $self->{$field} = shift; return $self } + return $self->{$field}; + } + } +} + +sub new { + my($class) = shift; + my(%params) = @_; + bless { + "_parts" => [ ], + "_parser" => undef, + "_persist_parts" => 0, + }, $class; +} + +sub is_supported_part { + my $self = shift; + return $SUPPORTED_TYPES->{ref $_[0]}; +} + +sub parts { + my $self = shift; + if (@_) { + $self->{'_parts'} = shift; + } + return $self->{'_parts'}; +} + +# This is a static method that helps find the right Packager +sub find_packager { + # TODO - Input: + # * the mimetype of the data to be decoded raw data that needs + # * the data to be decoded + # Returns: + # * the proper SOAP::Packager instance +} + +sub push_part { + my $self = shift; + my ($part) = @_; + push @{$self->{'_parts'}}, $part; +} + +sub package { + # do nothing + die "SOAP::Packager::package() must be implemented"; +} + +sub unpackage { + my $self = shift; + $self->{'_parts'} = [] if !$self->persist_parts; # experimental +} + +# ====================================================================== + +package SOAP::Packager::MIME; + +use strict; +use vars qw(@ISA); +@ISA = qw(SOAP::Packager); + +sub BEGIN { + no strict 'refs'; + for my $method ( qw(transfer_encoding env_id env_location) ) { + my $field = '_' . $method; + *$method = sub { + my $self = shift; + if (@_) { $self->{$field} = shift; return $self } + return $self->{$field}; + } + } +} + +sub new { + my ($classname) = @_; + my $self = SOAP::Packager::new(@_); + $self->{'_content_encoding'} = '8bit'; + $self->{'_env_id'} = ''; + $self->{'_env_location'} = '/main_envelope'; + bless $self, $classname; + $SOAP::Packager::SUPPORTED_TYPES->{"MIME::Entity"} = 1; + return $self; +} + +sub initialize_parser { + my $self = shift; + eval "require MIME::Parser;"; + die "Could not find MIME::Parser - is MIME::Tools installed? Aborting." if $@; + $self->{'_parser'} = MIME::Parser->new; + $self->{'_parser'}->output_to_core('ALL'); + $self->{'_parser'}->tmp_to_core(1); + $self->{'_parser'}->ignore_errors(1); +} + +sub generate_random_string { + my ($self,$len) = @_; + my @chars=('a'..'z','A'..'Z','0'..'9','_'); + my $random_string; + foreach (1..$len) { + $random_string .= $chars[rand @chars]; + } + return $random_string; +} + +sub get_multipart_id { + my ($id) = shift; + ($id || '') =~ /^]+)>?$/; $1 || ''; +} + +sub package { + my $self = shift; + my ($envelope,$context) = @_; + return $envelope if (!$self->parts); # if there are no parts, + # then there is nothing to do + require MIME::Entity; + local $MIME::Entity::BOUNDARY_DELIMITER = "\r\n"; + my $top = MIME::Entity->build('Type' => "Multipart/Related"); + my $soapversion = defined($context) ? $context->soapversion : '1.1'; + $top->attach('Type' => $soapversion == 1.1 ? "text/xml" : "application/soap+xml", + 'Content-Transfer-Encoding' => $self->transfer_encoding(), + 'Content-Location' => $self->env_location(), + 'Content-ID' => $self->env_id(), + 'Data' => $envelope ); + # consume the attachments that come in as input by 'shift'ing + no strict 'refs'; + while (my $part = shift(@{$self->parts})) { + $top->add_part($part); + } + # determine MIME boundary + my $boundary = $top->head->multipart_boundary; + $self->headers_http({ 'Content-Type' => 'Multipart/Related; type="text/xml"; start=""; boundary="'.$boundary.'"'}); + return $top->stringify_body; +} + +sub unpackage { + my $self = shift; + my ($raw_input,$context) = @_; + $self->SUPER::unpackage(); + + # Parse the raw input into a MIME::Entity structure. + # - fail if the raw_input is not MIME formatted + $self->initialize_parser() if !defined($self->parser); + my $entity = eval { $self->parser->parse_data($raw_input) } + or die "Something wrong with MIME message: @{[$@ || $self->parser->last_error]}\n"; + + my $env = undef; + # major memory bloat below! TODO - fix! + if (lc($entity->head->mime_type) eq 'multipart/form-data') { + $env = $self->process_form_data($entity); + } elsif (lc($entity->head->mime_type) eq 'multipart/related') { + $env = $self->process_related($entity); + } elsif (lc($entity->head->mime_type) eq 'text/xml') { + # I don't think this ever gets called. + # warn "I am somewhere in the SOAP::Packager::MIME code I didn't know I would be in!"; + $env = $entity->bodyhandle->as_string; + } else { + die "Can't handle MIME messsage with specified type (@{[$entity->head->mime_type]})\n"; + } + + # return the envelope + if ($env) { + return $env; + } elsif ($entity->bodyhandle->as_string) { + return $entity->bodyhandle->as_string; + } else { + die "No content in MIME message\n"; + } +} + +sub process_form_data { + my ($self, $entity) = @_; + my $env = undef; + foreach my $part ($entity->parts) { + my $name = $part->head->mime_attr('content-disposition.name'); + $name eq 'payload' ? + $env = $part->bodyhandle->as_string + : $self->push_part($part); + } + return $env; +} + +sub process_related { + my $self = shift; + my ($entity) = @_; + die "Multipart MIME messages MUST declare Multipart/Related content-type" + if ($entity->head->mime_attr('content-type') !~ /^multipart\/related/i); + # As it turns out, the Content-ID and start parameters are optional + # according to the MIME and SOAP specs. In the event that the head cannot + # be found, the head/root entity is used as a starting point. + # [19 Mar 2008] Modified by Feng Li + # Check optional start parameter, then optional Content-ID, then create/add + # Content-ID (the same approach as in SOAP::Lite 0.66) + + #my $start = get_multipart_id($entity->head->mime_attr('content-type.start')); + my $start = get_multipart_id($entity->head->mime_attr('content-type.start')) + || get_multipart_id($entity->parts(0)->head->mime_attr('content-id')); + + if (!defined($start) || $start eq "") { + $start = $self->generate_random_string(10); + $entity->parts(0)->head->add('content-id',$start); + } + my $location = $entity->head->mime_attr('content-location') || + 'thismessage:/'; + my $env; + foreach my $part ($entity->parts) { + next if !UNIVERSAL::isa($part => "MIME::Entity"); + + # Weird, the following use of head->get(SCALAR[,INDEX]) doesn't work as + # expected. Work around is to eliminate the INDEX. + my $pid = get_multipart_id($part->head->mime_attr('content-id')); + + # If Content-ID is not supplied, then generate a random one (HACK - because + # MIME::Entity does not do this as it should... content-id is required + # according to MIME specification) + $pid = $self->generate_random_string(10) if $pid eq ''; + my $type = $part->head->mime_type; + + # If a Content-Location header cannot be found, this will look for an + # alternative in the following MIME Header attributes + my $plocation = $part->head->get('content-location') || + $part->head->mime_attr('Content-Disposition.filename') || + $part->head->mime_attr('Content-Type.name'); + if ($start && $pid eq $start) { + $env = $part->bodyhandle->as_string; + } else { + $self->push_part($part); + } + } +# die "Can't find 'start' parameter in multipart MIME message\n" +# if @{$self->parts} > 1 && !$start; + return $env; +} + +# ====================================================================== + +package SOAP::Packager::DIME; + +use strict; +use vars qw(@ISA); +@ISA = qw(SOAP::Packager); + +sub BEGIN { + no strict 'refs'; + for my $method ( qw(foo) ) { + my $field = '_' . $method; + *$method = sub { + my $self = shift; + if (@_) { $self->{$field} = shift; return $self } + return $self->{$field}; + } + } +} + +sub new { + my ($classname) = @_; + my $self = SOAP::Packager::new(@_); + bless $self, $classname; + $SOAP::Packager::SUPPORTED_TYPES->{"DIME::Payload"} = 1; + return $self; +} + +sub initialize_parser { + my $self = shift; + print STDERR "Initializing parser\n"; + eval "require DIME::Parser;"; + die "Could not find DIME::Parser - is DIME::Tools installed? Aborting." if $@; + $self->{'_parser'} = DIME::Parser->new; +} + +sub package { + my $self = shift; + my ($envelope,$context) = @_; + return $envelope if (!$self->parts); # if there are no parts, + # then there is nothing to do + require DIME::Message; + require DIME::Payload; + my $message = DIME::Message->new; + my $top = DIME::Payload->new; + my $soapversion = defined($context) ? $context->soapversion : '1.1'; + $top->attach('MIMEType' => $soapversion == 1.1 ? + "http://schemas.xmlsoap.org/soap/envelope/" : "application/soap+xml", + 'Data' => $envelope ); + $message->add_payload($top); + # consume the attachments that come in as input by 'shift'ing + no strict 'refs'; + while (my $part = shift(@{$self->parts})) { + die "You are only allowed to add parts of type DIME::Payload to a DIME::Message" + if (!$part->isa('DIME::Payload')); +# print STDERR "Adding payload to DIME message: ".ref($part)."\n"; + $message->add_payload($part); +# print STDERR "Payload's payload is: ".${$part->print_content_data}."\n"; + } + $self->headers_http({ 'Content-Type' => 'application/dime' }); + return $message->print_data; +} + +sub unpackage { + my $self = shift; + my ($raw_input,$context) = @_; + $self->SUPER::unpackage(); + + # Parse the raw input into a DIME::Message structure. + # - fail if the raw_input is not DIME formatted + print STDERR "raw_data: $raw_input\n"; + $self->initialize_parser() if !defined($self->parser); + my $message = eval { $self->parser->parse_data(\$raw_input) } + or die "Something wrong with DIME message: @{[$@]}\n"; + + # The first payload is always the SOAP Message + # TODO - Error check + my @payloads = @{$message->{'_PAYLOADS'}}; + my $env = shift(@payloads); + my $env_str = $env->print_content_data; + print STDERR "Received this envelope: ".$env_str."\n"; + while (my $p = shift(@payloads)) { + print STDERR "Adding part to Packager\n"; + $self->push_part($p); + } + return $env_str; +} + +1; +__END__ + +=pod + +=head1 NAME + +SOAP::Packager - this class is an abstract class which allows for multiple types of packaging agents such as MIME and DIME. + +=head1 DESCRIPTION + +The SOAP::Packager class is responsible for managing a set of "parts." Parts are +additional pieces of information, additional documents, or virtually anything that +needs to be associated with the SOAP Envelope/payload. The packager then will take +these parts and encode/decode or "package"/"unpackage" them as they come and go +over the wire. + +=head1 METHODS + +=over + +=item new + +Instantiates a new instance of a SOAP::Packager. + +=item parts + +Contains an array of parts. The contents of this array and their types are completely +dependent upon the Packager being used. For example, when using MIME, the content +of this array is MIME::Entity's. + +=item push_part + +Adds a part to set of parts managed by the current instance of SOAP::Packager. + +=item parser + +Returns the parser used to parse attachments out of a data stream. + +=item headers_http + +This is a hook into the HTTP layer. It provides a way for a packager to add and/or modify +HTTP headers in a request/response. For example, most packaging layers will need to +override the Content-Type (e.g. multipart/related, or application/dime). + +=back + +=head1 ABSTRACT METHODS + +If you wish to implement your own SOAP::Packager, then the methods below must be +implemented by you according to the prescribed input and output requirements. + +=over + +=item package() + +The C subroutine takes as input the SOAP envelope in string/SCALAR form. +This will serve as the content of the root part. The packager then encapsulates the +envelope with the parts contained within C and returns the properly +encapsulated envelope in string/SCALAR form. + +=item unpackage() + +The C subroutines takes as input raw data that needs to be parsed into +a set of parts. It is responsible for extracting the envelope from the input, and +populating C with an ARRAY of parts extracted from the input. It then returns +the SOAP Envelope in string/SCALAR form so that SOAP::Lite can parse it. + +=back + +=head1 SUPPORTED PACKAGING FORMATS + +=head2 SOAP::Packager::MIME + +C utilizes L to provides the ability to send +and receive Multipart/Related and Multipart/Form-Data formatted requests and +responses. + +=head3 MIME METHODS + +The following methods are used when composing a MIME formatted message. + +=over + +=item transfer_encoding + +The value of the root part's Content-Transfer-Encoding MIME Header. Default is: 8bit. + +=item env_id + +The value of the root part's Content-Id MIME Header. Default is: . + +=item env_location + +The value of the root part's Content-Location MIME Header. Default is: /main_envelope. + +=item env_type + +The value of the root part's Content-Type MIME Header. Default is: text/xml. + +=back + +=head3 OPTIMIZING THE MIME PARSER + +The use of attachments can often result in a heavy drain on system resources depending +upon how your MIME parser is configured. For example, you can instruct the parser to +store attachments in memory, or to use temp files. Using one of the other can affect +performance, disk utilization, and/or reliability. Therefore you should consult the +following URL for optimization techniques and trade-offs: + +http://search.cpan.org/dist/MIME-tools/lib/MIME/Parser.pm#OPTIMIZING_YOUR_PARSER + +To modify the parser's configuration options consult the following code sample, +which incidentally shows how to minimize memory utilization: + + my $packager = SOAP::Packager::MIME->new; + # $packager->parser->decode_headers(1); # no difference + # $packager->parser->extract_nested_messages(1); # no difference + $packager->parser->output_to_core(0); # much less memory + $packager->parser->tmp_to_core(0); # much less memory + $packager->parser->tmp_recycling(0); # promotes faster garbage collection + $packager->parser->use_inner_files(1); # no difference + my $client = SOAP::Lite->uri($NS)->proxy($URL)->packager($packager); + $client->someMethod(); + +=head3 CLIENT SIDE EXAMPLE + +The following code sample shows how to use attachments within the context of a +SOAP::Lite client. + + #!/usr/bin/perl + use SOAP::Lite; + use MIME::Entity; + my $ent = build MIME::Entity + Type => "text/plain", + Path => "attachment.txt", + Filename => "attachment.txt", + Disposition => "attachment"; + $NS = "urn:Majordojo:TemperatureService"; + $HOST = "http://localhost/cgi-bin/soaplite.cgi"; + my $client = SOAP::Lite + ->packager(SOAP::Packager::MIME->new) + ->parts([ $ent ]) + ->uri($NS) + ->proxy($HOST); + $response = $client->c2f(SOAP::Data->name("temperature" => '100')); + print $response->valueof('//c2fResponse/foo'); + +=head3 SERVER SIDE EXAMPLE + +The following code shows how to use attachments within the context of a CGI +script. It shows how to read incoming attachments, and to return attachments to +the client. + + #!/usr/bin/perl -w + use SOAP::Transport::HTTP; + use MIME::Entity; + SOAP::Transport::HTTP::CGI + ->packager(SOAP::Packager::MIME->new) + ->dispatch_with({'urn:Majordojo:TemperatureService' => 'TemperatureService'}) + ->handle; + + BEGIN { + package TemperatureService; + use vars qw(@ISA); + @ISA = qw(Exporter SOAP::Server::Parameters); + use SOAP::Lite; + sub c2f { + my $self = shift; + my $envelope = pop; + my $temp = $envelope->dataof("//c2f/temperature"); + use MIME::Entity; + my $ent = build MIME::Entity + Type => "text/plain", + Path => "printenv", + Filename => "printenv", + Disposition => "attachment"; + # read attachments + foreach my $part (@{$envelope->parts}) { + print STDERR "soaplite.cgi: attachment found! (".ref($part).")\n"; + print STDERR "soaplite.cgi: contents => ".$part->stringify."\n"; + } + # send attachments + return SOAP::Data->name('convertedTemp' => (((9/5)*($temp->value)) + 32)), + $ent; + } + } + +=head2 SOAP::Packager::DIME + +TODO + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright (C) 2000-2004 Paul Kulchenko. All rights reserved. + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=head1 AUTHORS + +Byrne Reese (byrne@majordojo.com) + +=cut diff --git a/Slim/Plugin/UPnP/strings.txt b/Slim/Plugin/UPnP/strings.txt new file mode 100644 index 00000000000..eca5cbb1cf7 --- /dev/null +++ b/Slim/Plugin/UPnP/strings.txt @@ -0,0 +1,30 @@ +PLUGIN_UPNP_MODULE_NAME + CS Rozhraní média UPnP/DLNA + DA UPnP/DLNA-mediegrænseflade + DE UPnP/DLNA Media Interface + EN UPnP/DLNA Media Interface + ES Interfaz multimedia UPnP/DLNA + FI UPnP/DLNA Media -käyttöliittymä + FR Interface multimédia UPnP/DLNA + IT Interfaccia multimediale UPnP/DLNA + NL UPnP/DLNA Media Interface + NO UPnP/DLNA-mediegrensesnitt + PL Interfejs multimedialny UPnP/DLNA + RU Интерфейс UPnP/DLNA Media + SV Mediagränssnittet UPnP/DLNA + +PLUGIN_UPNP_MODULE_NAME_DESC + CS Přidá UPnP/DLNA AV MediaServer a MediaRenderer, a povolí přístup ostatních zařízení na místní síti. + DA Tilføjer en UPnP/DLNA AV MediaServer og MediaRenderer som giver adgang til andre enheder på det lokale netværk. + DE Fügt einen UPnP/DLNA AV MediaServer und MediaRenderer hinzu und ermöglicht so den Zugriff anderer Geräte auf das lokale Netzwerk. + EN Adds a UPnP/DLNA AV MediaServer and MediaRenderer, enabling access by other devices on the local network. + ES Agrega un MediaServer y un MediaRenderer AV UPnP/DLNA, lo que permite el acceso de otros dispositivos en la red local. + FI Lisää UPnP/DLNA AV MediaServer -palvelimen ja MediaRendererin, jolloin muiden laitteiden pääsy paikalliseen verkkoon sallitaan. + FR Ajoute un MediaServer et un MediaRenderer UPnP/DLNA AV pour permettre l'accès au réseau local à d'autres dispositifs. + IT Aggiunge un UPnP/DLNA AV MediaServer and MediaRenderer, consentendo l'accesso alla rete locale da parte di altri dispositivi. + NL Hiermee worden een UPnP/DLNA AV MediaServer en MediaRenderer toegevoegd, die zorgen voor toegang tot andere apparaten op het lokale netwerk. + NO Legger til en UPnP/DLNA AV MediaServer og MediaRenderer, slik at andre enheter på det lokale nettverket får tilgang. + PL Dodaje urządzenie MediaServer i MediaRenderer audio-wideo standardu UPnP/DLNA, umożliwiając dostęp innym urządzeniom w sieci lokalnej. + RU Добавляет UPnP/DLNA AV MediaServer и MediaRenderer, предоставляя возможность доступа с других устройств в локальной сети. + SV Lägger till en UPnP/DLNA AV MediaServer och MediaRenderer som möjliggör åtkomst för andra enheter i det lokala nätverket. + diff --git a/Slim/Plugin/UPnP/t/DLNA.t b/Slim/Plugin/UPnP/t/DLNA.t new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Slim/Plugin/UPnP/t/MediaRenderer.t b/Slim/Plugin/UPnP/t/MediaRenderer.t new file mode 100644 index 00000000000..b8ef8530cb9 --- /dev/null +++ b/Slim/Plugin/UPnP/t/MediaRenderer.t @@ -0,0 +1,1029 @@ +#!/usr/bin/perl + +use strict; +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Data::Dump qw(dump); +use JSON::RPC::Client; +use Test::More; +use LWP::Simple (); +use Net::UPnP::ControlPoint; +use Net::UPnP::AV::MediaRenderer; +use Net::UPnP::AV::MediaServer; +use XML::Simple qw(XMLin); +use GENA; +use URI; + +plan tests => 138; + +my $cp = Net::UPnP::ControlPoint->new; +my $mr; # MediaRenderer +my $cm; # ConnectionManager +my $cm_events; +my $rc; # RenderingControl +my $rc_events; +my $avt; # AVTransport +my $avt_events; +my $player; +my $res; + +print "# Searching for MediaRenderer:1...\n"; +my @dev_list = $cp->search( st => 'urn:schemas-upnp-org:device:MediaRenderer:1', mx => 1 ); +for my $dev ( @dev_list ) { + if ( $dev->getserialnumber =~ /^00:04:20:26:03:20/ ) { # test against a hardware SB + $mr = Net::UPnP::AV::MediaRenderer->new(); + $mr->setdevice($dev); + + $player = $dev->getserialnumber; + + $cm = $dev->getservicebyname('urn:schemas-upnp-org:service:ConnectionManager:1'); + $rc = $dev->getservicebyname('urn:schemas-upnp-org:service:RenderingControl:1'); + $avt = $dev->getservicebyname('urn:schemas-upnp-org:service:AVTransport:1'); + + print "# Using " . $dev->getfriendlyname . " for tests\n"; + last; + } +} + +if ( !$cm || !$rc || !$avt ) { + warn "# No MediaRenderer:1 devices found\n"; + exit; +} + +#goto TEMP; + +### Eventing + +# Setup 3 subscriptions, with a callback for the initial notify data +my $sub_count = 0; + +print "# Subscribing to ConnectionManager...\n"; +$cm_events = GENA->new( $cm->geteventsuburl, sub { + my ( $req, $props ) = @_; + $sub_count++; + + is( $req->method, 'NOTIFY', 'CM notify ok' ); + is( $req->header('Content-Length'), length($req->content), 'CM notify length ok' ); + is( $props->{SourceProtocolInfo}, '', 'CM notify SourceProtocolInfo ok' ); + is( $props->{CurrentConnectionIDs}, 0, 'CM notify CurrentConnectionIDs ok' ); + like( $props->{SinkProtocolInfo}, qr{http-get:\*:audio/mpeg:\*}, 'CM notify SinkProtocolInfo ok' ); + # XXX test DLNA extras +} ); +like( $cm_events->{sid}, qr{^uuid:[A-F0-9-]+$}, 'ConnectionManager subscribed ok' ); +GENA->wait(1); +ok( $cm_events->unsubscribe, 'ConnectionManager unsubscribed ok' ); + +print "# Subscribing to RenderingControl...\n"; +$rc_events = GENA->new( $rc->geteventsuburl, sub { + my ( $req, $props ) = @_; + $sub_count++; + + ok( $props->{LastChange}, 'RC notify LastChange ok' ); + + my $lc = XMLin( $props->{LastChange} ); + my $data = $lc->{InstanceID}; + like( $data->{Brightness}->{val}, qr/^\d+$/, 'RC notify Brightness ok' ); + like( $data->{Mute}->{val}, qr/^\d+$/, 'RC notify Mute ok' ); + is( $data->{PresetNameList}->{val}, 'FactoryDefaults', 'RC notify PresetNameList ok' ); + like( $data->{Volume}->{val}, qr/^-?\d+$/, 'RC notify Volume ok' ); +} ); +like( $rc_events->{sid}, qr{^uuid:[A-F0-9-]+$}, 'RenderingControl subscribed ok' ); +GENA->wait(1); +ok( $rc_events->unsubscribe, 'RenderingControl unsubscribed ok' ); + +=pod XXX FIXME +# Play a track, so we can properly test URI and Metadata values +my $res = _jsonrpc_get( [ 'titles', 0, 1, 'year:2000', 'tags:ldtagGpPsASeiqtymMkovrfjJnCYXRTIuwc', 'sort:tracknum' ] ); +if ( !$res->{count} ) { + warn "# No tracks found, at least 1 track from year:2000 is required\n"; + exit; +} +my $track = $res->{titles_loop}->[0]; + +_jsonrpc_get( $player, [ 'playlist', 'clear' ] ); + +print "# Subscribing to AVTransport...\n"; +$avt_events = GENA->new( $avt->geteventsuburl, sub { + my ( $req, $props ) = @_; + $sub_count++; + + ok( $props->{LastChange}, 'AVT notify LastChange ok' ); + + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + is( $e->{AVTransportURI}->{val}, '', 'AVT AVTransportURI ok' ); + is( $e->{AVTransportURIMetaData}->{val}, '', 'AVT AVTransportURIMetaData ok' ); + is( $e->{AbsoluteCounterPosition}->{val}, 0, 'AVT AbsoluteCounterPosition ok' ); + is( $e->{AbsoluteTimePosition}->{val}, '00:00:00', 'AVT AbsoluteTimePosition ok' ); + is( $e->{CurrentMediaDuration}->{val}, '00:00:00', 'AVT CurrentMediaDuration ok' ); + is( $e->{CurrentPlayMode}->{val}, 'NORMAL', 'AVT CurrentPlayMode ok' ); + is( $e->{CurrentRecordQualityMode}->{val}, 'NOT_IMPLEMENTED', 'AVT CurrentRecordQualityMode ok' ); + is( $e->{CurrentTrack}->{val}, 0, 'AVT CurrentTrack ok' ); + is( $e->{CurrentTrackDuration}->{val}, '00:00:00', 'AVT CurrentTrackDuration ok' ); + is( $e->{CurrentTrackMetaData}->{val}, '', 'AVT CurrentTrackMetaData ok' ); + is( $e->{CurrentTrackURI}->{val}, '', 'AVT CurrentTrackURI ok' ); + is( $e->{CurrentTransportActions}->{val}, 'PLAY,STOP', 'AVT CurrentTransportActions ok' ); + is( $e->{NextAVTransportURI}->{val}, '', 'AVT NextAVTransportURI ok' ); + is( $e->{NextAVTransportURIMetaData}->{val}, '', 'AVT NextAVTransportURIMetaData ok' ); + is( $e->{NumberOfTracks}->{val}, 0, 'AVT NumberOfTracks ok' ); + is( $e->{PlaybackStorageMedium}->{val}, 'NONE', 'AVT PlaybackStorageMedium ok' ); + is( $e->{PossiblePlaybackStorageMedia}->{val}, 'NONE,HDD,NETWORK,UNKNOWN', 'AVT PossiblePlaybackStorageMedia ok' ); + is( $e->{PossibleRecordQualityModes}->{val}, 'NOT_IMPLEMENTED', 'AVT PossibleRecordQualityModes ok' ); + is( $e->{PossibleRecordStorageMedia}->{val}, 'NOT_IMPLEMENTED', 'AVT PossibleRecordStorageMedia ok' ); + is( $e->{RecordMediumWriteStatus}->{val}, 'NOT_IMPLEMENTED', 'AVT RecordMediumWriteStatus ok' ); + is( $e->{RecordStorageMedium}->{val}, 'NOT_IMPLEMENTED', 'AVT RecordStorageMedium ok' ); + is( $e->{RelativeCounterPosition}->{val}, 0, 'AVT RelativeCounterPosition ok' ); + is( $e->{RelativeTimePosition}->{val}, '00:00:00', 'AVT RelativeTimePosition ok' ); + is( $e->{TransportPlaySpeed}->{val}, 1, 'AVT TransportPlaySpeed ok' ); + is( $e->{TransportState}->{val}, 'STOPPED', 'AVT TransportState ok' ); + is( $e->{TransportStatus}->{val}, 'OK', 'AVT TransportStatus ok' ); +} ); +like( $avt_events->{sid}, qr{^uuid:[A-F0-9-]+$}, 'AVTransport subscribed ok' ); + +GENA->wait(1); +$avt_events->clear_callback; + +is( $sub_count, 3, 'Eventing: 3 notifications received ok' ); + +# Get the first 2 tracks from the album that will be played +$res = _jsonrpc_get( [ 'titles', 0, 100, 'album_id:' . $track->{album_id}, 'tags:ldtagGpPsASeiqtymMkovrfjJnCYXRTIuwc', 'sort:tracknum' ] ); +my $track1 = $res->{titles_loop}->[0]; +my $track2 = $res->{titles_loop}->[1]; + +# This will trigger an AVT event +$sub_count = 0; +$avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $sub_count++; + + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + $e->{AVTransportURIMetaData} = XMLin( $e->{AVTransportURIMetaData}->{val} ); + $e->{CurrentTrackMetaData} = XMLin( $e->{CurrentTrackMetaData}->{val} ); + $e->{NextAVTransportURIMetaData} = XMLin( $e->{NextAVTransportURIMetaData}->{val} ); + + my $t1id = $track1->{id}; + my $t2id = $track2->{id}; + my $t1cid = $track1->{coverid}; + my $t2cid = $track2->{coverid}; + + like( $e->{AVTransportURI}->{val}, qr{^http://.+/music/${t1id}/download$}, 'AVT AVTransportURI change ok' ); + is( $e->{CurrentMediaDuration}->{val}, _secsToHMS($track1->{duration}), 'AVT CurrentMediaDuration change ok' ); + is( $e->{CurrentPlayMode}->{val}, 'NORMAL', 'AVT CurrentPlayMode change ok' ); + is( $e->{CurrentTrack}->{val}, 1, 'AVT CurrentTrack change ok' ); + is( $e->{CurrentTrackDuration}->{val}, _secsToHMS($track1->{duration}), 'AVT CurrentTrackDuration change ok' ); + like( $e->{CurrentTrackURI}->{val}, qr{^http://.+/music/${t1id}/download$}, 'AVT CurrentTrackURI change ok' ); + is( $e->{CurrentTransportActions}->{val}, 'PLAY,STOP,SEEK,PAUSE,NEXT,PREVIOUS', 'AVT CurrentTransportActions change ok' ); + like( $e->{NextAVTransportURI}->{val}, qr{^http://.+/music/${t2id}/download$}, 'AVT NextAVTransportURI change ok' ); + cmp_ok( $e->{NumberOfTracks}->{val}, '>=', 2, 'AVT NumberOfTracks change ok' ); + is( $e->{TransportState}->{val}, 'PLAYING', 'AVT TransportState -> PLAYING ok' ); + + ### Verify metadata values + + # AVTransportURIMetaData + my $cur = $e->{AVTransportURIMetaData}->{item}; + + # Handle possible array values + if ( ref $cur->{'dc:contributor'} eq 'ARRAY' ) { + $cur->{'dc:contributor'} = $cur->{'dc:contributor'}->[0]; + } + if ( ref $cur->{'upnp:artist'} eq 'ARRAY' ) { + $cur->{'upnp:artist'} = $cur->{'upnp:artist'}->[0]; + } + + is( $cur->{'dc:contributor'}, $track1->{artist}, 'AVT cur dc:contributor ok' ); + is( $cur->{'dc:creator'}, $track1->{artist}, 'AVT cur dc:creator ok' ); + is( $cur->{'dc:date'}, $track1->{year}, 'AVT cur dc:date ok' ); + is( $cur->{'dc:title'}, $track1->{title}, 'AVT cur dc:title ok' ); + is( $cur->{id}, "/t/${t1id}", 'AVT cur id ok' ); + is( $cur->{parentID}, '/t', 'AVT cur parentID ok' ); + my ($bitrate) = $track1->{bitrate} =~ /^(\d+)/; + is( $cur->{res}->{bitrate}, (($bitrate * 1000) / 8), 'AVT cur res@bitrate ok' ); + is( $cur->{res}->{content}, $e->{AVTransportURI}->{val}, 'AVT cur res content ok' ); + is( $cur->{res}->{duration}, _secsToHMS($track1->{duration}), 'AVT cur res@duration ok' ); + like( $cur->{res}->{protocolInfo}, qr{^http-get:\*:audio/[^:]+:\*$}, 'AVT cur res@protocolInfo ok' ); + is( $cur->{res}->{sampleFrequency}, $track1->{samplerate}, 'AVT cur res@sampleFrequency ok' ); + is( $cur->{res}->{size}, $track1->{filesize}, 'AVT cur res@size ok' ); + is( $cur->{restricted}, 1, 'AVT cur restricted ok' ); + is( $cur->{'upnp:album'}, $track1->{album}, 'AVT cur upnp:album ok' ); + like( $cur->{'upnp:albumArtURI'}, qr{^http://.+/music/${t1cid}/cover$}, 'AVT cur upnp:albumArtURI ok' ); + is( $cur->{'upnp:artist'}->{content}, $track1->{artist}, 'AVT cur upnp:artist ok' ); + like( $cur->{'upnp:artist'}->{role}, qr{^(track|album)artist$}, 'AVT cur upnp:artist@role ok' ); + is( $cur->{'upnp:class'}, 'object.item.audioItem.musicTrack', 'AVT cur upnp:class ok' ); + is( $cur->{'upnp:genre'}, $track1->{genre}, 'AVT cur upnp:genre ok' ); + is( $cur->{'upnp:originalTrackNumber'}, $track1->{tracknum}, 'AVT cur upnp:originalTrackNumber ok' ); + + # NextAVTransportURIMetaData + my $next = $e->{NextAVTransportURIMetaData}->{item}; + + # Handle possible array values + if ( ref $next->{'dc:contributor'} eq 'ARRAY' ) { + $next->{'dc:contributor'} = $next->{'dc:contributor'}->[0]; + } + if ( ref $next->{'upnp:artist'} eq 'ARRAY' ) { + $next->{'upnp:artist'} = $next->{'upnp:artist'}->[0]; + } + + is( $next->{'dc:contributor'}, $track2->{artist}, 'AVT next dc:contributor ok' ); + is( $next->{'dc:creator'}, $track2->{artist}, 'AVT next dc:creator ok' ); + is( $next->{'dc:date'}, $track2->{year}, 'AVT next dc:date ok' ); + is( $next->{'dc:title'}, $track2->{title}, 'AVT next dc:title ok' ); + is( $next->{id}, "/t/${t2id}", 'AVT next id ok' ); + is( $next->{parentID}, '/t', 'AVT next parentID ok' ); + my ($bitrate) = $track2->{bitrate} =~ /^(\d+)/; + is( $next->{res}->{bitrate}, (($bitrate * 1000) / 8), 'AVT next res@bitrate ok' ); + is( $next->{res}->{content}, $e->{NextAVTransportURI}->{val}, 'AVT next res content ok' ); + is( $next->{res}->{duration}, _secsToHMS($track2->{duration}), 'AVT next res@duration ok' ); + like( $next->{res}->{protocolInfo}, qr{^http-get:\*:audio/[^:]+:\*$}, 'AVT next res@protocolInfo ok' ); + is( $next->{res}->{sampleFrequency}, $track2->{samplerate}, 'AVT next res@sampleFrequency ok' ); + is( $next->{res}->{size}, $track2->{filesize}, 'AVT next res@size ok' ); + is( $next->{restricted}, 1, 'AVT next restricted ok' ); + is( $next->{'upnp:album'}, $track2->{album}, 'AVT next upnp:album ok' ); + like( $next->{'upnp:albumArtURI'}, qr{^http://.+/music/${t2cid}/cover$}, 'AVT next upnp:albumArtURI ok' ); + is( $next->{'upnp:artist'}->{content}, $track2->{artist}, 'AVT next upnp:artist ok' ); + like( $next->{'upnp:artist'}->{role}, qr{^(track|album)artist$}, 'AVT next upnp:artist@role ok' ); + is( $next->{'upnp:class'}, 'object.item.audioItem.musicTrack', 'AVT next upnp:class ok' ); + is( $next->{'upnp:genre'}, $track2->{genre}, 'AVT next upnp:genre ok' ); + is( $next->{'upnp:originalTrackNumber'}, $track2->{tracknum}, 'AVT next upnp:originalTrackNumber ok' ); +} ); + +# Play an album +$res = _jsonrpc_get( $player, [ 'playlistcontrol', 'cmd:load', 'album_id:' . $track->{album_id} ] ); +ok( $res->{count}, 'Played album ok' ); + +print "# Waiting for AVTransport notification...\n"; +GENA->wait(1); +ok( $avt_events->unsubscribe, 'AVT unsubscribed ok' ); + +is( $sub_count, 1, 'AVT notify count ok' ); +=cut + +### RenderingControl +print "# RenderingControl\n"; + +$rc_events = GENA->new( $rc->geteventsuburl, sub {} ); +GENA->wait(1); + +# Volume pref change eventing +{ + my $ec = 0; + my $newval; + + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{Volume}->{channel}, 'Master', 'RC volume change event channel ok' ); + is( $e->{Volume}->{val}, $newval, 'RC volume change event value ok' ); + } ); + + # Set volume to +1 or 25, to avoid setting it to the same value and getting no event + my $res = _jsonrpc_get( $player, [ 'mixer', 'volume', '?' ] ); + $newval = $res->{_volume} == 100 ? 25 : ++$res->{_volume}; + _jsonrpc_get( $player, [ 'mixer', 'volume', $newval ] ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 1, 'RC volume change notify count ok' ); +} + +# Mute pref change eventing +{ + my $ec = 0; + my $newval; + + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{Mute}->{channel}, 'Master', 'RC mute change event channel ok' ); + is( $e->{Mute}->{val}, $newval, 'RC mute change event value ok' ); + } ); + + my $res = _jsonrpc_get( $player, [ 'mixer', 'muting', '?' ] ); + $newval = $res->{_muting} == 1 ? 0 : 1; + _jsonrpc_get( $player, [ 'mixer', 'muting', $newval ] ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 1, 'RC mute change notify count ok' ); +} + +# Brightness pref change eventing +{ + my $ec = 0; + my $onval; + my $offval; + + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + if ($ec == 1) { # powerOnBrightness + is( $e->{Brightness}->{val}, $onval, 'RC powerOnBrightness change event ok' ); + } + elsif ($ec == 2) { # powerOffBrightness + is( $e->{Brightness}->{val}, $offval, 'RC powerOffBrightness change event ok' ); + } + } ); + + my $res = _jsonrpc_get( $player, [ 'playerpref', 'powerOnBrightness', '?' ] ); + $onval = $res->{_p2}; + + $res = _jsonrpc_get( $player, [ 'playerpref', 'powerOffBrightness', '?' ] ); + $offval = $res->{_p2}; + + # Turn player on and change the on brightness, will event + _jsonrpc_get( $player, [ 'power', 1 ] ); + $onval = $onval == 4 ? 1 : ++$onval; + _jsonrpc_get( $player, [ 'playerpref', 'powerOnBrightness', $onval ] ); + + # Change off brightness while player is on, will not event + $offval = $offval == 4 ? 1 : ++$offval; + _jsonrpc_get( $player, [ 'playerpref', 'powerOffBrightness', $offval ] ); + + GENA->wait(1); + + # Turn player off and change the off brightness, will event + _jsonrpc_get( $player, [ 'power', 0 ] ); + $offval = $offval == 4 ? 1 : ++$offval; + _jsonrpc_get( $player, [ 'playerpref', 'powerOffBrightness', $offval ] ); + + # Change on brightness while player is off, will not event + $onval = $onval == 4 ? 1 : ++$onval; + _jsonrpc_get( $player, [ 'playerpref', 'powerOnBrightness', $onval ] ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 2, 'RC brightness change notify count ok' ); +} + +# ListPresets +{ + my $res = _action( $rc, 'ListPresets' ); + is( $res->{CurrentPresetNameList}->{content}, 'FactoryDefaults', 'RC ListPresets ok' ); +} + +# SelectPreset +{ + my $ec = 0; + + # This changes 2 prefs but they are batched together into 1 event + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{Mute}->{val}, 0, 'RC SelectPreset mute change event ok' ); + is( $e->{Volume}->{val}, 50, 'RC SelectPreset volume change event ok' ); + } ); + + my $res = _action( $rc, 'SelectPreset', { PresetName => 'FactoryDefaults' } ); + ok( !$res->{errorCode}, 'RC SelectPreset ok' ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 1, 'RC SelectPreset change notify count ok' ); +} + +# GetBrightness +{ + my $res = _action( $rc, 'GetBrightness' ); + like( $res->{CurrentBrightness}->{content}, qr/^\d+$/, 'RC GetBrightness ok' ); +} + +# SetBrightness +{ + my $ec = 0; + my $power; + my $newval; + + my $res = _jsonrpc_get( $player, [ 'power', '?' ] ); + if ( $res->{_power} ) { + $res = _jsonrpc_get( $player, [ 'playerpref', 'powerOnBrightness', '?' ] ); + $newval = $res->{_p2} == 4 ? 1 : ++$res->{_p2}; + } + else { + $res = _jsonrpc_get( $player, [ 'playerpref', 'powerOffBrightness', '?' ] ); + $newval = $res->{_p2} == 4 ? 1 : ++$res->{_p2}; + } + + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{Brightness}->{val}, $newval, 'RC SetBrightness change event ok' ); + } ); + + $res = _action( $rc, 'SetBrightness', { DesiredBrightness => $newval } ); + ok( !$res->{errorCode}, 'RC SetBrightness ok' ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 1, 'RC SetBrightness change notify count ok' ); +} + +# GetMute +{ + my $res = _action( $rc, 'GetMute', { Channel => 'Master' } ); + like( $res->{CurrentMute}->{content}, qr/^\d+$/, 'RC GetMute ok' ); +} + +# SetMute +{ + my $ec = 0; + my $newval; + + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{Mute}->{channel}, 'Master', 'RC SetMute change event channel ok' ); + is( $e->{Mute}->{val}, $newval, 'RC SetMute change event value ok' ); + } ); + + my $res = _jsonrpc_get( $player, [ 'mixer', 'muting', '?' ] ); + $newval = $res->{_muting} == 1 ? 0 : 1; + + $res = _action( $rc, 'SetMute', { + Channel => 'Master', + DesiredMute => $newval, + } ); + ok( !$res->{errorCode}, 'RC SetMute ok' ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 1, 'RC SetMute change notify count ok' ); +} + +# GetVolume +{ + my $res = _action( $rc, 'GetVolume', { Channel => 'Master' } ); + like( $res->{CurrentVolume}->{content}, qr/^\d+$/, 'RC GetVolume ok' ); +} + +# SetVolume +{ + my $ec = 0; + my $newval; + + $rc_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{Volume}->{channel}, 'Master', 'RC SetVolume change event channel ok' ); + is( $e->{Volume}->{val}, $newval, 'RC SetVolume change event value ok' ); + } ); + + # Set volume to +1 or 25, to avoid setting it to the same value and getting no event + my $res = _jsonrpc_get( $player, [ 'mixer', 'volume', '?' ] ); + $newval = $res->{_volume} == 100 ? 25 : ++$res->{_volume}; + + $res = _action( $rc, 'SetVolume', { + Channel => 'Master', + DesiredVolume => $newval, + } ); + ok( !$res->{errorCode}, 'RC SetVolume ok' ); + + GENA->wait(1); + $rc_events->clear_callback; + + is( $ec, 1, 'RC SetVolume change notify count ok' ); +} + +$rc_events->unsubscribe; + +### AVTransport +#TEMP: +print "# AVTransport\n"; + +# Find a non-SBS MediaServer we will stream from +my $cd; + +print "# Searching for MediaServer:1...\n"; +my @dev_list = $cp->search( st => 'urn:schemas-upnp-org:device:MediaServer:1', mx => 1 ); +for my $dev ( @dev_list ) { + if ( $dev->getmodelname !~ /^Logitech Media Server/ ) { + my $ms = Net::UPnP::AV::MediaServer->new(); + $ms->setdevice($dev); + + $cd = $dev->getservicebyname('urn:schemas-upnp-org:service:ContentDirectory:1'); + + # Require the Search method on this server + my $ctluri = URI->new($cd->getposturl); + my $scpduri = $cd->getscpdurl; + if ( $scpduri !~ /^http/ ) { + if ( $scpduri !~ m{^/} ) { + $scpduri = '/' . $scpduri; + } + $scpduri = 'http://' . $ctluri->host_port . $scpduri; + } + my $scpd = LWP::Simple::get($scpduri); + next unless $scpd =~ /SearchCriteria/; + + print "# Using " . $dev->getfriendlyname . " for AVTransport tests\n"; + last; + } +} +if ( !$cd ) { + warn "# No MediaServer:1 devices that support Search found, cannot continue\n"; + exit; +} + +# Find 2 audioItem items on this server +$res = _action( $cd, 'Search', { + ContainerID => 0, + SearchCriteria => 'upnp:class derivedfrom "object.item.audioItem" and @refID exists false', + Filter => '*', + StartingIndex => 0, + RequestedCount => 2, + SortCriteria => '', +} ); +if ( $res->{NumberReturned} != 2 ) { + warn "# MediaServer did not return 2 audioItem items, cannot continue\n"; + exit; +} + +my ($xml1, $xml2) = $res->{Result} =~ m{()()}; + +my $item1 = XMLin($xml1); +my $item2 = XMLin($xml2); + +print "# Test track 1: " . $item1->{'dc:title'} . ' (' . $item1->{res}->{duration} . ', ' . $item1->{res}->{bitrate} . " bytes/sec)\n"; +print "# Test track 2: " . $item2->{'dc:title'} . ' (' . $item2->{res}->{duration} . ', ' . $item2->{res}->{bitrate} . " bytes/sec)\n"; + +$xml1 =~ s/\r?\n//g; # newlines break the raw data comparison +$xml2 =~ s/\r?\n//g; + +# Add DIDL-Lite wrapper +my $didl = qq{}; +$xml1 = $didl . $xml1 . ''; +$xml2 = $didl . $xml2 . ''; + +# Reset player to an empty state +_jsonrpc_get( $player, [ 'playlist', 'clear' ] ); +sleep 1; + +my $ctluri = URI->new($avt->getposturl); +my $eventuri = $avt->geteventsuburl; +if ( $eventuri !~ /^http/ ) { + if ( $eventuri !~ m{^/} ) { + $eventuri = '/' . $eventuri; + } + $eventuri = 'http://' . $ctluri->host_port . $eventuri; +} +$avt_events = GENA->new( $eventuri, sub { + my ( $req, $props ) = @_; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + # Check initial state variables + is( $e->{TransportState}->{val}, 'NO_MEDIA_PRESENT', 'AVT initial TransportState ok' ); + is( $e->{TransportStatus}->{val}, 'OK', 'AVT initial TransportStatus ok' ); + is( $e->{PlaybackStorageMedium}->{val}, 'NONE', 'AVT initial PlaybackStorageMedium ok' ); + is( $e->{RecordStorageMedium}->{val}, 'NOT_IMPLEMENTED', 'AVT initial RecordStorageMedium ok' ); + is( $e->{PossiblePlaybackStorageMedia}->{val}, 'NONE,NETWORK', 'AVT initial PossiblePlaybackStorageMedia ok' ); + is( $e->{PossibleRecordStorageMedia}->{val}, 'NOT_IMPLEMENTED', 'AVT initial PossibleRecordStorageMedia ok' ); + is( $e->{CurrentPlayMode}->{val}, 'NORMAL', 'AVT initial CurrentPlayMode ok' ); + is( $e->{TransportPlaySpeed}->{val}, 1, 'AVT initial TransportPlaySpeed ok' ); + is( $e->{RecordMediumWriteStatus}->{val}, 'NOT_IMPLEMENTED', 'AVT initial RecordMediumWriteStatus ok' ); + is( $e->{CurrentRecordQualityMode}->{val}, 'NOT_IMPLEMENTED', 'AVT initial CurrentRecordQualityMode ok' ); + is( $e->{PossibleRecordQualityModes}->{val}, 'NOT_IMPLEMENTED', 'AVT initial PossibleRecordQualityModes ok' ); + is( $e->{NumberOfTracks}->{val}, 0, 'AVT initial NumberOfTracks ok' ); + is( $e->{CurrentTrack}->{val}, 0, 'AVT initial CurrentTrack ok' ); + is( $e->{CurrentTrackDuration}->{val}, '00:00:00', 'AVT initial CurrentTrackDuration ok' ); + is( $e->{CurrentMediaDuration}->{val}, '00:00:00', 'AVT initial CurrentMediaDuration ok' ); + is( $e->{CurrentTrackMetaData}->{val}, '', 'AVT initial CurrentTrackMetaData ok' ); + is( $e->{CurrentTrackURI}->{val}, '', 'AVT initial CurrentTrackURI ok' ); + is( $e->{AVTransportURI}->{val}, '', 'AVT initial AVTransportURI ok' ); + is( $e->{AVTransportURIMetaData}->{val}, '', 'AVT initial AVTransportURIMetaData ok' ); + is( $e->{NextAVTransportURI}->{val}, '', 'AVT initial NextAVTransportURI ok' ); + is( $e->{NextAVTransportURIMetaData}->{val}, '', 'AVT initial NextAVTransportURIMetaData ok' ); + is( $e->{CurrentTransportActions}->{val}, 'Play,Stop,Pause,Seek,Next,Previous', 'AVT initial CurrentTransportActions ok' ); +} ); +GENA->wait(1); + +# SetAVTransportURI +{ + my $ec = 0; + + # The code will change the first variables, followed by TransportState, + # so this is also a test of the event batching code + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{AVTransportURI}->{val}, $item1->{res}->{content}, 'AVT SetAVTransportURI change for AVTransportURI ok' ); + is( $e->{CurrentTrackURI}->{val}, $item1->{res}->{content}, 'AVT SetAVTransportURI change for CurrentTrackURI ok' ); + is( $e->{AVTransportURIMetaData}->{val}, $xml1, 'AVT SetAVTransportURI change for AVTransportURIMetaData ok' ); + is( $e->{CurrentTrackMetaData}->{val}, $xml1, 'AVT SetAVTransportURI change for CurrentTrackMetaData ok' ); + is( $e->{NumberOfTracks}->{val}, 1, 'AVT SetAVTransportURI change for NumberOfTracks ok' ); + is( $e->{CurrentTrack}->{val}, 1, 'AVT SetAVTransportURI change for CurrentTrack ok' ); + is( $e->{CurrentMediaDuration}->{val}, $item1->{res}->{duration}, 'AVT SetAVTransportURI change for CurrentMediaDuration ok' ); + is( $e->{CurrentTrackDuration}->{val}, $item1->{res}->{duration}, 'AVT SetAVTransportURI change for CurrentTrackDuration ok' ); + is( $e->{PlaybackStorageMedium}->{val}, 'NETWORK', 'AVT SetAVTransportURI change for PlaybackStorageMedium ok' ); + is( $e->{TransportState}->{val}, 'STOPPED', 'AVT SetAVTransportURI change for TransportState ok' ); + } ); + + my $res = _action( $avt, 'SetAVTransportURI', { + InstanceID => 0, + CurrentURI => $item1->{res}->{content}, + CurrentURIMetaData => xmlEscape($xml1), + } ); + ok( !$res->{errorCode}, 'AVT SetAVTransportURI ok' ); + + GENA->wait(1); + $avt_events->clear_callback; + + is( $ec, 1, 'AVT SetAVTransportURI change notify count ok' ); + + # XXX more tests from different states: + # STOPPED -> STOPPED + # PLAYING -> PLAYING + # PAUSED -> STOPPED +} + +# SetNextAVTransportURI +{ + my $ec = 0; + + # This changes 2 values but they are batched together into 1 event + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{NextAVTransportURI}->{val}, $item2->{res}->{content}, 'AVT SetNextAVTransportURI change for NextAVTransportURI ok' ); + is( $e->{NextAVTransportURIMetaData}->{val}, $xml2, 'AVT SetNextAVTransportURI change for NextAVTransportURIMetaData ok' ); + } ); + + my $res = _action( $avt, 'SetNextAVTransportURI', { + InstanceID => 0, + NextURI => $item2->{res}->{content}, + NextURIMetaData => xmlEscape($xml2), + } ); + ok( !$res->{errorCode}, 'AVT SetNextAVTransportURI ok' ); + + GENA->wait(1); + $avt_events->clear_callback; + + is( $ec, 1, 'AVT SetNextAVTransportURI change notify count ok' ); + + # XXX test automatic transition from current -> next +} + +# GetMediaInfo +{ + my $res = _action( $avt, 'GetMediaInfo', { InstanceID => 0 } ); + + is( $res->{CurrentURI}->{content}, $item1->{res}->{content}, 'AVT GetMediaInfo CurrentURI ok' ); + is( $res->{CurrentURIMetaData}->{content}, $xml1, 'AVT GetMediaInfo CurrentURIMetaData ok' ); + is( $res->{MediaDuration}->{content}, $item1->{res}->{duration}, 'AVT GetMediaInfo MediaDuration ok' ); + is( $res->{NextURI}->{content}, $item2->{res}->{content}, 'AVT GetMediaInfo NextURI ok' ); + is( $res->{NextURIMetaData}->{content}, $xml2, 'AVT GetMediaInfo NextURIMetaData ok' ); + is( $res->{NrTracks}->{content}, 1, 'AVT GetMediaInfo NrTracks ok' ); + is( $res->{PlayMedium}->{content}, 'NETWORK', 'AVT GetMediaInfo PlayMedium ok' ); + is( $res->{RecordMedium}->{content}, 'NOT_IMPLEMENTED', 'AVT GetMediaInfo RecordMedium ok' ); + is( $res->{WriteStatus}->{content}, 'NOT_IMPLEMENTED', 'AVT GetMediaInfo WriteStatus ok' ); +} + +# GetTransportInfo +{ + my $res = _action( $avt, 'GetTransportInfo', { InstanceID => 0 } ); + + is( $res->{CurrentTransportState}->{content}, 'STOPPED', 'AVT CurrentTransportState CurrentTransportState ok' ); + is( $res->{CurrentTransportStatus}->{content}, 'OK', 'AVT GetTransportInfo CurrentTransportStatus ok' ); + is( $res->{CurrentSpeed}->{content}, 1, 'AVT GetTransportInfo CurrentSpeed ok' ); +} + +# GetPositionInfo +{ + my $res = _action( $avt, 'GetPositionInfo', { InstanceID => 0 } ); + + is( $res->{Track}->{content}, 1, 'AVT GetPositionInfo Track ok' ); + is( $res->{TrackDuration}->{content}, $item1->{res}->{duration}, 'AVT GetPositionInfo TrackDuration ok' ); + is( $res->{TrackMetaData}->{content}, $xml1, 'AVT GetPositionInfo TrackMetaData ok' ); + is( $res->{TrackURI}->{content}, $item1->{res}->{content}, 'AVT GetPositionInfo TrackURI ok' ); + is( $res->{RelTime}->{content}, '00:00:00', 'AVT GetPositionInfo RelTime ok' ); + is( $res->{AbsTime}->{content}, '00:00:00', 'AVT GetPositionInfo AbsTime ok' ); + is( $res->{RelCount}->{content}, 0, 'AVT GetPositionInfo RelCount ok' ); + is( $res->{AbsCount}->{content}, 0, 'AVT GetPositionInfo AbsCount ok' ); +} + +# GetDeviceCapabilities +{ + my $res = _action( $avt, 'GetDeviceCapabilities', { InstanceID => 0 } ); + + is( $res->{PlayMedia}->{content}, 'NONE,HDD,NETWORK,UNKNOWN', 'AVT GetDeviceCapabilities PlayMedia ok' ); + is( $res->{RecMedia}->{content}, 'NOT_IMPLEMENTED', 'AVT GetDeviceCapabilities RecMedia ok' ); + is( $res->{RecQualityModes}->{content}, 'NOT_IMPLEMENTED', 'AVT GetDeviceCapabilities RecQualityModes ok' ); +} + +# GetTransportSettings +{ + my $res = _action( $avt, 'GetTransportSettings', { InstanceID => 0 } ); + + is( $res->{PlayMode}->{content}, 'NORMAL', 'AVT GetTransportSettings PlayMode ok' ); + is( $res->{RecQualityMode}->{content}, 'NOT_IMPLEMENTED', 'AVT GetTransportSettings RecQualityMode ok' ); +} + +# Play +{ + my $ec = 0; + + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + # State goes through TRANSITIONING but it will be too fast to get evented + is( $e->{TransportState}->{val}, 'PLAYING', 'AVT Play TransportState change to PLAYING ok' ); + } ); + + my $res = _action( $avt, 'Play', { + InstanceID => 0, + Speed => 1, + } ); + ok( !$res->{errorCode}, 'AVT Play ok' ); + + # Play a second time will be ignored, with no event sent + _action( $avt, 'Play', { + InstanceID => 0, + Speed => 1, + } ); + + GENA->wait(1); + $avt_events->clear_callback; + + is( $ec, 1, 'AVT Play notify count ok' ); + + # Verify it's now playing + $res = _action( $avt, 'GetTransportInfo', { InstanceID => 0 } ); + is( $res->{CurrentTransportState}->{content}, 'PLAYING', 'AVT Play CurrentTransportState is PLAYING ok' ); + + sleep 4; + $res = _action( $avt, 'GetPositionInfo', { InstanceID => 0 } ); + cmp_ok( $res->{AbsCount}->{content}, '>=', 1, 'AVT Play AbsCount ' . $res->{AbsCount}->{content} . ' ok' ); + cmp_ok( $res->{RelCount}->{content}, '>=', 1, 'AVT Play RelCount ' . $res->{RelCount}->{content} . ' ok' ); + like( $res->{AbsTime}->{content}, qr/^0:00:0[1234]\.\d+$/, 'AVT Play AbsTime ' . $res->{AbsTime}->{content} . ' ok' ); + like( $res->{RelTime}->{content}, qr/^0:00:0[1234]\.\d+$/, 'AVT Play RelTime ' . $res->{RelTime}->{content} . ' ok' ); +} + +# Seek +{ + print "# Note: Seek tests require accurate bitrate/duration, try using CBR MP3 files if this fails\n"; + my $ec = 0; + + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + if ($ec == 1) { + is( $e->{TransportState}->{val}, 'TRANSITIONING', 'AVT Seek TransportState change to TRANSITIONING ok' ); + } + elsif ($ec == 2) { + is( $e->{TransportState}->{val}, 'PLAYING', 'AVT Seek TransportState change to PLAYING ok' ); + } + } ); + + my $res = _action( $avt, 'Seek', { + InstanceID => 0, + Unit => 'ABS_TIME', + Target => '0:01:00.123', + } ); + ok( !$res->{errorCode}, 'AVT Seek ok' ); + + GENA->wait(2); + $avt_events->clear_callback; + + is( $ec, 2, 'AVT Seek notify count ok' ); + + # Check that the playback position changed correctly + sleep 2; + $res = _action( $avt, 'GetPositionInfo', { InstanceID => 0 } ); + cmp_ok( $res->{AbsCount}->{content}, '>=', 60, 'AVT Seek AbsCount ' . $res->{AbsCount}->{content} . ' ok' ); + cmp_ok( $res->{RelCount}->{content}, '>=', 60, 'AVT Seek RelCount ' . $res->{RelCount}->{content} . ' ok' ); + like( $res->{AbsTime}->{content}, qr/^0:01:/, 'AVT Seek AbsTime ' . $res->{AbsTime}->{content} . ' ok' ); + like( $res->{RelTime}->{content}, qr/^0:01:/, 'AVT Seek RelTime ' . $res->{RelTime}->{content} . ' ok' ); +} + +# Pause +{ + my $ec = 0; + + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + if ($ec == 1) { # pause event + is( $e->{TransportState}->{val}, 'PAUSED_PLAYBACK', 'AVT Pause TransportState change to PAUSED_PLAYBACK ok' ); + } + elsif ($ec == 2) { # play event + is( $e->{TransportState}->{val}, 'PLAYING', 'AVT Play while paused TransportState change to PLAYING ok' ); + } + } ); + + my $res = _action( $avt, 'Pause', { InstanceID => 0 } ); + ok( !$res->{errorCode}, 'AVT Pause ok' ); + + GENA->wait(1); + is( $ec, 1, 'AVT Pause notify count ok' ); + + $res = _action( $avt, 'GetTransportInfo', { InstanceID => 0 } ); + is( $res->{CurrentTransportState}->{content}, 'PAUSED_PLAYBACK', 'AVT Pause CurrentTransportState is PAUSED_PLAYBACK ok' ); + + # Play while paused + $res = _action( $avt, 'Play', { + InstanceID => 0, + Speed => 1, + } ); + ok( !$res->{errorCode}, 'AVT Play while paused ok' ); + + GENA->wait(1); + $avt_events->clear_callback; + + is( $ec, 2, 'AVT Play while paused notify count ok' ); +} + +# Stop +{ + my $ec = 0; + + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{TransportState}->{val}, 'STOPPED', 'AVT Stop TransportState change to STOPPED ok' ); + } ); + + my $res = _action( $avt, 'Stop', { InstanceID => 0 } ); + ok( !$res->{errorCode}, 'AVT Stop ok' ); + + GENA->wait(1); + $avt_events->clear_callback; + + is( $ec, 1, 'AVT Stop notify count ok' ); + + $res = _action( $avt, 'GetTransportInfo', { InstanceID => 0 } ); + is( $res->{CurrentTransportState}->{content}, 'STOPPED', 'AVT Stop CurrentTransportState is STOPPED ok' ); +} + +# Next +{ + # Next is an error with a single track + my $res = _action( $avt, 'Next', { InstanceID => 0 } ); + is( $res->{errorCode}->{content}, 711, 'AVT Next failed ok' ); +} + +# Previous +{ + # Previous is an error with a single track + my $res = _action( $avt, 'Previous', { InstanceID => 0 } ); + is( $res->{errorCode}->{content}, 711, 'AVT Previous failed ok' ); +} + +# SetPlayMode +{ + my $ec = 0; + + $avt_events->set_callback( sub { + my ( $req, $props ) = @_; + $ec++; + my $lc = XMLin( $props->{LastChange} ); + my $e = $lc->{InstanceID}; + + is( $e->{CurrentPlayMode}->{val}, 'REPEAT_ONE', 'AVT SetPlayMode CurrentPlayMode change to REPEAT_ONE ok' ); + } ); + + my $res = _action( $avt, 'SetPlayMode', { + InstanceID => 0, + NewPlayMode => 'REPEAT_ONE', + } ); + ok( !$res->{errorCode}, 'AVT SetPlayMode ok' ); + + GENA->wait(1); + $avt_events->clear_callback; + + is( $ec, 1, 'AVT SetPlayMode notify count ok' ); +} + +# XXX test SetPlayMode with playlists + +# GetCurrentTransportActions +# XXX when stopped, this should be different... +{ + my $res = _action( $avt, 'GetCurrentTransportActions', { InstanceID => 0 } ); + is( $res->{Actions}->{content}, 'Play,Stop,Pause,Seek,Next,Previous', 'AVT GetCurrentTransportActions ok' ); +} + +### XXX metadata during internal SBS file playback + +### XXX Internet Radio + +### XXX File from our own MediaServer + +### XXX playlist files + +# Reset player +#_jsonrpc_get( $player, [ 'playlist', 'clear' ] ); + +END { + $cm_events && $cm_events->unsubscribe; + $rc_events && $rc_events->unsubscribe; + $avt_events && $avt_events->unsubscribe; +} + +sub _action { + my ( $service, $action, $args ) = @_; + + $args ||= {}; + + my $res = $service->postaction($action, $args); + my $hash = XMLin( $res->gethttpresponse->getcontent ); + + if ( $res->getstatuscode == 200 ) { + return $hash->{'s:Body'}->{"u:${action}Response"}; + } + else { + return $hash->{'s:Body'}->{'s:Fault'}->{detail}; + } +} + +sub _jsonrpc_get { + my $cmd = shift; + + my $client = JSON::RPC::Client->new; + my $uri = 'http://localhost:9000/jsonrpc.js'; + + # Support optional initial player param + my $player = ''; + if ( !ref $cmd ) { + $player = $cmd; + $cmd = shift; + } + + my $res = $client->call( $uri, { method => 'slim.request', params => [ $player, $cmd ] } ); + + if ( $res && $res->is_success ) { + return $res->content->{result}; + } + + return; +} + +# seconds to H:MM:SS[.F+] +sub _secsToHMS { + my $secs = shift; + + my $elapsed = sprintf '%d:%02d:%02d', int($secs / 3600), int($secs / 60), $secs % 60; + + if ( $secs =~ /\.(\d+)$/ ) { + $elapsed .= '.' . $1; + } + + return $elapsed; +} + +sub xmlEscape { + my $text = shift; + + if ( $text =~ /[\&\<\>'"]/) { + $text =~ s/&/&/go; + $text =~ s//>/go; + $text =~ s/'/'/go; + $text =~ s/"/"/go; + } + + return $text; +} diff --git a/Slim/Plugin/UPnP/t/MediaServer.t b/Slim/Plugin/UPnP/t/MediaServer.t new file mode 100644 index 00000000000..9d5225ff40c --- /dev/null +++ b/Slim/Plugin/UPnP/t/MediaServer.t @@ -0,0 +1,1533 @@ +#!/usr/bin/perl + +use strict; +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Data::Dump qw(dump); +use GENA; +use Test::More; +use Net::UPnP::ControlPoint; +use Net::UPnP::AV::MediaServer; +use XML::Fast; + +plan tests => 262; + +# Force a server to use, in case there is more than one on the network +my $force_ip = shift; + +my $cp = Net::UPnP::ControlPoint->new; +my $ms; # MediaServer +my $cm; # ConnectionManager +my $cm_events; +my $cd; # ContentDirectory +my $cd_events; + +print "# Searching for MediaServer:1...\n"; +my @dev_list = $cp->search( st => 'urn:schemas-upnp-org:device:MediaServer:1', mx => 1 ); +for my $dev ( @dev_list ) { + if ( $dev->getmodelname =~ /Logitech Media Server/ ) { + $ms = Net::UPnP::AV::MediaServer->new(); + $ms->setdevice($dev); + + $cm = $dev->getservicebyname('urn:schemas-upnp-org:service:ConnectionManager:1'); + $cd = $dev->getservicebyname('urn:schemas-upnp-org:service:ContentDirectory:1'); + + next if $force_ip && $cm->geteventsuburl !~ /$force_ip/; + + print '# Using MediaServer: ' . $dev->getfriendlyname . "\n"; + last; + } +} + +if ( !$cm || !$cd ) { + warn "# No MediaServer:1 devices found\n"; + exit; +} + +#goto HERE; + +### Eventing + +# Setup 2 subscriptions, with a callback for the initial notify data +my $sub_count = 0; + +print "# Subscribing to ConnectionManager...\n"; +$cm_events = GENA->new( $cm->geteventsuburl, sub { + my ( $req, $props ) = @_; + $sub_count++; + + is( $req->method, 'NOTIFY', 'CM notify ok' ); + is( $req->header('Content-Length'), length($req->content), 'CM notify length ok' ); + like( $props->{SourceProtocolInfo}, qr{http-get:\*:audio/mpeg:\*}, 'CM notify SourceProtocolInfo ok' ); + is( $props->{CurrentConnectionIDs}, 0, 'CM notify CurrentConnectionIDs ok' ); + is( $props->{SinkProtocolInfo}, '', 'CM notify SinkProtocolInfo ok' ); +} ); +like( $cm_events->{sid}, qr{^uuid:[A-F0-9-]+$}, 'ConnectionManager subscribed ok' ); + +print "# Subscribing to ContentDirectory...\n"; +$cd_events = GENA->new( $cd->geteventsuburl, sub { + my ( $req, $props ) = @_; + $sub_count++; + + like( $props->{SystemUpdateID}, qr/^\d+$/, 'CD notify SystemUpdateID ok' ); +} ); +like( $cd_events->{sid}, qr{^uuid:[A-F0-9-]+$}, 'ContentDirectory subscribed ok' ); + +# Wait for notifications for each service +GENA->wait(2); + +is( $sub_count, 2, 'Eventing: 2 notifications received ok' ); + +ok( $cm_events->renew, 'CM renewed ok' ); +ok( $cd_events->renew, 'CD renewed ok' ); + +ok( $cm_events->unsubscribe, 'CM unsubscribed ok' ); +ok( $cd_events->unsubscribe, 'CD unsubscribed ok' ); + +# Renew after unsubscribe should fail +ok( !$cm_events->renew, 'CM renew after unsubscribe failed ok' ); + +### ConnectionManager + +# Invalid action +{ + my $res = _action( $cm, 'InvalidAction' ); + is( $res->{errorCode}->{t}, 401, 'CM: InvalidAction errorCode ok' ); + is( $res->{errorDescription}->{t}, 'Invalid Action', 'CM: InvalidAction errorDescription ok' ); +} + +# GetProtocolInfo +{ + my $res = _action( $cm, 'GetProtocolInfo' ); + like( $res->{Source}->{t}, qr{audio/mpeg}, 'CM: GetProtocolInfo Source ok' ); +} + +# GetCurrentConnectionIDs +{ + my $res = _action( $cm, 'GetCurrentConnectionIDs' ); + is( $res->{ConnectionIDs}->{t}, 0, 'CM: GetCurrentConnectionIDs ConnectionIDs ok' ); +} + +# GetCurrentConnectionInfo +{ + my $res = _action( $cm, 'GetCurrentConnectionInfo', { ConnectionID => 0 } ); + is( $res->{AVTransportID}->{t}, -1, 'CM: GetCurrentConnectionInfo ok' ); + + # Test invalid ConnectionID + $res = _action( $cm, 'GetCurrentConnectionInfo', { ConnectionID => 1 } ); + is( $res->{errorDescription}->{t}, 'Invalid connection reference', 'CM: GetCurrentConnectionInfo invalid ConnectionID ok' ); +} + +### ContentDirectory + +# GetSearchCapabilities +{ + my $res = _action( $cd, 'GetSearchCapabilities' ); + like( $res->{SearchCaps}->{t}, qr/dc:title/, 'CD: GetSearchCapabilities ok' ); +} + +# GetSortCapabilities +{ + my $res = _action( $cd, 'GetSortCapabilities' ); + like( $res->{SortCaps}->{t}, qr/dc:title/, 'CD: GetSortCapabilities ok' ); +} + +# GetSystemUpdateID +{ + my $res = _action( $cd, 'GetSystemUpdateID' ); + like( $res->{Id}->{t}, qr/\d+/, 'CD: GetSystemUpdateID ok' ); +} + +# XXX test triggering a SystemUpdateID change + +# Browse top-level menu +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => 0, + Filter => '*', + StartingIndex => 0, + RequestedCount => 1, + SortCriteria => '', + } ); + + is( $res->{NumberReturned}->{t}, 1, 'CD: Browse ObjectID 0 RequestedCount 1, NumberReturned ok' ); + is( $res->{TotalMatches}->{t}, 2, 'CD: Browse ObjectID 0 RequestedCount 1, TotalMatches ok' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + is( scalar @{$container}, 1, 'CD: Browse ObjectID 0 RequestedCount 1, container count ok' ); + + my $item1 = $container->[0]; + is( $item1->{'-id'}, '/music', 'CD: Browse ObjectID 0 RequestedCount 1, container 1 id ok' ); + is( $item1->{'-parentID'}, 0, 'CD: Browse ObjectID 0 RequestedCount 1, container 1 parentID ok' ); + is( $item1->{'-restricted'}, 1, 'CD: Browse ObjectID 0 RequestedCount 1, container 1 restricted ok' ); + is( $item1->{'-searchable'}, 0, 'CD: Browse ObjectID 0 RequestedCount 1, container 1 searchable ok' ); + is( $item1->{'dc:title'}, 'Music', 'CD: Browse ObjectID 0 RequestedCount 1, container 1 dc:title ok' ); + is( $item1->{'upnp:class'}, 'object.container', 'CD: Browse ObjectID 0 RequestedCount 1, container 1 upnp:class ok' ); + + # Test top-level menu metadata + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => 0, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'BrowseMetadata ObjectID 0 TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'BrowseMetadata ObjectID 0 NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, 0, 'CD: BrowseMetadata ObjectID 0, id ok' ); + is( $container->{'-parentID'}, -1, 'CD: BrowseMetadata ObjectID 0, parentID ok' ); + is( $container->{'-searchable'}, 1, 'CD: BrowseMetadata ObjectID 0, searchable ok' ); + like( $container->{'dc:title'}, qr/^Logitech Media Server/, 'CD: BrowseMetadata ObjectID 0, dc:title ok' ); +} + +# Browse music menu +{ + # Fetch first menu item only + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/music', + Filter => '*', + StartingIndex => 0, + RequestedCount => 1, + SortCriteria => '', + } ); + + is( $res->{NumberReturned}->{t}, 1, 'CD: Browse ObjectID /music RequestedCount 1, NumberReturned ok' ); + is( $res->{TotalMatches}->{t}, 7, 'CD: Browse ObjectID /music RequestedCount 1, TotalMatches ok' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + is( scalar @{$container}, 1, 'CD: Browse ObjectID /music RequestedCount 1, container count ok' ); + + my $item1 = $container->[0]; + is( $item1->{'-id'}, '/a', 'CD: Browse ObjectID /music RequestedCount 1, container 1 id ok' ); + is( $item1->{'-parentID'}, '/music', 'CD: Browse ObjectID /music RequestedCount 1, container 1 parentID ok' ); + is( $item1->{'-restricted'}, 1, 'CD: Browse ObjectID /music RequestedCount 1, container 1 restricted ok' ); + is( $item1->{'-searchable'}, 0, 'CD: Browse ObjectID /music RequestedCount 1, container 1 searchable ok' ); + is( $item1->{'dc:title'}, 'Artists', 'CD: Browse ObjectID /music RequestedCount 1, container 1 dc:title ok' ); + is( $item1->{'upnp:class'}, 'object.container', 'CD: Browse ObjectID /music RequestedCount 1, container 1 upnp:class ok' ); + + # Fetch rest of menu, with sorting + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/music', + Filter => '*', + StartingIndex => 1, + RequestedCount => 6, + SortCriteria => '+dc:title', + } ); + + is( $res->{NumberReturned}->{t}, 6, 'CD: Browse ObjectID /music RequestedCount 6, NumberReturned ok' ); + is( $res->{TotalMatches}->{t}, 7, 'CD: Browse ObjectID /music RequestedCount 6, TotalMatches ok' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $container = $menu->{'DIDL-Lite'}->{container}; + is( scalar @{$container}, 6, 'CD: Browse ObjectID /music RequestedCount 6, container count ok' ); + + # Check sorting is correct + is( $container->[0]->{'-id'}, '/a', 'CD: Browse ObjectID /music RequestedCount 6, sorted container 1 id ok' ); + is( $container->[-1]->{'-id'}, '/y', 'CD: Browse ObjectID /music RequestedCount 6, sorted container 6 id ok' ); + + # Test music menu metadata + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/music', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'BrowseMetadata ObjectID /music TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'BrowseMetadata ObjectID /music NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, '/music', 'CD: BrowseMetadata ObjectID /music, id ok' ); + is( $container->{'-parentID'}, 0, 'CD: BrowseMetadata ObjectID /music, parentID ok' ); + is( $container->{'-searchable'}, 0, 'CD: BrowseMetadata ObjectID /music, searchable ok' ); + is( $container->{'dc:title'}, 'Music', 'CD: BrowseMetadata ObjectID /music, dc:title ok' ); +} + +# Browse video menu +{ + # Fetch first menu item only + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/video', + Filter => '*', + StartingIndex => 0, + RequestedCount => 1, + SortCriteria => '', + } ); + + is( $res->{NumberReturned}->{t}, 1, 'CD: Browse ObjectID /video RequestedCount 1, NumberReturned ok' ); + is( $res->{TotalMatches}->{t}, 2, 'CD: Browse ObjectID /video RequestedCount 1, TotalMatches ok' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + is( scalar @{$container}, 1, 'CD: Browse ObjectID /video RequestedCount 1, container count ok' ); + + my $item1 = $container->[0]; + is( $item1->{'-id'}, '/v', 'CD: Browse ObjectID /video RequestedCount 1, container 1 id ok' ); + is( $item1->{'-parentID'}, '/video', 'CD: Browse ObjectID /video RequestedCount 1, container 1 parentID ok' ); + is( $item1->{'-restricted'}, 1, 'CD: Browse ObjectID /video RequestedCount 1, container 1 restricted ok' ); + is( $item1->{'-searchable'}, 0, 'CD: Browse ObjectID /video RequestedCount 1, container 1 searchable ok' ); + is( $item1->{'dc:title'}, 'Video Folder', 'CD: Browse ObjectID /video RequestedCount 1, container 1 dc:title ok' ); + is( $item1->{'upnp:class'}, 'object.container', 'CD: Browse ObjectID /video RequestedCount 1, container 1 upnp:class ok' ); + + # Fetch rest of menu, with sorting + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/video', + Filter => '*', + StartingIndex => 0, + RequestedCount => 2, + SortCriteria => '+dc:title', + } ); + + is( $res->{NumberReturned}->{t}, 2, 'CD: Browse ObjectID /video RequestedCount 2, NumberReturned ok' ); + is( $res->{TotalMatches}->{t}, 2, 'CD: Browse ObjectID /video RequestedCount 2, TotalMatches ok' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $container = $menu->{'DIDL-Lite'}->{container}; + is( scalar @{$container}, 2, 'CD: Browse ObjectID /video RequestedCount 2, container count ok' ); + + # Check sorting is correct + is( $container->[0]->{'-id'}, '/va', 'CD: Browse ObjectID /video RequestedCount 2, sorted container 1 id ok' ); + is( $container->[-1]->{'-id'}, '/v', 'CD: Browse ObjectID /video RequestedCount 2, sorted container 2 id ok' ); + + # Test video menu metadata + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/video', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'BrowseMetadata ObjectID /video TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'BrowseMetadata ObjectID /video NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, '/video', 'CD: BrowseMetadata ObjectID /video, id ok' ); + is( $container->{'-parentID'}, 0, 'CD: BrowseMetadata ObjectID /video, parentID ok' ); + is( $container->{'-searchable'}, 0, 'CD: BrowseMetadata ObjectID /video, searchable ok' ); + is( $container->{'dc:title'}, 'Video', 'CD: BrowseMetadata ObjectID /video, dc:title ok' ); +} +exit; + +# Test localized dc:title values +{ + local $ENV{ACCEPT_LANGUAGE} = 'de,en-us;q=0.7,en;q=0.3'; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/music', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '-dc:title', + } ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->[0]->{'dc:title'}, 'Wiedergabelisten', 'CD: Browse ObjectID /music Accept-Language: de, sorted container 1 ok' ); + is( $container->[-1]->{'dc:title'}, 'Alben', 'CD: Browse ObjectID /music Accept-Language: de, sorted container 7 ok' ); +} + +### /a artists menu + +# Test browsing artists menu +my $artist; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/a', + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + + # Skip Various Artists artist if it's there + $artist = $container->[0]->{'dc:title'} eq 'Various Artists' ? $container->[1] : $container->[0]; + + like( $artist->{'-id'}, qr{^/a/\d+/l$}, 'Artist container id ok' ); + is( $artist->{'-parentID'}, '/a', 'Artist container parentID ok' ); + ok( $artist->{'dc:title'}, 'Artist container dc:title ok' ); + is( $artist->{'upnp:class'}, 'object.container.person.musicArtist', 'Artist container upnp:class ok' ); + + # Test BrowseMetadata on artist item + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/a', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/a BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/a BrowseMetadata NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, '/a', '/a BrowseMetadata id ok' ); + is( $container->{'-parentID'}, '/music', '/a BrowseMetadata parentID ok' ); + is( $container->{'dc:title'}, 'Artists', '/a BrowseMetadata dc:title ok' ); + is( $container->{'upnp:class'}, 'object.container', '/a BrowseMetadata upnp:class ok' ); + + # Test BrowseMetadata on an artist + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $artist->{'-id'}, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'Artist BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'Artist BrowseMetadata NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, $artist->{'-id'}, 'Artist BrowseMetadata id ok' ); + is( $container->{'-parentID'}, $artist->{'-parentID'}, 'Artist BrowseMetadata parentID ok' ); + is( $container->{'dc:title'}, $artist->{'dc:title'}, 'Artist BrowseMetadata dc:title ok' ); + is( $container->{'upnp:class'}, $artist->{'upnp:class'}, 'Artist BrowseMetadata upnp:class ok' ); + + # Test requesting only 1 artist (used by iOS app 'Dixim DMC') + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/a', + Filter => '*', + StartingIndex => 0, + RequestedCount => 1, + SortCriteria => '', + } ); + + is( $res->{NumberReturned}->{t}, 1, 'Artist BrowseDirectChildren 0 1 ok' ); +} + +# Test browsing an artist's menu (albums) +my $album; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $artist->{'-id'}, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', # XXX test sort + } ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + + $album = $container->[0]; + like( $album->{'-id'}, qr{^/a/\d+/l/\d+/t$}, 'Album container id ok' ); + is( $album->{'-parentID'}, $artist->{'-id'}, 'Album container parentID ok' ); + ok( $album->{'dc:title'}, 'Album container dc:title ok' ); + like( $album->{'dc:date'}, qr/^\d{4}-\d{2}-\d{2}$/, 'Album container dc:date ok' ); + ok( $album->{'dc:creator'}, 'Album container dc:creator ok' ); + ok( $album->{'upnp:artist'}, 'Album container upnp:artist ok' ); + ok( $album->{'upnp:albumArtURI'}, 'Album container upnp:albumArtURI ok' ); + #cmp_ok( $album->{'-childCount'}, '>', 0, 'Album container childCount ok' ); + is( $album->{'upnp:class'}, 'object.container.album.musicAlbum', 'Album container upnp:class ok' ); + + # Test BrowseMetadata + filtering to avoid getting some of the album's items + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $album->{'-id'}, + Filter => 'upnp:artist', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'Album BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'Album BrowseMetadata NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, $album->{'-id'}, 'Album BrowseMetadata id ok' ); + is( $container->{'-parentID'}, $album->{'-parentID'}, 'Album BrowseMetadata parentID ok' ); + is( $container->{'dc:title'}, $album->{'dc:title'}, 'Album BrowseMetadata dc:title ok' ); # required + is( $container->{'upnp:class'}, $album->{'upnp:class'}, 'Album BrowseMetadata upnp:class ok' ); # required + is( $container->{'upnp:artist'}, $album->{'upnp:artist'}, 'Album BrowseMetadata upnp:artist ok' ); # in filter + ok( !exists $container->{'dc:creator'}, 'Album BrowseMetadata dc:creator filtered out' ); # optional + ok( !exists $container->{'upnp:albumArtURI'}, 'Album BrowseMetadata upnp:albumArtURI filtered out' ); # optional + ok( !exists $container->{'dc:date'}, 'Album BrowseMetadata dc:date filtered out' ); # optional +} + +# Test browsing an album's menu (tracks) +my $track; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $album->{'-id'}, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', # XXX test sort + } ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'item' ] ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + $track = $item->[0]; + like( $track->{'-id'}, qr{^/a/\d+/l/\d+/t/\d+$}, 'Track item id ok' ); + is( $track->{'-parentID'}, $album->{'-id'}, 'Track item parentID ok' ); + ok( $track->{'dc:contributor'}, 'Track item dc:contributor ok' ); + ok( $track->{'dc:creator'}, 'Track item dc:creator ok' ); + like( $track->{'dc:date'}, qr/^\d{4}-\d{2}-\d{2}$/, 'Track item dc:date ok' ); + ok( $track->{'dc:title'}, 'Track item dc:title ok' ); + ok( $track->{'upnp:album'}, 'Track item upnp:album ok' ); + ok( $track->{'upnp:albumArtURI'}, 'Track item upnp:albumArtURI ok' ); + ok( $track->{'upnp:artist'}, 'Track item upnp:artist ok' ); + is( $track->{'upnp:class'}, 'object.item.audioItem.musicTrack', 'Track item upnp:class ok' ); + ok( $track->{'upnp:genre'}, 'Track item upnp:genre ok' ); + like( $track->{'upnp:originalTrackNumber'}, qr/^\d+$/, 'Track item upnp:originalTrackNumber ok' ); + + $track->{res} = $track->{res}->[0] if ref $track->{res} eq 'ARRAY'; + my $res = $track->{res}; + like( $res->{'-bitrate'}, qr/^\d+$/, 'Track item res@bitrate ok' ); + like( $res->{'-duration'}, qr/^\d+:\d{2}:\d{2}(\.\d+)?$/, 'Track item res@duraton ok' ); + like( $res->{'-protocolInfo'}, qr{^http-get:\*:audio/[^:]+:\*$}, 'Track item res@protocolInfo ok' ); + like( $res->{'-sampleFrequency'}, qr/^\d+$/, 'Track item res@sampleFrequency ok' ); + like( $res->{'-size'}, qr/^\d+$/, 'Track item res@size ok' ); + like( $res->{t}, qr{^http://[^/]+/music/\d+/download}, 'Track item res URL ok' ); +} + +# Test BrowseMetadata on track + filter +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $track->{'-id'}, + Filter => 'upnp:album,upnp:albumArtURI,res,res@bitrate', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'Track BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'Track BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + is( $item->{'-id'}, $track->{'-id'}, 'Track BrowseMetadata id ok' ); + is( $item->{'-parentID'}, $track->{'-parentID'}, 'Track BrowseMetadata parentID ok' ); + is( $item->{'dc:title'}, $track->{'dc:title'}, 'Track BrowseMetadata dc:title ok' ); # required + is( $item->{'upnp:class'}, $track->{'upnp:class'}, 'Track BrowseMetadata upnp:class ok' ); # required + is( $item->{'upnp:album'}, $track->{'upnp:album'}, 'Track BrowseMetadata upnp:album ok' ); # in filter + is( $item->{'upnp:albumArtURI'}, $track->{'upnp:albumArtURI'}, 'Track BrowseMetadata upnp:albumArtURI ok' ); # in filter + ok( !exists $item->{'dc:contributor'}, 'Track BrowseMetadata dc:contributor filtered out' ); # optional + ok( !exists $item->{'dc:creator'}, 'Track BrowseMetadata dc:creator filtered out' ); # optional + ok( !exists $item->{'dc:date'}, 'Track BrowseMetadata dc:date filtered out' ); # optional + ok( !exists $item->{'upnp:artist'}, 'Track BrowseMetadata upnp:artist filtered out' ); # optional + ok( !exists $item->{'upnp:genre'}, 'Track BrowseMetadata upnp:genre filtered out' ); # optional + ok( !exists $item->{'upnp:originalTrackNumber'}, 'Track BrowseMetadata upnp:originalTrackNumber filtered out' ); # optional + + my $res = $item->{res}; + $res = $res->[0] if ref $res eq 'ARRAY'; + is( $res->{'-bitrate'}, $track->{res}->{'-bitrate'}, 'Track BrowseMetadata item res@bitrate ok' ); # in filter + ok( !exists $res->{'-duration'}, 'Track BrowseMetadata item res@duraton filtered out' ); # optional + is( $res->{'-protocolInfo'}, $track->{res}->{'-protocolInfo'}, 'Track BrowseMetadata item res@protocolInfo ok' ); # required + ok( !exists $res->{'-sampleFrequency'}, 'Track BrowseMetadata item res@sampleFrequency filtered out' ); # optional + ok( !exists $res->{'-size'}, 'Track BrowseMetadata item res@size filtered out' ); # optional + is( $res->{t}, $track->{res}->{t}, 'Track BrowseMetadata item res URL ok' ); # in filter +} + +### /l albums tree + +# /l +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/l', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/l BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/l BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is( $c->{'-id'}, '/l', '/l BrowseMetadata id ok' ); + is( $c->{'-parentID'}, '/music', '/l BrowseMetadata parentID ok' ); + is( $c->{'dc:title'}, 'Albums', '/l BrowseMetadata dc:title ok' ); + is( $c->{'upnp:class'}, 'object.container', '/l BrowseMetadata upnp:class ok' ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/l', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + is( scalar @{$c}, 10, '/l child count ok' ); + + $album = $c->[0]; + like( $album->{'-id'}, qr{^/l/\d+/t$}, '/l album id ok' ); + is( $album->{'-parentID'}, '/l', '/l album parentID ok' ); + #cmp_ok( $album->{'-childCount'}, '>', 0, '/l album childCount ok' ); + is( $album->{'upnp:class'}, 'object.container.album.musicAlbum', '/l album upnp:class ok' ); +} + +# /l//t +{ + my $aid = $album->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$aid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$aid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $album, "$aid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'item' ] ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + like( $track->{'-id'}, qr{^$aid/\d+$}, "$aid BrowseDirectChildren id ok" ); + is( $track->{'-parentID'}, $aid, "$aid BrowseDirectChildren parentID ok" ); +} + +# /l//t/ +{ + my $tid = $track->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $tid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$tid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$tid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + is_deeply( $item, $track, "$tid BrowseMetadata ok" ); +} + +### /g genres tree + +# /g +my $genre; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/g', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/g BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/g BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is( $c->{'-id'}, '/g', '/g BrowseMetadata id ok' ); + is( $c->{'-parentID'}, '/music', '/g BrowseMetadata parentID ok' ); + is( $c->{'dc:title'}, 'Genres', '/g BrowseMetadata dc:title ok' ); + is( $c->{'upnp:class'}, 'object.container', '/g BrowseMetadata upnp:class ok' ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/g', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + is( scalar @{$c}, 10, '/g child count ok' ); + + $genre = $c->[0]; + like( $genre->{'-id'}, qr{^/g/\d+/a$}, '/g genre id ok' ); + is( $genre->{'-parentID'}, '/g', '/g genre parentID ok' ); + is( $genre->{'upnp:class'}, 'object.container.genre.musicGenre', '/g genre upnp:class ok' ); +} + +# /g//a +{ + my $gid = $genre->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $gid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$gid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$gid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $genre, "$gid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $gid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + $artist = $c->[0]; + + like( $artist->{'-id'}, qr{^$gid/\d+/l$}, "$gid BrowseDirectChildren id ok" ); + is( $artist->{'-parentID'}, $gid, "$gid BrowseDirectChildren parentID ok" ); +} + +# /g//a//l +{ + my $aid = $artist->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$aid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$aid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $artist, "$aid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $c = $menu->{'DIDL-Lite'}->{container}; + + $album = $c; + + like( $album->{'-id'}, qr{^$aid/\d+/t$}, "$aid BrowseDirectChildren id ok" ); + is( $album->{'-parentID'}, $aid, "$aid BrowseDirectChildren parentID ok" ); +} + +# /g//a//l//t +{ + my $aid = $album->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$aid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$aid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $album, "$aid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'item' ] ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + like( $track->{'-id'}, qr{^$aid/\d+$}, "$aid BrowseDirectChildren id ok" ); + is( $track->{'-parentID'}, $aid, "$aid BrowseDirectChildren parentID ok" ); +} + +# /g//a//l//t/ +{ + my $tid = $track->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $tid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$tid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$tid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + is_deeply( $item, $track, "$tid BrowseMetadata ok" ); +} + +### /y years tree + +# /y +my $year; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/y', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/y BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/y BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is( $c->{'-id'}, '/y', '/y BrowseMetadata id ok' ); + is( $c->{'-parentID'}, '/music', '/y BrowseMetadata parentID ok' ); + is( $c->{'dc:title'}, 'Years', '/y BrowseMetadata dc:title ok' ); + is( $c->{'upnp:class'}, 'object.container', '/y BrowseMetadata upnp:class ok' ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/y', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + is( scalar @{$c}, 10, '/y child count ok' ); + + # Make sure to get a proper year + ($year) = grep { $_->{'dc:title'} =~ /^(19|20)/ } reverse @{$c}; + + like( $year->{'-id'}, qr{^/y/\d+/l$}, '/y year id ok' ); + is( $year->{'-parentID'}, '/y', '/y year parentID ok' ); + is( $year->{'upnp:class'}, 'object.container', '/y year upnp:class ok' ); +} + +# /y//l +{ + my $yid = $year->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $yid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$yid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$yid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $year, "$yid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $yid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + $album = $c->[0]; + + like( $album->{'-id'}, qr{^$yid/\d+/t$}, "$yid BrowseDirectChildren id ok" ); + is( $album->{'-parentID'}, $yid, "$yid BrowseDirectChildren parentID ok" ); +} + +# /y//l//t +{ + my $aid = $album->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$aid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$aid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $album, "$aid BrowseMetadata ok" ); +} + +### /n new music tree + +# /n +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/n', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/n BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/n BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is( $c->{'-id'}, '/n', '/n BrowseMetadata id ok' ); + is( $c->{'-parentID'}, '/music', '/n BrowseMetadata parentID ok' ); + is( $c->{'dc:title'}, 'New Music', '/n BrowseMetadata dc:title ok' ); + is( $c->{'upnp:class'}, 'object.container', '/n BrowseMetadata upnp:class ok' ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/n', + Filter => '*', + StartingIndex => 0, + RequestedCount => 200, # to check that we only get 100 (default age limit pref) + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + is( scalar @{$c}, 100, '/n child count ok (limited to 100)' ); + + $album = $c->[0]; + like( $album->{'-id'}, qr{^/n/\d+/t$}, '/n album id ok' ); + is( $album->{'-parentID'}, '/n', '/n album parentID ok' ); + #cmp_ok( $album->{'-childCount'}, '>', 0, '/n album childCount ok' ); + is( $album->{'upnp:class'}, 'object.container.album.musicAlbum', '/n album upnp:class ok' ); +} + +# /n//t +{ + my $aid = $album->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$aid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$aid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $album, "$aid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $aid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'item' ] ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + like( $track->{'-id'}, qr{^$aid/\d+$}, "$aid BrowseDirectChildren id ok" ); + is( $track->{'-parentID'}, $aid, "$aid BrowseDirectChildren parentID ok" ); +} + +# /n//t/ +{ + my $tid = $track->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $tid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$tid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$tid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + is_deeply( $item, $track, "$tid BrowseMetadata ok" ); +} + +### /m music folder tree + +print "# Note: /m musicfolder tests require an artist/album/track folder structure\n"; + +# /m +my $folder; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/m', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/m BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/m BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is( $c->{'-id'}, '/m', '/m BrowseMetadata id ok' ); + is( $c->{'-parentID'}, '/music', '/m BrowseMetadata parentID ok' ); + is( $c->{'dc:title'}, 'Music Folder', '/m BrowseMetadata dc:title ok' ); + is( $c->{'upnp:class'}, 'object.container', '/m BrowseMetadata upnp:class ok' ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/m', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + is( scalar @{$c}, 10, '/m child count ok' ); + + $folder = $c->[0]; + like( $folder->{'-id'}, qr{^/m/\d+/m$}, '/m folder id ok' ); + is( $folder->{'-parentID'}, '/m', '/m folder parentID ok' ); + is( $folder->{'upnp:class'}, 'object.container.storageFolder', '/m folder upnp:class ok' ); +} + +# /m//m +{ + my $fid = $folder->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $fid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$fid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$fid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $folder, "$fid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $fid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + $folder = $c->[0]; + + like( $folder->{'-id'}, qr{^$fid/\d+/m$}, "$fid BrowseDirectChildren id ok" ); + is( $folder->{'-parentID'}, $fid, "$fid BrowseDirectChildren parentID ok" ); +} + +# /m//m//m (an album's menu, at least in my dir structure) +{ + my $fid = $folder->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $fid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$fid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$fid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $folder, "$fid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $fid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'item' ] ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + # Handle changed track ID + my $fidtrack = $fid; + $fidtrack =~ s/m$/t/; + + like( $track->{'-id'}, qr{^$fidtrack/\d+$}, "$fid BrowseDirectChildren id ok" ); + is( $track->{'-parentID'}, $fid, "$fid BrowseDirectChildren parentID ok" ); +} + +# /m//m//t/ +{ + my $tid = $track->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $tid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$tid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$tid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + is_deeply( $item, $track, "$tid BrowseMetadata ok" ); +} + +### /p playlists tree + +print "# These tests require at least 1 playlist\n"; + +# /p +my $playlist; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/p', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/p BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/p BrowseMetadata NumberReturned is 1' ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is( $c->{'-id'}, '/p', '/p BrowseMetadata id ok' ); + is( $c->{'-parentID'}, '/music', '/p BrowseMetadata parentID ok' ); + is( $c->{'dc:title'}, 'Playlists', '/p BrowseMetadata dc:title ok' ); + is( $c->{'upnp:class'}, 'object.container', '/p BrowseMetadata upnp:class ok' ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/p', + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + $c = $menu->{'DIDL-Lite'}->{container}; + + cmp_ok( scalar @{$c}, '>=', 1, '/p child count ok' ); + + $playlist = $c->[0]; + like( $playlist->{'-id'}, qr{^/p/\d+/t$}, '/p playlist id ok' ); + is( $playlist->{'-parentID'}, '/p', '/p playlist parentID ok' ); + is( $playlist->{'upnp:class'}, 'object.container.playlistContainer', '/p playlist upnp:class ok' ); +} + +# /p//t +{ + my $pid = $playlist->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $pid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$pid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$pid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $c = $menu->{'DIDL-Lite'}->{container}; + + is_deeply( $c, $playlist, "$pid BrowseMetadata ok" ); + + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => $pid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '', + } ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + like( $track->{'-id'}, qr{^$pid/\d+$}, "$pid BrowseDirectChildren id ok" ); + is( $track->{'-parentID'}, $pid, "$pid BrowseDirectChildren parentID ok" ); +} + +# /p//t/ +{ + my $tid = $track->{'-id'}; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $tid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$tid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$tid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + is_deeply( $item, $track, "$tid BrowseMetadata ok" ); +} + +### Special /t/ track ID +{ + my ($id) = $track->{'-id'} =~ m{t/(\d+)}; + my $tid = "/t/${id}"; + + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $tid, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, "$tid BrowseMetadata TotalMatches is 1" ); + is( $res->{NumberReturned}->{t}, 1, "$tid BrowseMetadata NumberReturned is 1" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $item = $menu->{'DIDL-Lite'}->{item}; + + # Fix IDs + $track->{'-id'} = $tid; + $track->{'-parentID'} = '/t'; + + is_deeply( $item, $track, "$tid BrowseMetadata ok" ); +} + +### All Videos (/va) + +# Test browsing All Videos menu +my $video; +{ + my $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseDirectChildren', + ObjectID => '/va', + Filter => '*', + StartingIndex => 0, + RequestedCount => 100, + SortCriteria => '', + } ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't', array => [ 'container' ] ); + my $container = $menu->{'DIDL-Lite'}->{container}; + + # Skip Various Artists artist if it's there + $video = $container->[0]; + + like( $video->{'-id'}, qr{^/va/\d+/v$}, 'Video container id ok' ); + is( $video->{'-parentID'}, '/a', 'Video container parentID ok' ); + ok( $video->{'dc:title'}, 'Video container dc:title ok' ); + ok( $video->{'upnp:album'}, 'Video container upnp:album ok' ); + is( $video->{'upnp:class'}, 'object.container.person.musicArtist', 'Video container upnp:class ok' ); + + # Test BrowseMetadata on videos item + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => '/va', + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, '/va BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, '/va BrowseMetadata NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, '/va', '/va BrowseMetadata id ok' ); + is( $container->{'-parentID'}, '/video', '/va BrowseMetadata parentID ok' ); + is( $container->{'dc:title'}, 'All Videos', '/va BrowseMetadata dc:title ok' ); + is( $container->{'upnp:class'}, 'object.container', '/va BrowseMetadata upnp:class ok' ); + + # Test BrowseMetadata on a video + $res = _action( $cd, 'Browse', { + BrowseFlag => 'BrowseMetadata', + ObjectID => $video->{'-id'}, + Filter => '*', + StartingIndex => 0, + RequestedCount => 0, + SortCriteria => '', + } ); + + is( $res->{TotalMatches}->{t}, 1, 'Video BrowseMetadata TotalMatches is 1' ); + is( $res->{NumberReturned}->{t}, 1, 'Video BrowseMetadata NumberReturned is 1' ); + + $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + $container = $menu->{'DIDL-Lite'}->{container}; + + is( $container->{'-id'}, $video->{'-id'}, 'Video BrowseMetadata id ok' ); + is( $container->{'-parentID'}, $video->{'-parentID'}, 'Video BrowseMetadata parentID ok' ); + is( $container->{'dc:title'}, $video->{'dc:title'}, 'Video BrowseMetadata dc:title ok' ); + is( $container->{'upnp:album'}, $video->{'upnp:album'}, 'Video BrowseMetadata upnp:album ok' ); + is( $container->{'upnp:class'}, $video->{'upnp:class'}, 'Video BrowseMetadata upnp:class ok' ); +} + +### Search + +# Windows 7 WMP uses this query to build a complete index of all audio tracks on the server +{ + my $res = _action( $cd, 'Search', { + ContainerID => 0, + SearchCriteria => 'upnp:class derivedfrom "object.item.audioItem" and @refID exists false', + Filter => '*', + StartingIndex => 0, + RequestedCount => 200, + SortCriteria => '+upnp:artist,+upnp:album,+upnp:originalTrackNumber,+dc:title', + } ); + + cmp_ok( $res->{TotalMatches}->{t}, '>', 0, "Win7 Search TotalMatches is >0" ); + cmp_ok( $res->{NumberReturned}->{t}, '>', 0, "Win7 Search NumberReturned is >0" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + like( $track->{'-id'}, qr{^/t/\d+$}, 'Win7 Search result id ok' ); + is( $track->{'-parentID'}, '/t', 'Win7 Search result parentID ok' ); +} + +# Revue Media Player 1.0 uses this query +{ + my $res = _action( $cd, 'Search', { + ContainerID => 0, + SearchCriteria => '(dc:title contains "david") or (dc:creator contains "david") or (upnp:artist contains "david") or (upnp:genre contains "david") or (upnp:album contains "david")', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '+dc:title', + } ); + + cmp_ok( $res->{TotalMatches}->{t}, '>', 0, "Revue Search TotalMatches is >0" ); + cmp_ok( $res->{NumberReturned}->{t}, '>', 0, "Revue Search NumberReturned is >0" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + $track = $items->[0]; + + like( $track->{'-id'}, qr{^/t/\d+$}, 'Revue Search result id ok' ); + is( $track->{'-parentID'}, '/t', 'Revue Search result parentID ok' ); +} + +# Test searching for new videos only +{ + my $res = _action( $cd, 'Search', { + ContainerID => 0, + SearchCriteria => 'pv:lastUpdated > 0 and upnp:class derivedfrom "object.item.videoItem"', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '-pv:lastUpdated', + } ); + + cmp_ok( $res->{TotalMatches}->{t}, '>', 0, "Video Search TotalMatches is >0" ); + cmp_ok( $res->{NumberReturned}->{t}, '>', 0, "Video Search NumberReturned is >0" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + my $video = $items->[0]; + + like( $video->{'-id'}, qr{^/v/[0-9a-f]{8}$}, 'Video Search result id ok' ); + is( $video->{'-parentID'}, '/v', 'Video Search result parentID ok' ); +} + +# Test searching for images +{ + my $res = _action( $cd, 'Search', { + ContainerID => 0, + SearchCriteria => 'pv:lastUpdated > 0 and upnp:class derivedfrom "object.item.imageItem"', + Filter => '*', + StartingIndex => 0, + RequestedCount => 10, + SortCriteria => '-pv:lastUpdated', + } ); + + cmp_ok( $res->{TotalMatches}->{t}, '>', 0, "Image Search TotalMatches is >0" ); + cmp_ok( $res->{NumberReturned}->{t}, '>', 0, "Image Search NumberReturned is >0" ); + + my $menu = xml2hash( $res->{Result}->{t}, text => 't' ); + my $items = $menu->{'DIDL-Lite'}->{item}; + + my $image = $items->[0]; + + like( $image->{'-id'}, qr{^/i/[0-9a-f]{8}$}, 'Image Search result id ok' ); + is( $image->{'-parentID'}, '/i', 'Image Search result parentID ok' ); +} +exit; + +sub _action { + my ( $service, $action, $args ) = @_; + + $args ||= {}; + + my $res = $service->postaction($action, $args); + my $hash = xml2hash( $res->gethttpresponse->getcontent, text => 't' ); + + if ( $res->getstatuscode == 200 ) { + return $hash->{'s:Envelope'}->{'s:Body'}->{"u:${action}Response"}; + } + else { + return $hash->{'s:Envelope'}->{'s:Body'}->{'s:Fault'}->{detail}; + } +} diff --git a/Slim/Plugin/UPnP/t/UPnP.t b/Slim/Plugin/UPnP/t/UPnP.t new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Slim/Plugin/UPnP/t/lib/GENA.pm b/Slim/Plugin/UPnP/t/lib/GENA.pm new file mode 100644 index 00000000000..6ddf0b8a284 --- /dev/null +++ b/Slim/Plugin/UPnP/t/lib/GENA.pm @@ -0,0 +1,235 @@ +package GENA; + +# Very basic GENA client for testing + +use strict; + +use Data::Dump qw(dump); +use IO::Select; +use IO::Socket::INET; +use HTTP::Daemon; +use URI; +use XML::Simple qw(XMLin); + +use constant TIMEOUT => 5; + +my $SERVER; +my %SUBS; + +sub new { + my ( $class, $url, $cb ) = @_; + + # Setup a server for callbacks + $SERVER ||= HTTP::Daemon->new( + Listen => SOMAXCONN, + ReuseAddr => 1, + Reuse => 1, + Timeout => 1, + ); + + if ( !$SERVER ) { + die "Unable to open GENA callback socket: $!\n"; + } + + my $self = bless { + evt_url => URI->new($url), + cb_url => 'http://' . _detect_ip() . ':' . $SERVER->sockport . '/', + cb => $cb || sub { die "No callback registered for $url, did you forget to unsubscribe?\n" }, + }, $class; + + $self->subscribe() || return; + + $SUBS{ $self->{sid} } = $self; + + return $self; +} + +sub clear_callback { + my $self = shift; + + $self->{cb} = sub { die "No callback registered for " . $self->{evt_url} . "\n" }; +} + +sub set_callback { + my ( $self, $cb ) = @_; + + $self->{cb} = $cb; +} + +sub subscribe { + my $self = shift; + + my $uri = $self->{evt_url}; + + my $req = join "\x0D\x0A", ( + 'SUBSCRIBE ' . $uri->path_query . ' HTTP/1.1', + 'Host: ' . $uri->host_port, + 'Callback: <' . $self->{cb_url} . '>', + 'NT: upnp:event', + 'Timeout: Second-300', + '', '', + ); + + my $sock = IO::Socket::INET->new( + PeerAddr => $uri->host, + PeerPort => $uri->port, + Timeout => TIMEOUT, + ) || die "Unable to connect to $uri: $!\n"; + + syswrite $sock, $req || die "Unable to write to $uri: $!\n"; + + sysread $sock, my $res, 4096 || die "Unable to read from $uri: $!\n"; + + close $sock; + + if ( $res =~ m{^HTTP/1.1 200 OK} ) { + ($self->{sid}) = $res =~ /SID:\s+(uuid:.+)\x0D/; + return 1; + } + else { + my ($status) = $res =~ /(.+)\x0D/; + $self->{error} = $status; + return; + } +} + +sub renew { + my $self = shift; + + my $uri = $self->{evt_url}; + + my $req = join "\x0D\x0A", ( + 'SUBSCRIBE ' . $uri->path_query . ' HTTP/1.1', + 'Host: ' . $uri->host_port, + 'SID: ' . $self->{sid}, + 'Timeout: Second-300', + '', '', + ); + + my $sock = IO::Socket::INET->new( + PeerAddr => $uri->host, + PeerPort => $uri->port, + Timeout => TIMEOUT, + ) || die "Unable to connect to $uri: $!\n"; + + syswrite $sock, $req || die "Unable to write to $uri: $!\n"; + + sysread $sock, my $res, 4096 || die "Unable to read from $uri: $!\n"; + + close $sock; + + my $sid = $self->{sid}; + if ( $res =~ m{SID:\s+$sid} ) { + return 1; + } + else { + my ($status) = $res =~ /(.+)\x0D/; + $self->{error} = $status; + return; + } +} + +sub unsubscribe { + my $self = shift; + + if ( delete $SUBS{ $self->{sid} } ) { + my $uri = $self->{evt_url}; + + my $req = join "\x0D\x0A", ( + 'UNSUBSCRIBE ' . $uri->path_query . ' HTTP/1.1', + 'Host: ' . $uri->host_port, + 'SID: ' . $self->{sid}, + '', '', + ); + + my $sock = IO::Socket::INET->new( + PeerAddr => $uri->host, + PeerPort => $uri->port, + Timeout => TIMEOUT, + ) || die "Unable to connect to $uri: $!\n"; + + syswrite $sock, $req || die "Unable to write to $uri: $!\n"; + + sysread $sock, my $res, 4096 || die "Unable to read from $uri: $!\n"; + + close $sock; + + if ( $res =~ m{^HTTP/1.1 200 OK} ) { + $self->{sid} = 0; + return 1; + } + else { + my ($status) = $res =~ /(.+)\x0D/; + $self->{error} = $status; + return; + } + } +} + +sub wait { + my ( $class, $wanted ) = @_; + + my $sel = IO::Select->new($SERVER); + + while ( $sel->can_read(TIMEOUT) ) { + my $client = $SERVER->accept || die "Unable to accept(): $!\n"; + + my $request = $client->get_request; + + if ( !$request ) { + warn "# invalid GENA request: " . $client->reason . "\n"; + syswrite $client, "HTTP/1.1 400 Bad Request\r\n\r\n"; + close $client; + next; + } + + my $instance = $SUBS{ $request->header('SID') }; + if ( !$instance ) { + warn "# invalid SID in request: " . dump($request) . "\n"; + syswrite $client, "HTTP/1.1 400 Bad Request\r\n\r\n"; + close $client; + next; + } + + syswrite $client, "HTTP/1.1 200 OK\r\n\r\n"; + close $client; + + # Clean up the property data + my $props = {}; + #warn dump($request->content); + my $evt = eval { XMLin( $request->content, ForceArray => [ 'e:property' ] ) }; + if ( $@ ) { + die "GENA XML parse error: $@\n"; + } + + for my $prop ( @{ $evt->{'e:property'} } ) { + for my $k ( keys %{$prop} ) { + $props->{$k} = ref $prop->{$k} eq 'HASH' ? '' : $prop->{$k}; + } + } + + $instance->{cb}->( $request, $props ); + + # Break out if we've received enough events + last unless --$wanted; + } +} + +sub _detect_ip { + # From IPDetect + my $raddr = '192.43.244.18'; + my $rport = 123; + + my $proto = (getprotobyname('udp'))[2]; + my $pname = (getprotobynumber($proto))[0]; + my $sock = Symbol::gensym(); + my $iaddr = inet_aton($raddr); + my $paddr = sockaddr_in($rport, $iaddr); + socket($sock, PF_INET, SOCK_DGRAM, $proto); + connect($sock, $paddr); + my ($port, $address) = sockaddr_in( (getsockname($sock))[0] ); + + return inet_ntoa($address); +} + +1; diff --git a/Slim/Plugin/Visualizer/Plugin.pm b/Slim/Plugin/Visualizer/Plugin.pm index 19da506ac79..0e3d51227de 100644 --- a/Slim/Plugin/Visualizer/Plugin.pm +++ b/Slim/Plugin/Visualizer/Plugin.pm @@ -2,7 +2,7 @@ package Slim::Plugin::Visualizer::Plugin; # $Id: $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/Visualizer/install.xml b/Slim/Plugin/Visualizer/install.xml index 4f123a6c62b..52f4e930b2b 100644 --- a/Slim/Plugin/Visualizer/install.xml +++ b/Slim/Plugin/Visualizer/install.xml @@ -14,7 +14,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/WiMP/install.xml b/Slim/Plugin/WiMP/install.xml index 25a1ef5e61f..706d49bd41e 100644 --- a/Slim/Plugin/WiMP/install.xml +++ b/Slim/Plugin/WiMP/install.xml @@ -11,7 +11,7 @@ plugins/WiMP/html/images/icon.png 2 - Squeezebox Server + Logitech Media Server 7.5 * diff --git a/Slim/Plugin/iTunes/Common.pm b/Slim/Plugin/iTunes/Common.pm index b02720b7203..f44847f7a62 100644 --- a/Slim/Plugin/iTunes/Common.pm +++ b/Slim/Plugin/iTunes/Common.pm @@ -1,6 +1,6 @@ package Slim::Plugin::iTunes::Common; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -19,7 +19,7 @@ package Slim::Plugin::iTunes::Common; # # ignoredisableditunestracks # -- if this is set (1), songs that are 'disabled' (unchecked) -# in iTunes will still be available to Squeezebox Server. If this is +# in iTunes will still be available to Logitech Media Server. If this is # unset (0) or undefined, disabled songs will be skipped. # # itunesscaninterval @@ -226,16 +226,18 @@ sub findMusicLibraryFile { $base, ); - my $audiodir = Slim::Utils::Misc::getAudioDir(); + my $mediadirs = Slim::Utils::Misc::getAudioDirs(); - if (defined $audiodir) { - push @searchdirs, ( - catdir($audiodir, 'My Music', 'iTunes'), - catdir($audiodir, 'iTunes'), - $audiodir - ); + if (scalar @{ $mediadirs }) { + foreach my $audiodir (@{ $mediadirs }) { + push @searchdirs, ( + catdir($audiodir, 'My Music', 'iTunes'), + catdir($audiodir, 'iTunes'), + $audiodir + ); + } } - + for my $dir (@searchdirs) { $path = catfile(($dir), 'iTunes Music Library.xml'); diff --git a/Slim/Plugin/iTunes/Importer.pm b/Slim/Plugin/iTunes/Importer.pm index 532c12335fd..2e035e9d99e 100644 --- a/Slim/Plugin/iTunes/Importer.pm +++ b/Slim/Plugin/iTunes/Importer.pm @@ -1,6 +1,6 @@ package Slim::Plugin::iTunes::Importer; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/iTunes/Plugin.pm b/Slim/Plugin/iTunes/Plugin.pm index 7f6e42428ae..a8204ba5b51 100644 --- a/Slim/Plugin/iTunes/Plugin.pm +++ b/Slim/Plugin/iTunes/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::iTunes::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/iTunes/Settings.pm b/Slim/Plugin/iTunes/Settings.pm index 3e160a06ac4..0a6766a9972 100644 --- a/Slim/Plugin/iTunes/Settings.pm +++ b/Slim/Plugin/iTunes/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::iTunes::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/iTunes/install.xml b/Slim/Plugin/iTunes/install.xml index 40c6b7ca3aa..33c6b0631d6 100644 --- a/Slim/Plugin/iTunes/install.xml +++ b/Slim/Plugin/iTunes/install.xml @@ -17,7 +17,7 @@ http://www.mysqueezebox.com/support plugins/iTunes/settings/itunes.html - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Plugin/iTunes/strings.txt b/Slim/Plugin/iTunes/strings.txt index 887394e6f2b..3cd8911d7e1 100644 --- a/Slim/Plugin/iTunes/strings.txt +++ b/Slim/Plugin/iTunes/strings.txt @@ -125,22 +125,22 @@ SETUP_ITUNES ZH_CN iTunes SETUP_ITUNES_DESC - CS Squeezebox Server může použít vaši hudební knihovnu a seznamy skladeb iTunes. Veškeré změny, které provede v iTunes se odrazí ve vašem přehrávači. Zaškrtněte níže uvedené políčko, jestli chcete importovat informace o vaší hudební knihovně iTunes. - DA Squeezebox Server kan bruge musikbiblioteket og afspilningslisterne fra iTunes. Alt hvad der ændres i iTunes, bliver afspejlet på afspilleren. Du skal markere feltet nedenfor hvis du vil importere oplysninger om iTunes-musikbiblioteket. - DE Squeezebox Server kann die Musiksammlung und Wiedergabeliste aus iTunes nutzen. In iTunes vorgenommene Änderungen werden an den Player übertragen. Aktivieren Sie das Kontrollkästchen unten, wenn die iTunes-Musiksammlung importiert werden soll. - EN Squeezebox Server can use your iTunes music library and playlists. Any changes that you make in iTunes will be reflected on your player. Check the box below if you want to import your iTunes Music Library information. - ES Squeezebox Server puede usar la biblioteca de música y las listas de reproducción de iTunes. Cualquier cambio que se realice en iTunes se reflejará en el reproductor. Marque la casilla siguiente si desea importar la información de la biblioteca de música de iTunes. - FI Squeezebox Server voi käyttää iTunesin musiikkikirjastoa ja soittoluetteloita. Kaikki iTunesiin tekemäsi muutokset heijastuvat soittimeen. Lisää valintamerkki alla olevaan ruutuun, jos haluat tuoda iTunes-musiikkikirjaston tiedot. - FR Le Squeezebox Server peut utiliser votre bibliothèque et vos listes de lecture iTunes. Les modifications apportées dans iTunes sont reportées sur votre platine. Cochez la case ci-dessous pour importer les données de la bibliothèque iTunes. - HE Squeezebox Server יכול להשתמש בספריית המוסיקה וברשימות ההשמעה של iTunes. כל שינוי שתבצע ב-iTunes ייוצג בנגן. סמן את התיבה שלהלן אם ברצונך לייבא את מידע ספריית המוסיקה של iTunes. - IT In Squeezebox Server è possibile utilizzare la libreria musicale e le playlist di iTunes. Le eventuali modifiche apportate in iTunes vengono estese al lettore. Selezionare la casella seguente se si desidera importare i dati della libreria musicale di iTunes. - JA Squeezebox ServerはiTunesの音楽ライブラリーとプレイリストを使用することができます。iTunesにおける変更はプレーヤーに反映されます。iTunesの音楽ライブラリー情報を利用するには、以下の項目をチェックしてください。 - NL Squeezebox Server kan gebruik maken van je iTunes-muziekcollectie en -playlists. Alle veranderingen in iTunes worden ook op je muzieksysteem doorgevoerd. Selecteer het vakje hieronder als je de iTunes-muziekcollectiegegevens wilt importeren. - NO Squeezebox Server kan bruke musikkbiblioteket og spillelistene til iTunes. Hvis du endrer noe i iTunes, vises disse endringene på spilleren. Merk av i boksen nedenfor hvis du vil importere musikkbibliotekinformasjonen til iTunes. - PL Program Squeezebox Server może korzystać z biblioteki muzyki i list odtwarzania programu iTunes. Wszelki zmiany wprowadzone w programie iTunes zostaną uwzględnione w odtwarzaczu. Aby zaimportować informacje z biblioteki muzyki programu iTunes, zaznacz pole wyboru poniżej. - RU Squeezebox Server может использовать медиатеку и плей-листы iTunes. Все изменения, вносимые в iTunes, отражаются в плеере. Установите флажок (ниже), чтобы импортировать данные медиатеки iTunes. - SV Musikbiblioteket och spellistorna från iTunes kan användas i Squeezebox Server. Ändringar du gör i iTunes återspeglas även på spelaren. Markera kryssrutan nedan om du vill att musikbiblioteksinformationen från iTunes ska importeras. - ZH_CN Squeezebox Server可以使用您的iTunes音乐库和播放表。您在iTunes所作的所有变动都会显示在您的播放机。如果要导入您的iTunes音乐库信息,请点击如下的复选框。 + CS Logitech Media Server může použít vaši hudební knihovnu a seznamy skladeb iTunes. Veškeré změny, které provede v iTunes se odrazí ve vašem přehrávači. Zaškrtněte níže uvedené políčko, jestli chcete importovat informace o vaší hudební knihovně iTunes. + DA Logitech Media Server kan bruge musikbiblioteket og afspilningslisterne fra iTunes. Alt hvad der ændres i iTunes, bliver afspejlet på afspilleren. Du skal markere feltet nedenfor hvis du vil importere oplysninger om iTunes-musikbiblioteket. + DE Logitech Media Server kann die Musiksammlung und Wiedergabeliste aus iTunes nutzen. In iTunes vorgenommene Änderungen werden an den Player übertragen. Aktivieren Sie das Kontrollkästchen unten, wenn die iTunes-Musiksammlung importiert werden soll. + EN Logitech Media Server can use your iTunes music library and playlists. Any changes that you make in iTunes will be reflected on your player. Check the box below if you want to import your iTunes Music Library information. + ES Logitech Media Server puede usar la biblioteca de música y las listas de reproducción de iTunes. Cualquier cambio que se realice en iTunes se reflejará en el reproductor. Marque la casilla siguiente si desea importar la información de la biblioteca de música de iTunes. + FI Logitech Media Server voi käyttää iTunesin musiikkikirjastoa ja soittoluetteloita. Kaikki iTunesiin tekemäsi muutokset heijastuvat soittimeen. Lisää valintamerkki alla olevaan ruutuun, jos haluat tuoda iTunes-musiikkikirjaston tiedot. + FR Le Logitech Media Server peut utiliser votre bibliothèque et vos listes de lecture iTunes. Les modifications apportées dans iTunes sont reportées sur votre platine. Cochez la case ci-dessous pour importer les données de la bibliothèque iTunes. + HE Logitech Media Server יכול להשתמש בספריית המוסיקה וברשימות ההשמעה של iTunes. כל שינוי שתבצע ב-iTunes ייוצג בנגן. סמן את התיבה שלהלן אם ברצונך לייבא את מידע ספריית המוסיקה של iTunes. + IT In Logitech Media Server è possibile utilizzare la libreria musicale e le playlist di iTunes. Le eventuali modifiche apportate in iTunes vengono estese al lettore. Selezionare la casella seguente se si desidera importare i dati della libreria musicale di iTunes. + JA Logitech Media ServerはiTunesの音楽ライブラリーとプレイリストを使用することができます。iTunesにおける変更はプレーヤーに反映されます。iTunesの音楽ライブラリー情報を利用するには、以下の項目をチェックしてください。 + NL Logitech Media Server kan gebruik maken van je iTunes-muziekcollectie en -playlists. Alle veranderingen in iTunes worden ook op je muzieksysteem doorgevoerd. Selecteer het vakje hieronder als je de iTunes-muziekcollectiegegevens wilt importeren. + NO Logitech Media Server kan bruke musikkbiblioteket og spillelistene til iTunes. Hvis du endrer noe i iTunes, vises disse endringene på spilleren. Merk av i boksen nedenfor hvis du vil importere musikkbibliotekinformasjonen til iTunes. + PL Program Logitech Media Server może korzystać z biblioteki muzyki i list odtwarzania programu iTunes. Wszelki zmiany wprowadzone w programie iTunes zostaną uwzględnione w odtwarzaczu. Aby zaimportować informacje z biblioteki muzyki programu iTunes, zaznacz pole wyboru poniżej. + RU Logitech Media Server может использовать медиатеку и плей-листы iTunes. Все изменения, вносимые в iTunes, отражаются в плеере. Установите флажок (ниже), чтобы импортировать данные медиатеки iTunes. + SV Musikbiblioteket och spellistorna från iTunes kan användas i Logitech Media Server. Ändringar du gör i iTunes återspeglas även på spelaren. Markera kryssrutan nedan om du vill att musikbiblioteksinformationen från iTunes ska importeras. + ZH_CN Logitech Media Server可以使用您的iTunes音乐库和播放表。您在iTunes所作的所有变动都会显示在您的播放机。如果要导入您的iTunes音乐库信息,请点击如下的复选框。 SETUP_ITUNESSCANINTERVAL CS Interval znovunačítání iTunes @@ -161,21 +161,21 @@ SETUP_ITUNESSCANINTERVAL ZH_CN iTunes刷新间隔时间 SETUP_ITUNESSCANINTERVAL_DESC - CS Když se změní knihovna iTunes Music, Squeezebox Server automaticky importuje informace o knihovně. Můžete specifikovat minimální dobu (v sekundách), po kterou bude Squeezebox Server čekat před znovunačtením knihovny iTunes Music. Nulová hodnota zakáže opětovné načtení. - DA Når noget i iTunes-musikbiblioteket ændres, importeres disse oplysninger automatisk i Squeezebox Server. Du kan angive hvor lang tid (i sekunder) der mindst skal gå før iTunes-musikbiblioteket genindlæses i serveren. Hvis værdien er 0, genindlæses det ikke. - DE Wenn sich die iTunes-Musiksammlung ändert, importiert Squeezebox Server die Daten automatisch erneut. Sie können die Zeit (in Sekunden) angeben, die Squeezebox Server mindestens warten soll, bevor die iTunes-Musiksammlung neu geladen wird. Wenn Sie 0 eingeben, wird diese Option deaktiviert. - EN When your iTunes Music Library changes Squeezebox Server will automatically import the library information. You can specify the minimum amount of time (in seconds) that the server will wait before reloading your iTunes Music Library again. A value of zero disables the reload. - ES Cuando cambie la biblioteca de música de iTunes, Squeezebox Server importará automáticamente la información de la biblioteca. Se puede especificar la cantidad de tiempo mínima (en segundos) que el servidor esperará antes de volver a cargar la biblioteca de música de iTunes. Un valor de cero desactiva la recarga. - FI Jos iTunes-musiikkikirjastossa tapahtuu muutoksia, Squeezebox Server tuo kirjaston tiedot automaattisesti. Voit määrittää minimiajan (sekunteina), jonka palvelin odottaa, ennen kuin se lataa iTunes-musiikkikirjaston uudelleen. Jos arvo on nolla, lataaminen on poistettu käytöstä. - FR Le Squeezebox Server importe automatiquement les informations de la collection musicale d'iTunes lorsque vous la modifiez. Vous pouvez spécifier le délai minimal en secondes au bout duquel le serveur actualise la collection musicale d'iTunes. La valeur 0 désactive cette fonctionnalité. - HE כאשר ספריית המוסיקה של iTunes משתנה, Squeezebox Server מייבא את מידע הספרייה באופן אוטומטי. באפשרותך לציין כמות זמן מינימלית (בשניות) שבמהלכה על Squeezebox Server להמתין לפני טעינה חוזרת של ספריית המוסיקה של iTunes. ערך אפס משבית את אפשרות הטעינה מחדש. - IT Se si modifica la libreria musicale di iTunes, Squeezebox Server importa automaticamente i nuovi dati. È possibile specificare il periodo minimo (in secondi) che il server deve attendere prima di ricaricare la libreria musicale di iTunes. Se si imposta il valore zero, la libreria non viene ricaricata. - NL Wanneer je iTunes-muziekcollectie verandert, worden de collectiegegevens automatisch door Squeezebox Server geïmporteerd. Je kunt opgeven (in seconden) hoe lang de server minimaal moet wachten alvorens je iTunes-muziekcollectie te herladen. Een waarde van 0 seconden schakelt herladen uit. - NO Når musikkbiblioteket til iTunes endres, importerer Squeezebox Server automatisk bibliotekinformasjonen. Du kan angi en minimumstid (i sekunder) for hvor lenge serveren skal vente med å laste inn musikkbiblioteket til iTunes igjen. Hvis verdien er null, deaktiveres innlasting. - PL Jeżeli biblioteka muzyki programu iTunes zmieni się, program Squeezebox Server automatycznie zaimportuje informacje z biblioteki. Możliwe jest określenie minimalnego czasu (w sekundach) po jakim program Squeezebox Server ponownie załaduje bibliotekę muzyki programu iTunes. Ustawienie wartości zero powoduje wyłączenie ponownego ładowania. - RU При изменении медиатеки iTunes ее данные автоматически импортируются в Squeezebox Server. Для сервера можно задать минимальный интервал времени (в секундах) перед повторной загрузкой медиатеки iTunes. Значение 0 означает отмену повторной загрузки данных. - SV När ditt iTunes-musikbibliotek ändras importeras biblioteksinformationen automatiskt till Squeezebox Server. Du kan ange en minimitid (i sekunder) som servern ska vänta mellan varje gång informationen från iTunes-biblioteket uppdateras. Om värdet 0 anges avaktiveras uppdateringsfunktionen. - ZH_CN 当您的iTunes音乐库改变时,Squeezebox Server将自动地导入最新音乐库信息。您可以指定Squeezebox Server再装您的iTunes数据库之前极小等候时间(以秒为单位)。以零为值意味着关闭再装功能。 + CS Když se změní knihovna iTunes Music, Logitech Media Server automaticky importuje informace o knihovně. Můžete specifikovat minimální dobu (v sekundách), po kterou bude Logitech Media Server čekat před znovunačtením knihovny iTunes Music. Nulová hodnota zakáže opětovné načtení. + DA Når noget i iTunes-musikbiblioteket ændres, importeres disse oplysninger automatisk i Logitech Media Server. Du kan angive hvor lang tid (i sekunder) der mindst skal gå før iTunes-musikbiblioteket genindlæses i serveren. Hvis værdien er 0, genindlæses det ikke. + DE Wenn sich die iTunes-Musiksammlung ändert, importiert Logitech Media Server die Daten automatisch erneut. Sie können die Zeit (in Sekunden) angeben, die Logitech Media Server mindestens warten soll, bevor die iTunes-Musiksammlung neu geladen wird. Wenn Sie 0 eingeben, wird diese Option deaktiviert. + EN When your iTunes Music Library changes Logitech Media Server will automatically import the library information. You can specify the minimum amount of time (in seconds) that the server will wait before reloading your iTunes Music Library again. A value of zero disables the reload. + ES Cuando cambie la biblioteca de música de iTunes, Logitech Media Server importará automáticamente la información de la biblioteca. Se puede especificar la cantidad de tiempo mínima (en segundos) que el servidor esperará antes de volver a cargar la biblioteca de música de iTunes. Un valor de cero desactiva la recarga. + FI Jos iTunes-musiikkikirjastossa tapahtuu muutoksia, Logitech Media Server tuo kirjaston tiedot automaattisesti. Voit määrittää minimiajan (sekunteina), jonka palvelin odottaa, ennen kuin se lataa iTunes-musiikkikirjaston uudelleen. Jos arvo on nolla, lataaminen on poistettu käytöstä. + FR Le Logitech Media Server importe automatiquement les informations de la collection musicale d'iTunes lorsque vous la modifiez. Vous pouvez spécifier le délai minimal en secondes au bout duquel le serveur actualise la collection musicale d'iTunes. La valeur 0 désactive cette fonctionnalité. + HE כאשר ספריית המוסיקה של iTunes משתנה, Logitech Media Server מייבא את מידע הספרייה באופן אוטומטי. באפשרותך לציין כמות זמן מינימלית (בשניות) שבמהלכה על Logitech Media Server להמתין לפני טעינה חוזרת של ספריית המוסיקה של iTunes. ערך אפס משבית את אפשרות הטעינה מחדש. + IT Se si modifica la libreria musicale di iTunes, Logitech Media Server importa automaticamente i nuovi dati. È possibile specificare il periodo minimo (in secondi) che il server deve attendere prima di ricaricare la libreria musicale di iTunes. Se si imposta il valore zero, la libreria non viene ricaricata. + NL Wanneer je iTunes-muziekcollectie verandert, worden de collectiegegevens automatisch door Logitech Media Server geïmporteerd. Je kunt opgeven (in seconden) hoe lang de server minimaal moet wachten alvorens je iTunes-muziekcollectie te herladen. Een waarde van 0 seconden schakelt herladen uit. + NO Når musikkbiblioteket til iTunes endres, importerer Logitech Media Server automatisk bibliotekinformasjonen. Du kan angi en minimumstid (i sekunder) for hvor lenge serveren skal vente med å laste inn musikkbiblioteket til iTunes igjen. Hvis verdien er null, deaktiveres innlasting. + PL Jeżeli biblioteka muzyki programu iTunes zmieni się, program Logitech Media Server automatycznie zaimportuje informacje z biblioteki. Możliwe jest określenie minimalnego czasu (w sekundach) po jakim program Logitech Media Server ponownie załaduje bibliotekę muzyki programu iTunes. Ustawienie wartości zero powoduje wyłączenie ponownego ładowania. + RU При изменении медиатеки iTunes ее данные автоматически импортируются в Logitech Media Server. Для сервера можно задать минимальный интервал времени (в секундах) перед повторной загрузкой медиатеки iTunes. Значение 0 означает отмену повторной загрузки данных. + SV När ditt iTunes-musikbibliotek ändras importeras biblioteksinformationen automatiskt till Logitech Media Server. Du kan ange en minimitid (i sekunder) som servern ska vänta mellan varje gång informationen från iTunes-biblioteket uppdateras. Om värdet 0 anges avaktiveras uppdateringsfunktionen. + ZH_CN 当您的iTunes音乐库改变时,Logitech Media Server将自动地导入最新音乐库信息。您可以指定Logitech Media Server再装您的iTunes数据库之前极小等候时间(以秒为单位)。以零为值意味着关闭再装功能。 SETUP_ITUNES_LIBRARY_XML_PATH CS Umístění hudební knihovny .xml iTunes @@ -196,21 +196,21 @@ SETUP_ITUNES_LIBRARY_XML_PATH ZH_CN iTunes Music Library.xml地点 SETUP_ITUNES_LIBRARY_XML_PATH_DESC - CS Pokud běží iTunes na jiném počítači než Squeezebox Server, můžete zde specifikovat explicitní cestu k .xml souboru hudební knihovny iTunes. Ponechte prázdné, pokud iTunes běží na stejném počítači jako Squeezebox Server. - DA Hvis iTunes kører på en anden computer end Squeezebox Server, kan du angive stien til filen iTunes Music Library.xml her. Du skal lade feltet være tomt hvis iTunes kører på samme computer som Squeezebox Server. - DE Falls iTunes auf einem anderen Rechner als Squeezebox Server ausgeführt wird, können Sie hier den expliziten Pfad zur Datei 'iTunes Music Library.xml' angeben. Lassen Sie das Feld leer, wenn iTunes auf demselben Rechner wie Squeezebox Server installiert ist. - EN If you are running iTunes on a different computer than Squeezebox Server, you may specify an explicit path to the iTunes Music Library.xml file here. Leave this blank if you are running iTunes on the same computer as Squeezebox Server. - ES Si ejecuta iTunes en un equipo distinto al de Squeezebox Server, puede especificar aquí una ruta explícita a la carpeta de música de iTunes. Deje en blanco si ejecuta iTunes en el mismo equipo que Squeezebox Server. - FI Jos iTunes on käytössä eri tietokoneessa kuin Squeezebox Server, voit määrittää nimenomaisen polun iTunes Music Library.xml -tiedostoon tässä. Jätä tämä kohta tyhjäksi, jos iTunes on asennettuna samaan tietokoneeseen kuin Squeezebox Server. - FR Si vous exécutez iTunes sur un ordinateur différent de celui avec le Squeezebox Server, vous pouvez spécifier ici un chemin d'accès vers le fichier iTunes Music Library.xml. Ne renseignez pas ce champ si la bibliothèque iTunes se trouve sur le même ordinateur que le Squeezebox Server. - HE אם אתה מפעיל את iTunes במחשב אחר מזה שמותקן בו Squeezebox Server, באפשרותך לציין כאן נתיב מפורש לקובץ iTunes Music Library.xml. השאר שדה זה ריק אם אתה מפעיל את iTunes באותו מחשב שבו מותקן Squeezebox Server. - IT Se si utilizza iTunes in un computer diverso da quello in cui è installato Squeezebox Server, è possibile indicare in questo campo il percorso del file Music Library.xml di iTunes. Se iTunes e Squeezebox Server sono installati nello stesso computer, lasciare il campo vuoto. + CS Pokud běží iTunes na jiném počítači než Logitech Media Server, můžete zde specifikovat explicitní cestu k .xml souboru hudební knihovny iTunes. Ponechte prázdné, pokud iTunes běží na stejném počítači jako Logitech Media Server. + DA Hvis iTunes kører på en anden computer end Logitech Media Server, kan du angive stien til filen iTunes Music Library.xml her. Du skal lade feltet være tomt hvis iTunes kører på samme computer som Logitech Media Server. + DE Falls iTunes auf einem anderen Rechner als Logitech Media Server ausgeführt wird, können Sie hier den expliziten Pfad zur Datei 'iTunes Music Library.xml' angeben. Lassen Sie das Feld leer, wenn iTunes auf demselben Rechner wie Logitech Media Server installiert ist. + EN If you are running iTunes on a different computer than Logitech Media Server, you may specify an explicit path to the iTunes Music Library.xml file here. Leave this blank if you are running iTunes on the same computer as Logitech Media Server. + ES Si ejecuta iTunes en un equipo distinto al de Logitech Media Server, puede especificar aquí una ruta explícita a la carpeta de música de iTunes. Deje en blanco si ejecuta iTunes en el mismo equipo que Logitech Media Server. + FI Jos iTunes on käytössä eri tietokoneessa kuin Logitech Media Server, voit määrittää nimenomaisen polun iTunes Music Library.xml -tiedostoon tässä. Jätä tämä kohta tyhjäksi, jos iTunes on asennettuna samaan tietokoneeseen kuin Logitech Media Server. + FR Si vous exécutez iTunes sur un ordinateur différent de celui avec le Logitech Media Server, vous pouvez spécifier ici un chemin d'accès vers le fichier iTunes Music Library.xml. Ne renseignez pas ce champ si la bibliothèque iTunes se trouve sur le même ordinateur que le Logitech Media Server. + HE אם אתה מפעיל את iTunes במחשב אחר מזה שמותקן בו Logitech Media Server, באפשרותך לציין כאן נתיב מפורש לקובץ iTunes Music Library.xml. השאר שדה זה ריק אם אתה מפעיל את iTunes באותו מחשב שבו מותקן Logitech Media Server. + IT Se si utilizza iTunes in un computer diverso da quello in cui è installato Logitech Media Server, è possibile indicare in questo campo il percorso del file Music Library.xml di iTunes. Se iTunes e Logitech Media Server sono installati nello stesso computer, lasciare il campo vuoto. JA iTunesの音楽ライブラリーの場所を手動で指定する場合には、ここにファイル名を含めてxmlファイルへのパスを入力してください。 - NL Als iTunes op een andere computer draait dan Squeezebox Server, kun je hier een expliciet pad naar het bestand iTunes Music Library.xml opgeven. Laat dit veld leeg als iTunes op dezelfde computer als Squeezebox Server draait. - NO Hvis du kjører iTunes på en annen datamaskin enn Squeezebox Server, kan du angi banen til filen iTunes Music Library.xml her. La dette feltet stå tomt hvis du kjører iTunes på samme datamaskin som Squeezebox Server. - PL Jeżeli program iTunes jest uruchomiony na innym komputerze niż program Squeezebox Server, w tym miejscu można określić ścieżkę do pliku Music Library.xml programu iTunes. Jeżeli program iTunes działa na tym samym komputerze co program Squeezebox Server, pozostaw to pole puste. - RU Если iTunes и Squeezebox Server установлены на разных компьютерах, можно напрямую задать путь к файлу XML медиатеки iTunes. Если приложение iTunes установлено на том же компьютере, что и Squeezebox Server, оставьте поле пустым. - SV Om du kör iTunes på en annan dator än den där du kör Squeezebox Server anger du sökvägen till xml-filen för iTunes-musikbiblioteket här. Lämna fältet tomt om iTunes körs på samma dator som Squeezebox Server. + NL Als iTunes op een andere computer draait dan Logitech Media Server, kun je hier een expliciet pad naar het bestand iTunes Music Library.xml opgeven. Laat dit veld leeg als iTunes op dezelfde computer als Logitech Media Server draait. + NO Hvis du kjører iTunes på en annen datamaskin enn Logitech Media Server, kan du angi banen til filen iTunes Music Library.xml her. La dette feltet stå tomt hvis du kjører iTunes på samme datamaskin som Logitech Media Server. + PL Jeżeli program iTunes jest uruchomiony na innym komputerze niż program Logitech Media Server, w tym miejscu można określić ścieżkę do pliku Music Library.xml programu iTunes. Jeżeli program iTunes działa na tym samym komputerze co program Logitech Media Server, pozostaw to pole puste. + RU Если iTunes и Logitech Media Server установлены на разных компьютерах, можно напрямую задать путь к файлу XML медиатеки iTunes. Если приложение iTunes установлено на том же компьютере, что и Logitech Media Server, оставьте поле пустым. + SV Om du kör iTunes på en annan dator än den där du kör Logitech Media Server anger du sökvägen till xml-filen för iTunes-musikbiblioteket här. Lämna fältet tomt om iTunes körs på samma dator som Logitech Media Server. ZH_CN 如果您选择指定iTunes音乐库的地点,请在此输入iTunes Music Library.xml文件的路径及其文件名。 SETUP_ITUNES_LIBRARY_MUSIC_PATH @@ -233,21 +233,21 @@ SETUP_ITUNES_LIBRARY_MUSIC_PATH ZH_CN iTunes音乐文件夹 SETUP_ITUNES_LIBRARY_MUSIC_PATH_DESC - CS Pokud běží iTunes na jiném počítači než Squeezebox Server, můžete zde specifikovat explicitní cestu ke složce iTunes Music. Ponechte prázdné, pokud iTunes běží na stejném počítači jako Squeezebox Server. - DA Hvis iTunes kører på en anden computer end Squeezebox Server, kan du angive stien til iTunes-musikmappen her. Du skal lade feltet være tomt hvis iTunes kører på samme computer som Squeezebox Server. - DE Falls iTunes auf einem anderen Rechner als Squeezebox Server ausgeführt wird, können Sie hier den vollständigen Pfad zum Ordner 'iTunes Media' angeben. Lassen Sie das Feld leer, wenn iTunes auf demselben Rechner wie Squeezebox Server installiert ist. - EN If you are running iTunes on a different computer than Squeezebox Server, you may specify an explicit path to the iTunes Media folder here. Leave this blank if you are running iTunes on the same computer as Squeezebox Server. - ES Si ejecuta iTunes en un equipo distinto al de Squeezebox Server, puede especificar aquí una ruta explícita a la carpeta iTunes Media. Deje en blanco si ejecuta iTunes en el mismo equipo que Squeezebox Server. - FI Jos iTunes on käytössä eri tietokoneessa kuin Squeezebox Server, voit määrittää nimenomaisen polun iTunes Media -kansioon tässä. Jätä tämä kohta tyhjäksi, jos iTunes on asennettuna samaan tietokoneeseen kuin Squeezebox Server. - FR Si vous exécutez iTunes sur un ordinateur différent de celui avec le Squeezebox Server, vous pouvez spécifier ici un chemin d'accès vers la bibliothèque iTunes. Ne renseignez pas ce champ si la bibliothèque iTunes se trouve sur le même ordinateur que le Squeezebox Server. - HE אם אתה מפעיל את iTunes במחשב אחר מזה שמותקן בו Squeezebox Server, באפשרותך לציין כאן נתיב מפורש לתיקיית המוסיקה של iTunes. השאר שדה זה ריק אם אתה מפעיל את iTunes באותו מחשב שבו מותקן Squeezebox Server. - IT Se si utilizza iTunes in un computer diverso da quello in cui è installato Squeezebox Server, è possibile indicare in questo campo il percorso esplicito della cartella iTunes Media. Se iTunes e Squeezebox Server sono installati nello stesso computer, lasciare il campo vuoto. + CS Pokud běží iTunes na jiném počítači než Logitech Media Server, můžete zde specifikovat explicitní cestu ke složce iTunes Music. Ponechte prázdné, pokud iTunes běží na stejném počítači jako Logitech Media Server. + DA Hvis iTunes kører på en anden computer end Logitech Media Server, kan du angive stien til iTunes-musikmappen her. Du skal lade feltet være tomt hvis iTunes kører på samme computer som Logitech Media Server. + DE Falls iTunes auf einem anderen Rechner als Logitech Media Server ausgeführt wird, können Sie hier den vollständigen Pfad zum Ordner 'iTunes Media' angeben. Lassen Sie das Feld leer, wenn iTunes auf demselben Rechner wie Logitech Media Server installiert ist. + EN If you are running iTunes on a different computer than Logitech Media Server, you may specify an explicit path to the iTunes Media folder here. Leave this blank if you are running iTunes on the same computer as Logitech Media Server. + ES Si ejecuta iTunes en un equipo distinto al de Logitech Media Server, puede especificar aquí una ruta explícita a la carpeta iTunes Media. Deje en blanco si ejecuta iTunes en el mismo equipo que Logitech Media Server. + FI Jos iTunes on käytössä eri tietokoneessa kuin Logitech Media Server, voit määrittää nimenomaisen polun iTunes Media -kansioon tässä. Jätä tämä kohta tyhjäksi, jos iTunes on asennettuna samaan tietokoneeseen kuin Logitech Media Server. + FR Si vous exécutez iTunes sur un ordinateur différent de celui avec le Logitech Media Server, vous pouvez spécifier ici un chemin d'accès vers la bibliothèque iTunes. Ne renseignez pas ce champ si la bibliothèque iTunes se trouve sur le même ordinateur que le Logitech Media Server. + HE אם אתה מפעיל את iTunes במחשב אחר מזה שמותקן בו Logitech Media Server, באפשרותך לציין כאן נתיב מפורש לתיקיית המוסיקה של iTunes. השאר שדה זה ריק אם אתה מפעיל את iTunes באותו מחשב שבו מותקן Logitech Media Server. + IT Se si utilizza iTunes in un computer diverso da quello in cui è installato Logitech Media Server, è possibile indicare in questo campo il percorso esplicito della cartella iTunes Media. Se iTunes e Logitech Media Server sono installati nello stesso computer, lasciare il campo vuoto. JA iTunesの音楽ライブラリーの場所を手動で指定する場合には、ここに該当フォルダーへのパスを入力してください。 - NL Als iTunes op een andere computer dan Squeezebox Server wordt uitgevoerd, kun je hier een expliciet pad naar de iTunes Media-map opgeven. Laat dit veld leeg als iTunes op dezelfde computer als Squeezebox Server wordt uitgevoerd. - NO Hvis du kjører iTunes på en annen datamaskin enn Squeezebox Server, kan du angi banen til iTunes Media-mappen her. La dette feltet stå tomt hvis du kjører iTunes på samme datamaskin som Squeezebox Server. - PL Jeżeli program iTunes jest uruchomiony na innym komputerze niż program Squeezebox Server, w tym miejscu można określić katalog iTunes Media. Jeżeli program iTunes działa na tym samym komputerze co program Squeezebox Server, pozostaw to pole puste. - RU Если iTunes и Squeezebox Server установлены на разных компьютерах, можно напрямую задать путь к папке "iTunes Media" в iTunes. Если приложение iTunes установлено на том же компьютере, что и Squeezebox Server, оставьте поле пустым. - SV Om du kör iTunes på en annan dator än den där du kör Squeezebox Server så anger du sökvägen till iTunes-mediamappen här. Lämna fältet tomt om iTunes körs på samma dator som Squeezebox Server. + NL Als iTunes op een andere computer dan Logitech Media Server wordt uitgevoerd, kun je hier een expliciet pad naar de iTunes Media-map opgeven. Laat dit veld leeg als iTunes op dezelfde computer als Logitech Media Server wordt uitgevoerd. + NO Hvis du kjører iTunes på en annen datamaskin enn Logitech Media Server, kan du angi banen til iTunes Media-mappen her. La dette feltet stå tomt hvis du kjører iTunes på samme datamaskin som Logitech Media Server. + PL Jeżeli program iTunes jest uruchomiony na innym komputerze niż program Logitech Media Server, w tym miejscu można określić katalog iTunes Media. Jeżeli program iTunes działa na tym samym komputerze co program Logitech Media Server, pozostaw to pole puste. + RU Если iTunes и Logitech Media Server установлены на разных компьютерах, можно напрямую задать путь к папке "iTunes Media" в iTunes. Если приложение iTunes установлено на том же компьютере, что и Logitech Media Server, оставьте поле пустым. + SV Om du kör iTunes på en annan dator än den där du kör Logitech Media Server så anger du sökvägen till iTunes-mediamappen här. Lämna fältet tomt om iTunes körs på samma dator som Logitech Media Server. ZH_CN 如果您选择指定iTunes音乐库的地点,请在此输入存有您iTunes音乐的文件夹名及其路径。 SETUP_IGNOREDISABLEDITUNESTRACKS @@ -268,21 +268,21 @@ SETUP_IGNOREDISABLEDITUNESTRACKS ZH_CN 在iTunes中未经由复选框筛选的歌曲 SETUP_IGNOREDISABLEDITUNESTRACKS_DESC - CS Standardně, pokud odstraníte zaškrtnutí vedle nějaké skladby v iTunes, tato skladba se neobjeví při prohlížení vaší hudby pomocí Squeezebox Server. Toto chování můžete změnit níže. - DA Som standard vil numre som du fjerner markeringen fra i iTunes, ikke være synlige når du gennemser din musiksamling i Squeezebox Server. Du kan ændre det nedenfor. - DE Standardmäßig werden Titeln, die in iTunes deaktiviert sind, nicht in Squeezebox Server angezeigt. Sie können dieses Verhalten hier ändern. - EN By default, when you remove the check mark next to a song in iTunes, that song won't appear when you browse your music with Squeezebox Server. You can change that behavior below. - ES De forma predeterminada, cuando se quita la marca de verificación junto a una canción en iTunes, esa canción no aparecerá cuando se examine la música con Squeezebox Server. Ese comportamiento se puede cambiar a continuación. - FI Jos poistat valintamerkin kappaleen vierestä iTunesissä, kappale ei oletuksena tule näkyviin, kun etsit musiikkia Squeezebox Serverillä. Voit vaihtaa toiminnan alla. - FR Par défaut, lorsque vous désélectionnez un morceau dans iTunes, celui-ci ne s'affiche pas lorsque vous parcourez votre musique grâce au Squeezebox Server. Vous pouvez modifier ce comportement ci-dessous. - HE כברירת מחדל, כאשר אתה מסיר את סימן הביקורת שמוצב ליד שיר ב-iTunes, השיר לא יופיע בעת עיון בפריטי המוסיקה באמצעות Squeezebox Server. באפשרותך לשנות את ההתנהגות בהגדרות שלהלן. - IT Per impostazione predefinita, se in iTunes si deseleziona la casella in corrispondenza di un brano, tale brano non viene visualizzato quando si sfoglia la raccolta musicale con Squeezebox Server. È possibile modificare questa impostazione di seguito. - NL Wanneer je het vinkje weghaalt naast een liedje in iTunes, wordt dat liedje standaard niet weergegeven wanneer je met Squeezebox Server door je muziek bladert. Je kunt dit hieronder veranderen. - NO Hvis du fjerner markeringen ved en sang i iTunes, vises den som standard ikke når du blar i musikk med Squeezebox Server. Du kan endre dette nedenfor. - PL Domyślnie po usunięciu zaznaczenia pola wyboru obok utworu w programie iTunes utwór ten nie będzie wyświetlany podczas przeglądania muzyki w programie Squeezebox Server. Działanie tej funkcji można zmienić poniżej. - RU По умолчанию, если снять флажок песни в iTunes, она не будет отображаться при просмотре в Squeezebox Server. Изменить эту настройку можно ниже. - SV När du avmarkerar en låt i iTunes visas den som standard inte längre när du bläddrar bland dina låtar i Squeezebox Server. Du kan ändra den här funktionen nedan. - ZH_CN 根据缺省规定,当您去除iTunes歌曲旁边复选框的标志,该首歌曲就不会在您浏览Squeezebox Server的音乐时出现。您可以在如下选择是否要遵照此缺省规定。 + CS Standardně, pokud odstraníte zaškrtnutí vedle nějaké skladby v iTunes, tato skladba se neobjeví při prohlížení vaší hudby pomocí Logitech Media Server. Toto chování můžete změnit níže. + DA Som standard vil numre som du fjerner markeringen fra i iTunes, ikke være synlige når du gennemser din musiksamling i Logitech Media Server. Du kan ændre det nedenfor. + DE Standardmäßig werden Titeln, die in iTunes deaktiviert sind, nicht in Logitech Media Server angezeigt. Sie können dieses Verhalten hier ändern. + EN By default, when you remove the check mark next to a song in iTunes, that song won't appear when you browse your music with Logitech Media Server. You can change that behavior below. + ES De forma predeterminada, cuando se quita la marca de verificación junto a una canción en iTunes, esa canción no aparecerá cuando se examine la música con Logitech Media Server. Ese comportamiento se puede cambiar a continuación. + FI Jos poistat valintamerkin kappaleen vierestä iTunesissä, kappale ei oletuksena tule näkyviin, kun etsit musiikkia Logitech Media Serverillä. Voit vaihtaa toiminnan alla. + FR Par défaut, lorsque vous désélectionnez un morceau dans iTunes, celui-ci ne s'affiche pas lorsque vous parcourez votre musique grâce au Logitech Media Server. Vous pouvez modifier ce comportement ci-dessous. + HE כברירת מחדל, כאשר אתה מסיר את סימן הביקורת שמוצב ליד שיר ב-iTunes, השיר לא יופיע בעת עיון בפריטי המוסיקה באמצעות Logitech Media Server. באפשרותך לשנות את ההתנהגות בהגדרות שלהלן. + IT Per impostazione predefinita, se in iTunes si deseleziona la casella in corrispondenza di un brano, tale brano non viene visualizzato quando si sfoglia la raccolta musicale con Logitech Media Server. È possibile modificare questa impostazione di seguito. + NL Wanneer je het vinkje weghaalt naast een liedje in iTunes, wordt dat liedje standaard niet weergegeven wanneer je met Logitech Media Server door je muziek bladert. Je kunt dit hieronder veranderen. + NO Hvis du fjerner markeringen ved en sang i iTunes, vises den som standard ikke når du blar i musikk med Logitech Media Server. Du kan endre dette nedenfor. + PL Domyślnie po usunięciu zaznaczenia pola wyboru obok utworu w programie iTunes utwór ten nie będzie wyświetlany podczas przeglądania muzyki w programie Logitech Media Server. Działanie tej funkcji można zmienić poniżej. + RU По умолчанию, если снять флажок песни в iTunes, она не будет отображаться при просмотре в Logitech Media Server. Изменить эту настройку можно ниже. + SV När du avmarkerar en låt i iTunes visas den som standard inte längre när du bläddrar bland dina låtar i Logitech Media Server. Du kan ändra den här funktionen nedan. + ZH_CN 根据缺省规定,当您去除iTunes歌曲旁边复选框的标志,该首歌曲就不会在您浏览Logitech Media Server的音乐时出现。您可以在如下选择是否要遵照此缺省规定。 SETUP_IGNOREDISABLEDITUNESTRACKS_1 CS Zahrnout všechny skladby diff --git a/Slim/Plugin/xPL/Plugin.pm b/Slim/Plugin/xPL/Plugin.pm index 188aa784f2d..39a6672b0aa 100644 --- a/Slim/Plugin/xPL/Plugin.pm +++ b/Slim/Plugin/xPL/Plugin.pm @@ -1,6 +1,6 @@ package Slim::Plugin::xPL::Plugin; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -11,7 +11,7 @@ package Slim::Plugin::xPL::Plugin; # GNU General Public License for more details. # # -# xPL Protocol Support Plugin for Squeezebox Server +# xPL Protocol Support Plugin for Logitech Media Server # http://www.xplproject.org.uk/ # $Id: Plugin.pm 10841 2006-12-03 16:57:58Z adrian $ diff --git a/Slim/Plugin/xPL/Settings.pm b/Slim/Plugin/xPL/Settings.pm index a57576415d5..60b7322a224 100644 --- a/Slim/Plugin/xPL/Settings.pm +++ b/Slim/Plugin/xPL/Settings.pm @@ -1,6 +1,6 @@ package Slim::Plugin::xPL::Settings; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Plugin/xPL/install.xml b/Slim/Plugin/xPL/install.xml index 243584f836f..da4b5890ebe 100644 --- a/Slim/Plugin/xPL/install.xml +++ b/Slim/Plugin/xPL/install.xml @@ -15,7 +15,7 @@ 2 - Squeezebox Server + Logitech Media Server 7.0a * diff --git a/Slim/Schema.pm b/Slim/Schema.pm index 5e89ea41308..ce0dfe89e0b 100644 --- a/Slim/Schema.pm +++ b/Slim/Schema.pm @@ -2,7 +2,7 @@ package Slim::Schema; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -17,7 +17,7 @@ my $track = Slim::Schema->objectForUrl($url); =head1 DESCRIPTION -L is the main entry point for all interactions with Squeezebox Server's +L is the main entry point for all interactions with Logitech Media Server's database backend. It provides an ORM abstraction layer on top of L, acting as a subclass of L. @@ -490,7 +490,7 @@ sub migrateDB { } else { - # this occurs if a user downgrades Squeezebox Server to a version with an older schema and which does not include + # this occurs if a user downgrades Logitech Media Server to a version with an older schema and which does not include # the required downgrade sql scripts - attempt to drop and create the database at current schema version if ( $log->is_warn ) { @@ -1533,6 +1533,11 @@ sub _newTrack { if ($trackId) { $columnValueHash{'id'} = $trackId; } + + # Record time this track was added/updated + my $now = time(); + $columnValueHash{added_time} = $now; + $columnValueHash{updated_time} = $now; my $ct = $columnValueHash{'content_type'}; @@ -1758,6 +1763,9 @@ sub updateOrCreateBase { 'url' => $url, 'attributes' => $attributeHash, }); + + # Update timestamp + $attributeHash->{updated_time} = time(); while (my ($key, $val) = each %$attributeHash) { diff --git a/Slim/Schema/Album.pm b/Slim/Schema/Album.pm index 31801244705..12b0d454b53 100644 --- a/Slim/Schema/Album.pm +++ b/Slim/Schema/Album.pm @@ -96,7 +96,7 @@ sub title { ); } -# return the raw title untainted by Squeezebox Server logic +# return the raw title untainted by Logitech Media Server logic sub rawtitle { my $self = shift; diff --git a/Slim/Schema/DBI.pm b/Slim/Schema/DBI.pm index 428846b90bc..0c3395f1d80 100644 --- a/Slim/Schema/DBI.pm +++ b/Slim/Schema/DBI.pm @@ -2,7 +2,7 @@ package Slim::Schema::DBI; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Schema/Debug.pm b/Slim/Schema/Debug.pm index 1afe632e008..1488abe71ce 100644 --- a/Slim/Schema/Debug.pm +++ b/Slim/Schema/Debug.pm @@ -2,7 +2,7 @@ package Slim::Schema::Debug; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Schema/Image.pm b/Slim/Schema/Image.pm new file mode 100644 index 00000000000..4ab6ade198f --- /dev/null +++ b/Slim/Schema/Image.pm @@ -0,0 +1,103 @@ +package Slim::Schema::Image; + +use strict; + +use File::Basename; +use Date::Parse qw(str2time); +use Slim::Schema; +use Slim::Formats::XML; +use Slim::Utils::Misc; + +# XXX DBIx::Class stuff needed? + +my %orientation = ( + 'top-left' => 0, + 'top-right' => 1, + 'bottom-right' => 2, + 'bottom-left' => 3, + 'left-top' => 4, + 'right-top' => 5, + 'right-bottom' => 6, + 'left-bottom' => 7, +); + +sub updateOrCreateFromResult { + my ( $class, $result ) = @_; + + my $id; + my $url = Slim::Utils::Misc::fileURLFromPath($result->path); + + my $exifData = $result->tags; + + # Create title and album from path (if not in EXIF data) + my $title = Slim::Formats::XML::trim($exifData->{XPTitle}) + || Slim::Formats::XML::trim($exifData->{ImageDescription}); + + my ($filename, $dirs, undef) = fileparse($result->path); + $title ||= $filename; + + # Album is parent directory + $dirs =~ s{\\}{/}g; + my ($album) = $dirs =~ m{([^/]+)/$}; + + my $sort = Slim::Utils::Text::ignoreCaseArticles($title); + my $search = Slim::Utils::Text::ignoreCaseArticles($title, 1); + my $now = time(); + my $creationDate = str2time($exifData->{DateTimeOriginal}) || str2time($exifData->{DateTime}) || $result->mtime || 0; + + my $hash = { + hash => $result->hash, + url => $url, + title => $title, + titlesearch => $search, + titlesort => $sort, + album => $album, + image_codec => $result->codec, + mime_type => $result->mime_type, + dlna_profile => $result->dlna_profile, + width => $result->width, + height => $result->height, + mtime => $result->mtime, + added_time => $now, + updated_time => $now, + original_time=> $creationDate, + filesize => $result->size, + orientation => $orientation{ lc($exifData->{Orientation} || '') } || 0, + }; + + my $sth = Slim::Schema->dbh->prepare_cached('SELECT id FROM images WHERE url = ?'); + $sth->execute($url); + ($id) = $sth->fetchrow_array; + $sth->finish; + + if ( !$id ) { + $id = Slim::Schema->_insertHash( images => $hash ); + } + else { + $hash->{id} = $id; + + # Don't overwrite the original add time + delete $hash->{added_time}; + + Slim::Schema->_updateHash( images => $hash, 'id' ); + } + + return $id; +} + +sub findhash { + my ( $class, $id ) = @_; + + my $sth = Slim::Schema->dbh->prepare_cached( qq{ + SELECT * FROM images WHERE hash = ? + } ); + + $sth->execute($id); + my $hash = $sth->fetchrow_hashref; + $sth->finish; + + return $hash || {}; +} + +1; + diff --git a/Slim/Schema/Storage.pm b/Slim/Schema/Storage.pm index fae89352019..63b45140f55 100644 --- a/Slim/Schema/Storage.pm +++ b/Slim/Schema/Storage.pm @@ -2,7 +2,7 @@ package Slim::Schema::Storage; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Schema/Track.pm b/Slim/Schema/Track.pm index ecde1cad898..96070fc5742 100644 --- a/Slim/Schema/Track.pm +++ b/Slim/Schema/Track.pm @@ -22,7 +22,7 @@ my $log = logger('database.info'); our @allColumns = (qw( id urlmd5 url content_type title titlesort titlesearch album primary_artist tracknum - timestamp filesize disc remote audio audio_size audio_offset year secs + timestamp added_time updated_time filesize disc remote audio audio_size audio_offset year secs cover cover_cached vbr_scale bitrate samplerate samplesize channels block_alignment endian bpm tagversion drm musicmagic_mixable musicbrainz_id lossless lyrics replay_gain replay_peak extid virtual @@ -289,6 +289,18 @@ sub modificationTime { return $self->buildModificationTime( $self->timestamp ); } +sub addedTime { + my $self = shift; + + return $self->buildModificationTime( $self->added_time ); +} + +sub lastUpdated { + my $self = shift; + + return $self->buildModificationTime( $self->updated_time ); +} + sub buildModificationTime { my ( $self, $time ) = @_; diff --git a/Slim/Schema/Video.pm b/Slim/Schema/Video.pm new file mode 100644 index 00000000000..938972d55f2 --- /dev/null +++ b/Slim/Schema/Video.pm @@ -0,0 +1,84 @@ +package Slim::Schema::Video; + +use strict; + +use File::Basename; +use Slim::Schema; +use Slim::Utils::Misc; + +# XXX DBIx::Class stuff needed? + +sub updateOrCreateFromResult { + my ( $class, $result ) = @_; + + my $id; + my $url = Slim::Utils::Misc::fileURLFromPath($result->path); + + # Create title and album from path + my ($title, $dirs, undef) = fileparse($result->path); + + # Album is parent directory + $dirs =~ s{\\}{/}g; + my ($album) = $dirs =~ m{([^/]+)/$}; + + my $sort = Slim::Utils::Text::ignoreCaseArticles($title); + my $search = Slim::Utils::Text::ignoreCaseArticles($title, 1); + my $now = time(); + + my $hash = { + url => $url, + hash => $result->hash, + title => $title, + titlesearch => $search, + titlesort => $sort, + album => $album, + video_codec => $result->codec, + audio_codec => 'TODO', + mime_type => $result->mime_type, + dlna_profile => $result->dlna_profile, + width => $result->width, + height => $result->height, + mtime => $result->mtime, + added_time => $now, + updated_time => $now, + filesize => $result->size, + secs => $result->duration_ms / 1000, + bitrate => $result->bitrate, + channels => 'TODO', + }; + + my $sth = Slim::Schema->dbh->prepare_cached('SELECT id FROM videos WHERE url = ?'); + $sth->execute($url); + ($id) = $sth->fetchrow_array; + $sth->finish; + + if ( !$id ) { + $id = Slim::Schema->_insertHash( videos => $hash ); + } + else { + $hash->{id} = $id; + + # Don't overwrite the original add time + delete $hash->{added_time}; + + Slim::Schema->_updateHash( videos => $hash, 'id' ); + } + + return $id; +} + +sub findhash { + my ( $class, $id ) = @_; + + my $sth = Slim::Schema->dbh->prepare_cached( qq{ + SELECT * FROM videos WHERE hash = ? + } ); + + $sth->execute($id); + my $hash = $sth->fetchrow_hashref; + $sth->finish; + + return $hash || {}; +} + +1; diff --git a/Slim/Utils/Accessor.pm b/Slim/Utils/Accessor.pm index 8e8a51e58b9..949e7c4efce 100644 --- a/Slim/Utils/Accessor.pm +++ b/Slim/Utils/Accessor.pm @@ -2,7 +2,7 @@ package Slim::Utils::Accessor; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -15,7 +15,7 @@ Slim::Utils::Accessor L - Simple accessors for Squeezebox Server objects based on Class::Accessor::Faster by Marty Pauley + Simple accessors for Logitech Media Server objects based on Class::Accessor::Faster by Marty Pauley In addition to simple scalar accessors provides methods to arrays and hashes by index/key as used by Client and Display objects =cut diff --git a/Slim/Utils/Alarm.pm b/Slim/Utils/Alarm.pm index b82968d9d55..ce79273ba79 100644 --- a/Slim/Utils/Alarm.pm +++ b/Slim/Utils/Alarm.pm @@ -4,7 +4,7 @@ use strict; # Max Spicer, May 2008 # This code is derived from code with the following copyright message: # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -35,7 +35,7 @@ Slim::Utils::Alarm; =head1 DESCRIPTION -This class implements Squeezebox Server alarms (alarm clock functionality) and provides methods for manipulating them. +This class implements alarms (alarm clock functionality) and provides methods for manipulating them. Two types of alarm are implemented - daily alarms and calendar alarms. Daily alarms have a time component and a specified subset of weekdays on which to sound e.g. 09:00 on Monday, Saturday and Sunday. Calendar alarms have a time specified as an epoch value, representing an absolute date and time on which they sound e.g. 09:30 on 21/4/2008. @@ -1183,7 +1183,7 @@ sub _timeout { =head2 init -Initialise Squeezebox Server alarm functionality. This should be called on server startup (probably from slimserver.pl). +Initialise Logitech Media Server alarm functionality. This should be called on server startup (probably from slimserver.pl). =cut diff --git a/Slim/Utils/AutoRescan.pm b/Slim/Utils/AutoRescan.pm index 6356e2440ac..b7d4751c4f8 100644 --- a/Slim/Utils/AutoRescan.pm +++ b/Slim/Utils/AutoRescan.pm @@ -1,6 +1,6 @@ package Slim::Utils::AutoRescan; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/AutoRescan/Linux.pm b/Slim/Utils/AutoRescan/Linux.pm index c9b503a83f7..0ea2510e48a 100644 --- a/Slim/Utils/AutoRescan/Linux.pm +++ b/Slim/Utils/AutoRescan/Linux.pm @@ -1,6 +1,6 @@ package Slim::Utils::AutoRescan::Linux; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/AutoRescan/OSX.pm b/Slim/Utils/AutoRescan/OSX.pm index 1ea175776b4..1b6551e3409 100644 --- a/Slim/Utils/AutoRescan/OSX.pm +++ b/Slim/Utils/AutoRescan/OSX.pm @@ -1,6 +1,6 @@ package Slim::Utils::AutoRescan::OSX; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/AutoRescan/Stat.pm b/Slim/Utils/AutoRescan/Stat.pm index 04858f29fa5..874b9290d88 100644 --- a/Slim/Utils/AutoRescan/Stat.pm +++ b/Slim/Utils/AutoRescan/Stat.pm @@ -1,6 +1,6 @@ package Slim::Utils::AutoRescan::Stat; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/AutoRescan/Stat/AIO.pm b/Slim/Utils/AutoRescan/Stat/AIO.pm index 7a1a02a0057..b7fd10d667a 100644 --- a/Slim/Utils/AutoRescan/Stat/AIO.pm +++ b/Slim/Utils/AutoRescan/Stat/AIO.pm @@ -2,7 +2,7 @@ package Slim::Utils::AutoRescan::Stat::AIO; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. diff --git a/Slim/Utils/AutoRescan/Stat/Async.pm b/Slim/Utils/AutoRescan/Stat/Async.pm index d789965cc2d..0144396e7b2 100644 --- a/Slim/Utils/AutoRescan/Stat/Async.pm +++ b/Slim/Utils/AutoRescan/Stat/Async.pm @@ -2,7 +2,7 @@ package Slim::Utils::AutoRescan::Stat::Async; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. diff --git a/Slim/Utils/AutoRescan/Win32.pm b/Slim/Utils/AutoRescan/Win32.pm index c02a0c8a66f..eca6bb55dfd 100644 --- a/Slim/Utils/AutoRescan/Win32.pm +++ b/Slim/Utils/AutoRescan/Win32.pm @@ -1,6 +1,6 @@ package Slim::Utils::AutoRescan::Win32; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/DateTime.pm b/Slim/Utils/DateTime.pm index edc79a56aca..dce2acdc85b 100644 --- a/Slim/Utils/DateTime.pm +++ b/Slim/Utils/DateTime.pm @@ -1,6 +1,6 @@ package Slim::Utils::DateTime; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Errno.pm b/Slim/Utils/Errno.pm index 9f0735abc3e..3c2f7e00d55 100644 --- a/Slim/Utils/Errno.pm +++ b/Slim/Utils/Errno.pm @@ -2,7 +2,7 @@ package Slim::Utils::Errno; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Firmware.pm b/Slim/Utils/Firmware.pm index c90326e83dd..e81e5b3696c 100644 --- a/Slim/Utils/Firmware.pm +++ b/Slim/Utils/Firmware.pm @@ -1,6 +1,6 @@ package Slim::Utils::Firmware; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/IPDetect.pm b/Slim/Utils/IPDetect.pm index 4177de0402b..bd604084493 100644 --- a/Slim/Utils/IPDetect.pm +++ b/Slim/Utils/IPDetect.pm @@ -2,7 +2,7 @@ package Slim::Utils::IPDetect; # $Id:$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Light.pm b/Slim/Utils/Light.pm index 37ce79429d0..9cee4ea90be 100644 --- a/Slim/Utils/Light.pm +++ b/Slim/Utils/Light.pm @@ -2,13 +2,13 @@ package Slim::Utils::Light; # $Id: $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. # This module provides some functions compatible with functions -# from the core Squeezebox Server code, without their overhead. +# from the core Logitech Media Server code, without their overhead. # These functions are called by helper applications like SqueezeTray # or the control panel. @@ -159,28 +159,37 @@ sub getPref { $prefFile = $serverPrefFile; } - my $ret; - - if (-r $prefFile) { - - if (open(PREF, $prefFile)) { + require YAML::Syck; + $YAML::Syck::ImplicitUnicode = 1; + + my $prefs = eval { YAML::Syck::LoadFile($prefFile) }; - local $_; - while () { - - # read YAML (server) and old style prefs (installer) - if (/^$pref(:| \=)? (.+)$/) { - $ret = $2; - $ret =~ s/^['"]//; - $ret =~ s/['"\s]*$//s; - last; - } - } + my $ret; - close(PREF); - } + if (!$@) { + $ret = $prefs->{$pref}; } +# if (-r $prefFile) { +# +# if (open(PREF, $prefFile)) { +# +# local $_; +# while () { +# +# # read YAML (server) and old style prefs (installer) +# if (/^$pref(:| \=)? (.+)$/) { +# $ret = $2; +# $ret =~ s/^['"]//; +# $ret =~ s/['"\s]*$//s; +# last; +# } +# } +# +# close(PREF); +# } +# } + return $ret; } diff --git a/Slim/Utils/Log.pm b/Slim/Utils/Log.pm index 97c6879fcba..18592a281f3 100644 --- a/Slim/Utils/Log.pm +++ b/Slim/Utils/Log.pm @@ -2,7 +2,7 @@ package Slim::Utils::Log; # $Id$ -# Squeezebox Server Copyright 2001-2009 Dan Sully, Logitech. +# Logitech Media Server Copyright 2001-2011 Dan Sully, Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -577,7 +577,7 @@ sub serverLogMode { =head2 scannerLogFile ( ) -Returns the location of Squeezebox Server's scanner log file. +Returns the location of Logitech Media Server's scanner log file. =cut @@ -587,7 +587,7 @@ sub scannerLogFile { =head2 getLogFiles ( ) -Returns a list of the the locations of Squeezebox Server's log files. +Returns a list of the the locations of Logitech Media Server's log files. =cut @@ -601,7 +601,7 @@ sub getLogFiles { =head2 scannerLogMode ( ) -Returns the logging mode of Squeezebox Server's scanner log file. +Returns the logging mode of Logitech Media Server's scanner log file. =cut @@ -611,7 +611,7 @@ sub scannerLogMode { =head2 perfmonLogFile ( ) -Returns the location of Squeezebox Server's performance monitor log file. +Returns the location of Logitech Media Server's performance monitor log file. =cut @@ -621,7 +621,7 @@ sub perfmonLogFile { =head2 perfmonLogMode ( ) -Returns the logging mode of Squeezebox Server's performance monitor log file. +Returns the logging mode of Logitech Media Server's performance monitor log file. =cut @@ -746,7 +746,7 @@ sub writeConfig { my $fh = $file->openw or return 0; print $fh "# This file is autogenerated by $class\n\n"; - print $fh "# If you wish to modify, make a copy and call Squeezebox Server\n"; + print $fh "# If you wish to modify, make a copy and call Logitech Media Server\n"; print $fh "# with the --logconf=customlog.conf option\n\n"; for my $line (sort keys %runningConfig) { diff --git a/Slim/Utils/MemoryUsage.pm b/Slim/Utils/MemoryUsage.pm index 4656e9c925b..0bb92cede9a 100644 --- a/Slim/Utils/MemoryUsage.pm +++ b/Slim/Utils/MemoryUsage.pm @@ -3,7 +3,7 @@ package Slim::Utils::MemoryUsage; # $Id$ # # This module is a merging of B::TerseSize and Apache::Status -# put together to work with Squeezebox Server by Dan Sully +# put together to work with Logitech Media Server by Dan Sully # # These are not the droids you're looking for. # diff --git a/Slim/Utils/Misc.pm b/Slim/Utils/Misc.pm index a64774e786d..d1dda8bdfea 100644 --- a/Slim/Utils/Misc.pm +++ b/Slim/Utils/Misc.pm @@ -2,7 +2,7 @@ package Slim::Utils::Misc; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -24,7 +24,7 @@ assert, bt, msg, msgf, errorMsg, specified =head1 DESCRIPTION L serves as a collection of miscellaneous utility - functions useful throughout Squeezebox Server and third party plugins. + functions useful throughout Logitech Media Server and third party plugins. =cut @@ -518,10 +518,10 @@ sub fixPath { # the only kind of absolute file we like is one in # the music directory or the playlist directory... - my $audiodir = Slim::Utils::Misc::getAudioDir(); + my $mediadirs = Slim::Utils::Misc::getMediaDirs(); my $savedplaylistdir = Slim::Utils::Misc::getPlaylistDir(); - if ($audiodir && $file =~ /^\Q$audiodir\E/) { + if (scalar @$mediadirs && grep { $file =~ /^\Q$_\E/ } @$mediadirs) { $fixed = $file; @@ -529,7 +529,7 @@ sub fixPath { $fixed = $file; - } elsif (Slim::Music::Info::isURL($file) && (!defined($audiodir) || ! -r catfile($audiodir, $file))) { + } elsif (Slim::Music::Info::isURL($file) && (!scalar @$mediadirs || !grep {-r catfile($_, $file)} @$mediadirs)) { $fixed = $file; @@ -568,6 +568,10 @@ sub fixPath { } else { + # XXX - don't know how to handle this case: should we even return an untested value? + my $audiodir = $mediadirs->[0]; + logBacktrace("Dealing with single audiodir ($audiodir) instead of mediadirs " . Data::Dump::dump($mediadirs)); + $file =~ s/\Q$audiodir\E//; $fixed = catfile($audiodir, $file); } @@ -649,7 +653,8 @@ sub getLibraryName { =cut sub getAudioDir { - return Slim::Utils::Unicode::encode_locale($prefs->get('audiodir')); + logBacktrace("getAudioDir is deprecated, use getAudioDirs instead"); + return getAudioDirs()->[0]; } =head2 getPlaylistDir() @@ -662,14 +667,73 @@ sub getPlaylistDir { return Slim::Utils::Unicode::encode_locale($prefs->get('playlistdir')); } +=head2 getMediaDirs() + + Returns an arrayref of all media directories. + +=cut + +sub getMediaDirs { + my $type = shift; + + my $mediadirs = getDirsPref('mediadirs'); + + if ($type) { + my $ignoreList = { map { $_, 1 } @{ getDirsPref({ + audio => 'ignoreInAudioScan', + video => 'ignoreInVideoScan', + image => 'ignoreInImageScan', + }->{$type}) } }; + + $mediadirs = [ grep { !$ignoreList->{$_} } @$mediadirs ]; + } + + return $mediadirs +} + +sub getAudioDirs { + return getMediaDirs('audio'); +} + +sub getVideoDirs { + return getMediaDirs('video'); +} + +sub getImageDirs { + return getMediaDirs('image'); +} + +sub getDirsPref { + return [ map { Slim::Utils::Unicode::encode_locale($_) } @{ $prefs->get($_[0]) || [''] } ]; +} + +=head2 inMediaFolder( $) + + Check if argument is an item contained in one of the media folder trees + +=cut + +sub inMediaFolder { + my $path = shift; + my $mediadirs = getMediaDirs(); + + foreach ( @$mediadirs ) { + return 1 if _checkInFolder($path, $_); + } + + return 0; +} + =head2 inAudioFolder( $) Check if argument is an item contained in the music folder tree =cut +# XXX - is this function even used any more? Can't find any caller... sub inAudioFolder { - return _checkInFolder(shift, getAudioDir()); + logBacktrace('inAudioFolder is deprecated, use inMediaFolder() instead'); + return inMediaFolder(shift); } =head2 inPlaylistFolder( $) @@ -931,21 +995,18 @@ sub findAndScanDirectoryTree { my $url = $params->{'url'}; - # make sure we have a valid URL... - if (!defined $url) { - $url = Slim::Utils::Misc::getAudioDir(); - } - - if (!Slim::Music::Info::isURL($url)) { - $url = fileURLFromPath($url); + if (defined $url) { + if (!Slim::Music::Info::isURL($url)) { + $url = fileURLFromPath($url); + } + + $topLevelObj = Slim::Schema->objectForUrl({ + 'url' => $url, + 'create' => 1, + 'readTags' => 1, + 'commit' => 1, + }); } - - $topLevelObj = Slim::Schema->objectForUrl({ - 'url' => $url, - 'create' => 1, - 'readTags' => 1, - 'commit' => 1, - }); } if (main::ISMAC && blessed($topLevelObj) && $topLevelObj->can('path')) { @@ -998,7 +1059,7 @@ sub findAndScanDirectoryTree { } # Now read the raw directory and return it. This should always be really fast. - my $items = [ readDirectory($path) ]; + my $items = [ readDirectory($path, $params->{typeRegEx}, $params->{excludeFile}) ]; my $count = scalar @$items; return ($topLevelObj, $items, $count); @@ -1082,7 +1143,7 @@ sub userAgentString { ($osDetails->{'osArch'} || 'Unknown'), $prefs->get('language'), Slim::Utils::Unicode::currentLocale(), - main::SLIM_SERVICE ? 'SqueezeNetwork' : 'SqueezeCenter, Squeezebox Server', + main::SLIM_SERVICE ? 'SqueezeNetwork' : 'SqueezeCenter, Squeezebox Server, Logitech Media Server', ); return $userAgentString; @@ -1162,7 +1223,7 @@ sub assert { =head2 bt( [ $return ] ) - Useful for tracking the source of a problem during the execution of Squeezebox Server. + Useful for tracking the source of a problem during the execution of the server. use bt() to output in the log a list of function calls leading up to the point where bt() has been used. @@ -1214,7 +1275,7 @@ sub bt { =head2 msg( $entry, [ $forceLog ], [ $suppressTimestamp ]) - Outputs an entry to the Squeezebox Server log file. + Outputs an entry to the server log file. $entry is a string for the log. optional argument $suppressTimestamp can be set to remove the event timestamp from the long entry. diff --git a/Slim/Utils/MySQLHelper.pm b/Slim/Utils/MySQLHelper.pm index 0c1042d85b0..8e22654a54a 100644 --- a/Slim/Utils/MySQLHelper.pm +++ b/Slim/Utils/MySQLHelper.pm @@ -554,7 +554,7 @@ sub dbh { =head2 createDatabase( $dbh ) -Creates the initial Squeezebox Server database in MySQL. +Creates the initial Logitech Media Server database in MySQL. 'CREATE DATABASE slimserver' @@ -642,7 +642,7 @@ sub pragma { } =head2 cleanup() -Shut down MySQL when Squeezebox Server is shut down. +Shut down MySQL when the server is shut down. =cut diff --git a/Slim/Utils/Network.pm b/Slim/Utils/Network.pm index 5676b6fe83a..2c9e1799e4a 100644 --- a/Slim/Utils/Network.pm +++ b/Slim/Utils/Network.pm @@ -2,7 +2,7 @@ package Slim::Utils::Network; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/OS.pm b/Slim/Utils/OS.pm index 6203173df53..e187ca31f10 100644 --- a/Slim/Utils/OS.pm +++ b/Slim/Utils/OS.pm @@ -2,7 +2,7 @@ package Slim::Utils::OS; # $Id: Base.pm 21790 2008-07-15 20:18:07Z andy $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -129,7 +129,7 @@ sub initMySQL { Return OS Specific directories. -Argument $dir is a string to indicate which of the Squeezebox Server directories we +Argument $dir is a string to indicate which of the Logitech Media Server directories we need information for. =cut @@ -365,7 +365,7 @@ sub setPriority { return unless defined $priority && $priority =~ /^-?\d+$/; # For *nix, including OSX, set whatever priority the user gives us. - Slim::Utils::Log::logger('server')->info("Squeezebox Server changing process priority to $priority"); + Slim::Utils::Log::logger('server')->info("Logitech Media Server changing process priority to $priority"); eval { setpriority (0, 0, $priority); }; @@ -394,7 +394,7 @@ sub getPriority { =head2 initUpdate( ) -Initialize download of a potential updated Squeezebox Server version. +Initialize download of a potential updated Logitech Media Server version. Not needed on Linux distributions which do manage the update through their repositories. =cut @@ -408,7 +408,7 @@ sub installerOS { '' }; =head2 directFirmwareDownload( ) -Return true if you don't want Squeezebox Server to download and cache firmware +Return true if you don't want the server to download and cache firmware upgrades for your players. It will then tell the player to download them directly from SqueezeNetwork. @@ -421,7 +421,7 @@ sub directFirmwareDownload { 0 }; =head2 restartServer( ) -Squeezebox Server can initiate a restart on some systems. +The server can initiate a restart on some systems. This should call main::cleanup() or stopServer() to cleanly shut down before restarting =cut diff --git a/Slim/Utils/OS/Debian.pm b/Slim/Utils/OS/Debian.pm index 0c5ae2611ba..d6d162959c5 100644 --- a/Slim/Utils/OS/Debian.pm +++ b/Slim/Utils/OS/Debian.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::Debian; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -32,7 +32,7 @@ sub initDetails { Return OS Specific directories. -Argument $dir is a string to indicate which of the Squeezebox Server directories we +Argument $dir is a string to indicate which of the server directories we need information for. =cut diff --git a/Slim/Utils/OS/Linux.pm b/Slim/Utils/OS/Linux.pm index 643492829fc..fded551d81f 100644 --- a/Slim/Utils/OS/Linux.pm +++ b/Slim/Utils/OS/Linux.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::Linux; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/OS/OSX.pm b/Slim/Utils/OS/OSX.pm index 90e04b42012..89462616b5a 100644 --- a/Slim/Utils/OS/OSX.pm +++ b/Slim/Utils/OS/OSX.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::OSX; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -135,7 +135,7 @@ sub initSearchPath { Return OS Specific directories. -Argument $dir is a string to indicate which of the Squeezebox Server directories we +Argument $dir is a string to indicate which of the Logitech Media Server directories we need information for. =cut @@ -188,20 +188,29 @@ sub dirsFor { push @dirs, $::prefsdir || catdir($ENV{'HOME'}, '/Library/Application Support/Squeezebox'); - } elsif ($dir eq 'music') { + } elsif ($dir =~ /^(?:music|videos|pictures)$/) { - my $musicDir = catdir($ENV{'HOME'}, 'Music', 'iTunes'); + my $mediaDir; - if (!-d $musicDir) { - $musicDir = catdir($ENV{'HOME'}, 'Music'); + if ($dir eq 'music') { + $mediaDir = catdir($ENV{'HOME'}, 'Music', 'iTunes'); + if (!-d $mediaDir) { + $mediaDir = catdir($ENV{'HOME'}, 'Music'); + } + } + elsif ($dir eq 'videos') { + $mediaDir = catdir($ENV{'HOME'}, 'Movies'); + } + elsif ($dir eq 'pictures') { + $mediaDir = catdir($ENV{'HOME'}, 'Pictures'); } # bug 1361 expand music folder if it's an alias, or SC won't start - if ( my $alias = $class->pathFromMacAlias($musicDir) ) { - $musicDir = $alias; + if ( my $alias = $class->pathFromMacAlias($mediaDir) ) { + $mediaDir = $alias; } - push @dirs, $musicDir; + push @dirs, $mediaDir; } elsif ($dir eq 'playlists') { diff --git a/Slim/Utils/OS/ReadyNAS.pm b/Slim/Utils/OS/ReadyNAS.pm index 61fd104d7ff..4e1b04f7915 100644 --- a/Slim/Utils/OS/ReadyNAS.pm +++ b/Slim/Utils/OS/ReadyNAS.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::ReadyNAS; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/OS/RedHat.pm b/Slim/Utils/OS/RedHat.pm index f6e084474e5..660f6abce16 100644 --- a/Slim/Utils/OS/RedHat.pm +++ b/Slim/Utils/OS/RedHat.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::RedHat; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -24,7 +24,7 @@ sub initDetails { Return OS Specific directories. -Argument $dir is a string to indicate which of the Squeezebox Server directories we +Argument $dir is a string to indicate which of the Logitech Media Server directories we need information for. =cut diff --git a/Slim/Utils/OS/SlimService.pm b/Slim/Utils/OS/SlimService.pm index 7543df0c940..17a75be2d68 100644 --- a/Slim/Utils/OS/SlimService.pm +++ b/Slim/Utils/OS/SlimService.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::SlimService; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/OS/SqueezeOS.pm b/Slim/Utils/OS/SqueezeOS.pm index a69a435333b..34bd265eb88 100644 --- a/Slim/Utils/OS/SqueezeOS.pm +++ b/Slim/Utils/OS/SqueezeOS.pm @@ -70,6 +70,8 @@ sub initPrefs { $defaults->{maxPlaylistLength} = 100; $defaults->{libraryname} = "Squeezebox Touch"; $defaults->{autorescan} = 1; + $defaults->{disabledextensionsvideo} = 'VIDEO'; # don't scan videos on SqueezeOS + $defaults->{disabledextensionsimages} = 'bmp, gif, png' # scaling down non-jpg might use too much memory } my %prefSyncHandlers = ( @@ -95,7 +97,7 @@ my %prefSyncHandlers = ( $prefs->set('shortdateFormat', $1); } - # Squeezeplay only knows 12 vs. 24h time, but no fancy formats as Squeezebox Server + # Squeezeplay only knows 12 vs. 24h time, but no fancy formats as Logitech Media Server $prefs->set('timeFormat', $$data =~ /hours="24"/ ? '%H:%M' : '|%I:%M %p'); $prefs = Slim::Utils::Prefs::preferences('plugin.datetime'); @@ -130,20 +132,20 @@ sub postInitPrefs { _checkMediaAtStartup($prefs); - $prefs->setChange( \&_onAudiodirChange, 'audiodir', 'FIRST' ); + $prefs->setChange( \&_onAudiodirChange, 'mediadirs', 'FIRST' ); $prefs->setChange( sub { _updateLibraryname($prefs); - }, 'language', 'audiodir' ); + }, 'language', 'mediadirs' ); $prefs->setChange( \&_onSNTimediffChange, 'sn_timediff'); if ( !main::SCANNER ) { - # sync up prefs in case they were changed while Squeezebox Server wasn't running + # sync up prefs in case they were changed while the server wasn't running foreach (keys %prefSyncHandlers) { _syncPrefs($_); } - # initialize prefs syncing between Squeezeplay and Squeezebox Server + # initialize prefs syncing between Squeezeplay and the server eval { require Linux::Inotify2; import Linux::Inotify2; @@ -168,7 +170,7 @@ sub postInitPrefs { ); }; - Slim::Utils::Log::logError("Squeezeplay <-> Squeezebox Server prefs syncing failed to initialize: $@") if ($@); + Slim::Utils::Log::logError("Squeezeplay <-> Server prefs syncing failed to initialize: $@") if ($@); } } @@ -181,8 +183,9 @@ sub _updateLibraryname { # remove media name $libraryname =~ s/ \(.*?(?:USB|SD).*?\)$//i; - - my $audiodir = Slim::Utils::Misc::getAudioDir(); + + # XXX - for the time being we're going to assume that the embedded server will only handle one folder + my $audiodir = Slim::Utils::Misc::getAudioDirs()->[0]; if ( $audiodir && $audiodir =~ m{/(mmcblk|sd[a-z]\d)}i ) { $libraryname = sprintf( "%s (%s)", $libraryname, Slim::Utils::Strings::getString($1 =~ /mmc/ ? 'SD' : 'USB') ); } @@ -213,7 +216,7 @@ sub sqlHelperClass { 'Slim::Utils::SQLiteHelper' } Return OS Specific directories. -Argument $dir is a string to indicate which of the Squeezebox Server directories we +Argument $dir is a string to indicate which of the server directories we need information for. =cut @@ -344,7 +347,7 @@ sub _setupMediaDir { }; } - $prefs->set( audiodir => $path ); + $prefs->set( mediadirs => [ $path ] ); $prefs->set( librarycachedir => "$path/.Squeezebox/cache" ); # Create a playlist dir if necessary @@ -369,8 +372,9 @@ sub _setupMediaDir { sub _onAudiodirChange { require Slim::Utils::Prefs; my $prefs = Slim::Utils::Prefs::preferences('server'); - - my $audiodir = Slim::Utils::Misc::getAudioDir(); + + # XXX - for the time being we're going to assume that the embedded server will only handle one folder + my $audiodir = Slim::Utils::Misc::getAudioDirs()->[0]; if ($audiodir) { if (_setupMediaDir($audiodir, $prefs)) { @@ -379,7 +383,7 @@ sub _onAudiodirChange { } else { # it is defined but not valid warn "$audiodir cannot be used"; - $prefs->set('audiodir', undef); + $prefs->set('mediadirs', []); } } } @@ -412,7 +416,7 @@ sub _checkMediaAtStartup { } # Something went wrong, don't use this audiodir - $prefs->set( audiodir => undef ); + $prefs->set('mediadirs', []); } # Update system time if difference between system and SN time is bigger than 15 seconds diff --git a/Slim/Utils/OS/Suse.pm b/Slim/Utils/OS/Suse.pm index b82fdc816c5..93ee8764ee1 100644 --- a/Slim/Utils/OS/Suse.pm +++ b/Slim/Utils/OS/Suse.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::Suse; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/OS/Synology.pm b/Slim/Utils/OS/Synology.pm index dd5b870bd52..7843dd3e7f4 100644 --- a/Slim/Utils/OS/Synology.pm +++ b/Slim/Utils/OS/Synology.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::Synology; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -10,14 +10,14 @@ package Slim::Utils::OS::Synology; # Synology DiskStation (DS) include a wide range of NAS devices based on # several architectures (PPC, ARM, PPCe500v2, ARMv5, and maybe others). They # all use a custom and minimal Linux system (Linux 2.6 based). There are (to my -# knowledge) three options to run Squeezebox Server on these devices: +# knowledge) three options to run Logitech Media Server on these devices: # # 1) flipflip's SlimServer on DiskStation (SSODS) provides a system -# (libc, Perl, tools etc.) spcifically to run Squeezebox Server. +# (libc, Perl, tools etc.) spcifically to run Logitech Media Server. # 2) Synology recently added Perl to its standard system and provides an -# add-on Squeezebox Server package (via the DSM Package Management). +# add-on Logitech Media Server package (via the DSM Package Management). # 3) "Optware", a package for feed for numerous add-on packages from the -# NSLU2-Linux project, provides a Squeezebox Server package and its dependencies. +# NSLU2-Linux project, provides a Logitech Media Server package and its dependencies. # # This module is trying to provide customisations for all these options. @@ -38,7 +38,7 @@ sub initDetails $class->{osDetails}->{isDiskStation} = 1; - # check how this Squeezebox Server is run on the DiskStation + # check how this Logitech Media Server is run on the DiskStation if (-f '/volume1/SSODS/etc/ssods/ssods.conf' && "@INC" =~ m{/volume1/SSODS/lib/perl}) { diff --git a/Slim/Utils/OS/Unix.pm b/Slim/Utils/OS/Unix.pm index f95a8c8557f..5c125367bfe 100644 --- a/Slim/Utils/OS/Unix.pm +++ b/Slim/Utils/OS/Unix.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::Unix; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -41,7 +41,7 @@ sub initSearchPath { Return OS Specific directories. -Argument $dir is a string to indicate which of the Squeezebox Server directories we +Argument $dir is a string to indicate which of the server directories we need information for. =cut diff --git a/Slim/Utils/OS/Win32.pm b/Slim/Utils/OS/Win32.pm index fc861b15282..06b65d1727b 100644 --- a/Slim/Utils/OS/Win32.pm +++ b/Slim/Utils/OS/Win32.pm @@ -1,6 +1,6 @@ package Slim::Utils::OS::Win32; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -152,13 +152,14 @@ sub dirsFor { push @dirs, $::prefsdir || $class->writablePath('prefs'); - } elsif ($dir =~ /^(?:music|playlists)$/) { + } elsif ($dir =~ /^(?:music|playlists|videos|pictures)$/) { my $path; # Windows Home Server offers a Music share which is more likely to be used # than the administrator's My Music folder - if ($class->{osDetails}->{isWHS}) { + # XXX - should we continue to support WHS? + if ($class->{osDetails}->{isWHS} && $dir =~ /^(?:music|playlists)$/) { my $objWMI = Win32::OLE->GetObject('winmgmts://./root/cimv2'); if ( $objWMI && (my $shares = $objWMI->InstancesOf('Win32_Share')) ) { @@ -191,7 +192,20 @@ sub dirsFor { undef $objWMI; } - $path = Win32::GetFolderPath(Win32::CSIDL_MYMUSIC) unless $path; + my $fallback; + + if ($dir =~ /^(?:music|playlists)$/) { + $path = Win32::GetFolderPath(Win32::CSIDL_MYMUSIC) unless $path; + $fallback = 'My Music'; + } + elsif ($dir eq 'videos') { + $path = Win32::GetFolderPath(Win32::CSIDL_MYVIDEO) unless $path; + $fallback = 'My Videos'; + } + elsif ($dir eq 'pictures') { + $path = Win32::GetFolderPath(Win32::CSIDL_MYPICTURES) unless $path; + $fallback = 'My Pictures'; + } # fall back if no path or invalid path is returned if (!$path || $path eq Win32::GetFolderPath(0)) { @@ -205,9 +219,9 @@ sub dirsFor { ); if (defined $swKey) { - if (!($path = $swKey->{'My Music'})) { + if (!($path = $swKey->{$fallback})) { if ($path = $swKey->{'Personal'}) { - $path = catdir($path, 'My Music'); + $path = catdir($path, $fallback); } } } @@ -355,7 +369,7 @@ sub ignoredItems { =head2 getDrives() -Returns a list of drives available to Squeezebox Server, filtering out floppy drives etc. +Returns a list of drives available to the server, filtering out floppy drives etc. =cut @@ -417,7 +431,7 @@ sub isDriveReady { =head2 installPath() -Returns the base installation directory of Squeezebox Server. +Returns the base installation directory of Logitech Media Server. =cut @@ -484,7 +498,7 @@ sub writablePath { else { # second attempt: use the Windows API (recommended by MS) - # use the "Common Application Data" folder to store Squeezebox Server configuration etc. + # use the "Common Application Data" folder to store Logitech Media Server configuration etc. $writablePath = Win32::GetFolderPath(Win32::CSIDL_COMMON_APPDATA); # fall back if no path or invalid path is returned @@ -647,7 +661,7 @@ sub setPriority { return; }; - Slim::Utils::Log::logger('server')->info("Squeezebox Server changing process priority to $priorityClassName"); + Slim::Utils::Log::logger('server')->info("Logitech Media Server changing process priority to $priorityClassName"); eval { $setPriorityClass->Call($processHandle, $priorityClass) }; @@ -798,7 +812,7 @@ sub getUpdateParams { return if main::SLIM_SERVICE || main::SCANNER; if (!$PerlSvc::VERSION) { - Slim::Utils::Log::logger('server.update')->info("Running Squeezebox Server from the source - don't download the update."); + Slim::Utils::Log::logger('server.update')->info("Running Logitech Media Server from the source - don't download the update."); return; } @@ -846,7 +860,7 @@ sub restartServer { if (!$class->canRestartServer()) { - $log->warn("Squeezebox Server can't be restarted automatically on Windows if run from the perl source."); + $log->warn("Logitech Media Server can't be restarted automatically on Windows if run from the perl source."); return; } @@ -865,7 +879,7 @@ sub restartServer { Win32::Process::DETACHED_PROCESS() | Win32::Process::CREATE_NO_WINDOW() | Win32::Process::NORMAL_PRIORITY_CLASS(), ".") ) { - $log->error("Couldn't restart Squeezebox Server service (squeezesvc)"); + $log->error("Couldn't restart Logitech Media Server service (squeezesvc)"); } } diff --git a/Slim/Utils/OSDetect.pm b/Slim/Utils/OSDetect.pm index a0efe64c04d..80d7ed881ff 100644 --- a/Slim/Utils/OSDetect.pm +++ b/Slim/Utils/OSDetect.pm @@ -2,7 +2,7 @@ package Slim::Utils::OSDetect; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -30,7 +30,7 @@ my ($os, $isWindows, $isMac, $isLinux); =head2 OS( ) -returns a string to indicate the detected operating system currently running Squeezebox Server. +returns a string to indicate the detected operating system currently running Logitech Media Server. =cut diff --git a/Slim/Utils/PerlRunTime.pm b/Slim/Utils/PerlRunTime.pm index 9733f7cb3d9..811f1907286 100644 --- a/Slim/Utils/PerlRunTime.pm +++ b/Slim/Utils/PerlRunTime.pm @@ -2,7 +2,7 @@ package Slim::Utils::PerlRunTime; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/PluginManager.pm b/Slim/Utils/PluginManager.pm index f68e90ccafc..a07e92abcba 100644 --- a/Slim/Utils/PluginManager.pm +++ b/Slim/Utils/PluginManager.pm @@ -1,6 +1,6 @@ package Slim::Utils::PluginManager; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Prefs.pm b/Slim/Utils/Prefs.pm index b182037bad8..007085b5690 100644 --- a/Slim/Utils/Prefs.pm +++ b/Slim/Utils/Prefs.pm @@ -100,7 +100,7 @@ Slim::Utils::OSDetect->getOS()->migratePrefsFolder($path); my $prefs = preferences('server'); # File paths need to be prepared in order to correctly read the file system -$prefs->setFilepaths(qw(audiodir playlistdir cachedir librarycachedir coverArt)); +$prefs->setFilepaths(qw(mediadirs ignoreInAudioScan ignoreInVideoScan ignoreInImageScan playlistdir cachedir librarycachedir coverArt)); =head2 preferences( $namespace ) @@ -159,7 +159,7 @@ sub init { 'rank-GAMES' => 20, # Server Settings - Basic 'language' => \&defaultLanguage, - 'audiodir' => \&defaultAudioDir, + 'mediadirs' => \&defaultMediaDirs, 'playlistdir' => \&defaultPlaylistDir, 'autorescan' => 0, 'autorescan_stat_interval' => 10, @@ -189,8 +189,13 @@ sub init { 'ratingImplementation' => 'LOCAL_RATING_STORAGE', # Server Settings - FileTypes 'disabledextensionsaudio' => '', + 'disabledextensionsvideo' => '', + 'disabledextensionsimages' => '', 'disabledextensionsplaylist' => '', 'disabledformats' => [], + 'ignoreInAudioScan' => [], + 'ignoreInVideoScan' => [], + 'ignoreInImageScan' => [], # Server Settings - Networking 'webproxy' => \&Slim::Utils::OSDetect::getProxy, 'httpport' => 9000, @@ -701,7 +706,7 @@ sub init { # set validation functions $prefs->setValidate( 'num', qw(displaytexttimeout browseagelimit remotestreamtimeout screensavertimeout itemsPerPage refreshRate thumbSize httpport bufferSecs remotestreamtimeout) ); - $prefs->setValidate( 'dir', qw(cachedir librarycachedir playlistdir audiodir artfolder) ); + $prefs->setValidate( 'dir', qw(cachedir librarycachedir playlistdir artfolder) ); $prefs->setValidate( 'array', qw(guessFileFormats titleFormat disabledformats) ); # allow users to set a port below 1024 on windows which does not require admin for this @@ -766,6 +771,26 @@ sub init { } }, 'coverArt', ); + + # mediadirs must be a list of unique, valid folders + $prefs->setValidate({ + validator => sub { + my $new = $_[1]; + return 0 if ref $new ne 'ARRAY'; + + # don't accept duplicate entries + my %seen; + return 0 if scalar ( grep { !$seen{$_}++ } @{$new} ) != scalar @$new; + + foreach (@{ $new }) { + if (! (-d $_ || (main::ISWINDOWS && -d Win32::GetANSIPathName($_)) || -d Slim::Utils::Unicode::encode_locale($_)) ) { + return 0; + } + } + + return 1; + } + }, 'mediadirs', 'ignoreInAudioScan', 'ignoreInVideoScan', 'ignoreInImageScan'); # set on change functions $prefs->setChange( \&Slim::Web::HTTP::adjustHTTPPort, 'httpport' ); @@ -793,10 +818,10 @@ sub init { if ( !main::SCANNER ) { $prefs->setChange( sub { - require Slim::Music::MusicFolderScan; - Slim::Music::MusicFolderScan->init; + require Slim::Media::MediaFolderScan; + Slim::Media::MediaFolderScan->init; Slim::Control::Request::executeRequest(undef, ['wipecache']); - }, 'audiodir'); + }, 'mediadirs'); } $prefs->setChange( sub { @@ -956,9 +981,9 @@ use File::Spec::Functions qw(:ALL); use Digest::MD5; sub makeSecuritySecret { - # each Squeezebox Server installation should have a unique, + # each Logitech Media Server installation should have a unique, # strongly random value for securitySecret. This routine - # will be called by the first time Squeezebox Server is started + # will be called by the first time the server is started # to "seed" the prefs file with a value for this installation my $hash = new Digest::MD5; @@ -980,14 +1005,42 @@ sub defaultLanguage { return Slim::Utils::OSDetect->getOS->getSystemLanguage; } -sub defaultAudioDir { - my $path = Slim::Utils::OSDetect::dirsFor('music'); +sub defaultMediaDirs { + my $audiodir = $prefs->get('audiodir'); - if ($path && -d $path) { - return $path; - } else { - return ''; + $prefs->remove('audiodir') if $audiodir; + + my @mediaDirs; + + # if an audiodir had been there before, configure LMS as we did in SBS: audio only + if ($audiodir) { + # set mediadirs to the former audiodir + push @mediaDirs, $audiodir; + + # add the audiodir to the list of sources to be ignored by the other scans + foreach ('ignoreInVideoScan', 'ignoreInImageScan') { + my $ignoreDirs = $prefs->get($_) || []; + + push @$ignoreDirs, $audiodir; + $prefs->set($_, $ignoreDirs); + } } + + # new LMS installation: default to all media folders + else { + # try to find the OS specific default folders for various media types + foreach my $medium ('music', 'videos', 'pictures') { + my $path = Slim::Utils::OSDetect::dirsFor($medium); + + main::DEBUGLOG && $log && $log->debug("Setting default path for medium '$medium' to '$path' if available."); + + if ($path && -d $path) { + push @mediaDirs, $path; + } + } + } + + return \@mediaDirs; } sub defaultPlaylistDir { diff --git a/Slim/Utils/Prefs/Base.pm b/Slim/Utils/Prefs/Base.pm index c6f03d3a4b7..af8e1a012f2 100644 --- a/Slim/Utils/Prefs/Base.pm +++ b/Slim/Utils/Prefs/Base.pm @@ -252,7 +252,12 @@ sub set { } if (main::ISWINDOWS && $root->{'filepathPrefs'}->{ $pref }) { - $new = Win32::GetANSIPathName($new); + if ( ref $new eq 'ARRAY' ) { + $new = [ map { Win32::GetANSIPathName($_) } @{ $new } ] + } + else { + $new = Win32::GetANSIPathName($new); + } } $class->{'prefs'}->{ $pref } = $new; diff --git a/Slim/Utils/Prefs/Namespace.pm b/Slim/Utils/Prefs/Namespace.pm index bbf66ef379c..dd363b2c233 100644 --- a/Slim/Utils/Prefs/Namespace.pm +++ b/Slim/Utils/Prefs/Namespace.pm @@ -191,7 +191,12 @@ sub setFilepaths { } if ( $class->{'prefs'}->{ $pref } ) { - $class->{'prefs'}->{ $pref } = Win32::GetANSIPathName($class->{'prefs'}->{ $pref }); + if ( ref $class->{'prefs'}->{ $pref } eq 'ARRAY' ) { + $class->{'prefs'}->{ $pref } = [ map { Win32::GetANSIPathName($_) } @{ $class->{'prefs'}->{ $pref } } ] + } + else { + $class->{'prefs'}->{ $pref } = Win32::GetANSIPathName($class->{'prefs'}->{ $pref }); + } } $class->{'filepathPrefs'}->{ $pref } = 1; diff --git a/Slim/Utils/Progress.pm b/Slim/Utils/Progress.pm index 7a2b81d4d7b..e011e2688af 100644 --- a/Slim/Utils/Progress.pm +++ b/Slim/Utils/Progress.pm @@ -2,7 +2,7 @@ package Slim::Utils::Progress; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. @@ -207,12 +207,13 @@ sub update { $elapsed = 0.01; } - my $rate = $done / $elapsed; - $self->rate($rate); + if ( my $rate = $done / $elapsed ) { + $self->rate($rate); - if ( my $total = $self->total ) { - # Calculate new ETA value if we know the total - $self->eta( int( ( $total - $done ) / $rate ) ); + if ( my $total = $self->total ) { + # Calculate new ETA value if we know the total + $self->eta( int( ( $total - $done ) / $rate ) ); + } } if ( $self->dball || $now > $self->dbup + UPDATE_DB_INTERVAL ) { diff --git a/Slim/Utils/SQLiteHelper.pm b/Slim/Utils/SQLiteHelper.pm index 80150fe6430..af38965458e 100644 --- a/Slim/Utils/SQLiteHelper.pm +++ b/Slim/Utils/SQLiteHelper.pm @@ -524,7 +524,7 @@ sub updateProgress { =head2 cleanup() -Shut down when Squeezebox Server is shut down. +Shut down when Logitech Media Server is shut down. =cut diff --git a/Slim/Utils/Scanner.pm b/Slim/Utils/Scanner.pm index 11978ad3063..2226a6984a3 100644 --- a/Slim/Utils/Scanner.pm +++ b/Slim/Utils/Scanner.pm @@ -2,7 +2,7 @@ package Slim::Utils::Scanner; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. @@ -148,14 +148,14 @@ sub findFilesMatching { $url = Slim::Utils::OS::Win32->fileURLFromShortcut($url) || next; $file = Slim::Utils::Misc::pathFromFileURL($url); - my $audiodir = Slim::Utils::Misc::getAudioDir(); + my $mediadirs = Slim::Utils::Misc::getMediaDirs(); # Bug: 2485: # Use Path::Class to determine if the file points to a # directory above us - if so, that's a loop and we need to break it. - if ( dir($file)->subsumes($topDir) || ($audiodir && dir($file)->subsumes($audiodir)) ) { + if ( dir($file)->subsumes($topDir) || ($mediadirs && grep { dir($file)->subsumes($_) } @$mediadirs) ) { - logWarning("Found an infinite loop! Breaking out: $file -> $topDir"); + logWarning("Found an infinite loop! Breaking out."); next; } diff --git a/Slim/Utils/Scanner/LMS.pm b/Slim/Utils/Scanner/LMS.pm new file mode 100644 index 00000000000..a9bf60e6e23 --- /dev/null +++ b/Slim/Utils/Scanner/LMS.pm @@ -0,0 +1,1244 @@ +package Slim::Utils::Scanner::LMS; + +# $Id: /sd/slim/7.6/branches/lms/server/Slim/Utils/Scanner/LMS.pm 78886 2011-07-26T15:15:45.375510Z andy $ +# +# Logitech Media Server Copyright 2001-2011 Logitech. +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License, version 2. +# +# This file is to migrate from Scanner::Local to Media::Scan-based scanning, +# where the module handles the file discovery, reporting progress, and so on. +# Eventually ::Local will be replaced with this module, when it supports audio formats. + +use strict; + +use File::Basename qw(basename dirname); +use File::Next; +use FileHandle; +use Media::Scan; +use Path::Class (); +use Scalar::Util qw(blessed); + +use Slim::Schema::Video; +use Slim::Schema::Image; +use Slim::Utils::ArtworkCache; +use Slim::Utils::Misc (); +use Slim::Utils::Log; +use Slim::Utils::Prefs; +use Slim::Utils::Progress; +use Slim::Utils::Scheduler; + +use constant PENDING_DELETE => 0x01; +use constant PENDING_NEW => 0x02; +use constant PENDING_CHANGED => 0x04; + +# If more than this many items are changed during a scan, the database is optimized +use constant OPTIMIZE_THRESHOLD => 100; + +my $log = logger('scan.scanner'); +my $prefs = preferences('server'); + +my %pending = (); + +# Coderefs to plugin handler functions +my $pluginHandlers = {}; + +sub hasAborted { + my ($progress, $no_async) = @_; + + if ( Slim::Music::Import->hasAborted() ) { + main::DEBUGLOG && $log->is_debug && $log->debug("Scan aborted"); + + if ( !main::SCANNER && !$no_async ) { + Slim::Music::Import->setAborted(0); + Slim::Music::Import->clearProgressInfo(); + Slim::Music::Import->setIsScanning(0); + Slim::Control::Request::notifyFromArray( undef, [ 'rescan', 'done' ] ); + } + + $progress && $progress->final; + return 1; + } +} + +sub rescan { + my ( $class, $in_paths, $args ) = @_; + + my $dbh = Slim::Schema->dbh; + + if ( ref $in_paths ne 'ARRAY' ) { + $in_paths = [ $in_paths ]; + } + + my $paths = []; + for my $p ( @{$in_paths} ) { + # Strip trailing slashes + $p =~ s{/$}{}; + + # Must make sure all scanned paths are raw bytes + push @{$paths}, Slim::Utils::Unicode::encode_locale($p); + } + + main::DEBUGLOG && $log->is_debug && $log->debug("Rescanning " . join(", ", @{$paths}) ); + + if ( !main::SCANNER ) { + my $type = 'SETUP_STANDARDRESCAN'; + if ( $args->{wipe} ) { + $type = 'SETUP_WIPEDB'; + } + elsif ( $args->{types} eq 'list' ) { + $type = 'SETUP_PLAYLISTRESCAN'; + } + + Slim::Music::Import->setIsScanning($type); + } + + #$pending{$next} = 0; + + # Initialize plugin hooks if any plugins want scan events. + # The API module is only loaded if a plugin uses it. + $pluginHandlers = {}; + + if ( Slim::Utils::Scanner::API->can('getHandlers') ) { + $pluginHandlers = Slim::Utils::Scanner::API->getHandlers(); + } + + # Keep track of the number of changes we've made so we can decide + # if we should optimize the database or not, and also so we know if + # we need to udpate lastRescanTime + my $changes = 0; + + my $ignore = [ + keys %{ Slim::Music::Info::disabledExtensions('image') }, + keys %{ Slim::Music::Info::disabledExtensions('video') }, + ]; + + # if we're dealing with one folder only, filter out unwanted media types + # XXX - unfortunately we can only do this for single folders, as Media::Scan would apply the filter to all folders + if ( scalar @$paths == 1 ) { + my $mediafolder = $paths->[0]; + + push @{$ignore}, 'VIDEO' if ( grep { $_ eq $mediafolder } @{ $prefs->get('ignoreInVideoScan') } ); + push @{$ignore}, 'IMAGE' if ( grep { $_ eq $mediafolder } @{ $prefs->get('ignoreInImageScan') } ); + } + + + my $progress; + if ( $args->{progress} ) { + $progress = Slim::Utils::Progress->new( { + type => 'importer', + name => join(', ', @$paths) . '|' . $args->{scanName} . '_media', + bar => 1, + } ); + } + + # AnyEvent watcher for async scans + my $watcher; + + # Media::Scan object + my $s; + + # Flag set when a scan has been aborted + my $aborted = 0; + + # This callback checks if the user has aborted the scan + my $abortCheck = sub { + if ( !$aborted && hasAborted($progress, $args->{no_async}) ) { + $s->abort; + $aborted = 1; + } + }; + + # Scan options + my $flags = MS_USE_EXTENSION; # Scan by extension only, no guessing + if ( $args->{wipe} ) { + $flags |= MS_CLEARDB | MS_FULL_SCAN; # Scan everything and clear the internal libmediascan database + } + else { + $flags |= MS_RESCAN | MS_INCLUDE_DELETED; # Only scan files that have changed size or timestamp, + # and notify us of files that have been deleted + } + + # Begin scan + $s = Media::Scan->new( $paths, { + loglevel => $log->is_debug ? MS_LOG_DEBUG : MS_LOG_ERR, # Set to MS_LOG_MEMORY for very verbose logging + async => $args->{no_async} ? 0 : 1, + flags => $flags, + cachedir => $prefs->get('librarycachedir'), + ignore => $ignore, + thumbnails => [ + { width => 300 }, # XXX + ], + on_result => sub { + my $result = shift; + + $changes++; + + # XXX flag for new/changed/deleted + new($result); + + $abortCheck->(); + }, + on_error => sub { + my $error = shift; + + $log->error( + 'ERROR SCANNING ' . $error->path . ': ' . $error->error_string + . '(code ' . $error->error_code . ')' + ); + + $abortCheck->(); + }, + on_progress => sub { + if ($progress) { + my $p = shift; + + my $total = $p->total; + + if ( $total && !$progress->total ) { + $progress->total( $total ); + } + + if ( $p->cur_item ) { + $progress->update( $p->cur_item, $p->done ); + } + + if ($total && $p->done && $p->done == $total) { + $progress->final($total); + } + } + + $abortCheck->(); + }, + on_finish => sub { + my $stats = {}; + #$changes = $stats->{change_count}; # XXX library should provide this? + + $progress && $progress->final; + + main::DEBUGLOG && $log->is_debug && $log->debug("Finished scanning"); + + # plugin hook + if ( my $handler = $pluginHandlers->{onFinishedHandler} ) { + $handler->($changes); + } + + # Update the last rescan time if any changes were made + if ($changes) { + main::DEBUGLOG && $log->is_debug && $log->debug("Scanner made $changes changes, updating last rescan timestamp"); + Slim::Music::Import->setLastScanTime(); + Slim::Schema->wipeCaches(); + } + + # Persist the count of "changes since last optimization" + # so for example adding 50 tracks, then 50 more would trigger optimize + my $totalChanges = $changes + _getChangeCount(); + if ( $totalChanges >= OPTIMIZE_THRESHOLD ) { + main::DEBUGLOG && $log->is_debug && $log->debug("Scan change count reached $changes, optimizing database"); + Slim::Schema->optimizeDB(); + _setChangeCount(0); + } + else { + _setChangeCount($totalChanges); + } + + if ( !main::SCANNER ) { + Slim::Music::Import->setIsScanning(0); + Slim::Control::Request::notifyFromArray( undef, [ 'rescan', 'done' ] ); + } + + if ( $args->{onFinished}) { + $args->{onFinished}->(); + } + + # Stop async watcher + undef $watcher; + }, + } ); + + if ( !main::SCANNER && $args->{no_async} ) { + # All done, send a done event + Slim::Music::Import->setIsScanning(0); + Slim::Schema->wipeCaches(); + Slim::Control::Request::notifyFromArray( undef, [ 'rescan', 'done' ] ); # XXX also needs the scan path? + } + + # Setup async scan monitoring + if ( !$args->{no_async} ) { + $watcher = AnyEvent->io( + fh => $s->async_fd, + poll => 'r', + cb => sub { + $s->async_process; + + if ($aborted) { + # Stop the IO watcher and destroy the Media::Scan object + undef $watcher; + undef $s; + } + }, + ); + } + + return $changes; + +=pod + # Get list of files within this path + Slim::Utils::Scanner::Local->find( $next, $args, sub { + my $count = shift; + my $others = shift || []; # other dirs we need to scan (shortcuts/aliases) + + my $basedir = Slim::Utils::Misc::fileURLFromPath($next); + + my $dbh = Slim::Schema->dbh; + + # Generate 3 lists of files: + + # 1. Files that no longer exist on disk + # and are not virtual (from a cue sheet) + my $inDBOnlySQL = qq{ + SELECT DISTINCT url + FROM tracks + WHERE url NOT IN ( + SELECT url FROM scanned_files + WHERE filesize != 0 + ) + AND url LIKE '$basedir%' + AND virtual IS NULL + AND content_type != 'dir' + }; + + # 2. Files that are new and not in the database. + my $onDiskOnlySQL = qq{ + SELECT DISTINCT url + FROM scanned_files + WHERE url NOT IN ( + SELECT url FROM tracks + ) + AND url LIKE '$basedir%' + AND filesize != 0 + }; + + # 3. Files that have changed mtime or size. + # XXX can this query be optimized more? + my $changedOnlySQL = qq{ + SELECT scanned_files.url + FROM scanned_files + JOIN tracks ON ( + scanned_files.url = tracks.url + AND ( + scanned_files.timestamp != tracks.timestamp + OR + scanned_files.filesize != tracks.filesize + ) + AND tracks.content_type != 'dir' + ) + WHERE scanned_files.url LIKE '$basedir%' + }; + + my ($inDBOnlyCount) = $dbh->selectrow_array( qq{ + SELECT COUNT(*) FROM ( $inDBOnlySQL ) AS t1 + } ); + + my ($onDiskOnlyCount) = $dbh->selectrow_array( qq{ + SELECT COUNT(*) FROM ( $onDiskOnlySQL ) AS t1 + } ); + + my ($changedOnlyCount) = $dbh->selectrow_array( qq{ + SELECT COUNT(*) FROM ( $changedOnlySQL ) AS t1 + } ); + + $log->error( "Removing deleted files ($inDBOnlyCount)" ) unless main::SCANNER && $main::progress; + + if ( $inDBOnlyCount ) { + my $inDBOnly = $dbh->prepare_cached($inDBOnlySQL); + $inDBOnly->execute; + + my $deleted; + $inDBOnly->bind_col(1, \$deleted); + + $pending{$next} |= PENDING_DELETE; + + my $progress; + if ( $args->{progress} ) { + $progress = Slim::Utils::Progress->new( { + type => 'importer', + name => $args->{scanName} . '_deleted', + bar => 1, + every => ($args->{scanName} && $args->{scanName} eq 'playlist'), # record all playists in the db + total => $inDBOnlyCount, + } ); + } + + my $handle_deleted = sub { + if ( $inDBOnly->fetch ) { + $progress && $progress->update($deleted); + $changes++; + + deleted($deleted); + + return 1; + } + else { + markDone( $next => PENDING_DELETE, $changes ) unless $args->{no_async}; + + $progress && $progress->final; + + return 0; + } + }; + + if ( $args->{no_async} ) { + my $i = 0; + while ( $handle_deleted->() ) { + if (++$i % 200 == 0) { + Slim::Schema->forceCommit; + } + } + } + else { + Slim::Utils::Scheduler::add_ordered_task( $handle_deleted ); + } + } + + $log->error( "Scanning new files ($onDiskOnlyCount)" ) unless main::SCANNER && $main::progress; + + if ( $onDiskOnlyCount ) { + my $onDiskOnly = $dbh->prepare_cached($onDiskOnlySQL); + $onDiskOnly->execute; + + my $new; + $onDiskOnly->bind_col(1, \$new); + + $pending{$next} |= PENDING_NEW; + + my $progress; + if ( $args->{progress} ) { + $progress = Slim::Utils::Progress->new( { + type => 'importer', + name => $args->{scanName} . '_new', + bar => 1, + every => ($args->{scanName} && $args->{scanName} eq 'playlist'), # record all playists in the db + total => $onDiskOnlyCount, + } ); + } + + my $handle_new = sub { + if ( $onDiskOnly->fetch ) { + $progress && $progress->update($new); + $changes++; + + new($new); + + return 1; + } + else { + markDone( $next => PENDING_NEW, $changes ) unless $args->{no_async}; + + $progress && $progress->final; + + return 0; + } + }; + + if ( $args->{no_async} ) { + my $i = 0; + while ( $handle_new->() ) { + if (++$i % 200 == 0) { + Slim::Schema->forceCommit; + } + } + } + else { + Slim::Utils::Scheduler::add_ordered_task( $handle_new ); + } + } + + $log->error( "Rescanning changed files ($changedOnlyCount)" ) unless main::SCANNER && $main::progress; + + if ( $changedOnlyCount ) { + my $changedOnly = $dbh->prepare_cached($changedOnlySQL); + $changedOnly->execute; + + my $changed; + $changedOnly->bind_col(1, \$changed); + + $pending{$next} |= PENDING_CHANGED; + + my $progress; + if ( $args->{progress} ) { + $progress = Slim::Utils::Progress->new( { + type => 'importer', + name => $args->{scanName} . '_changed', + bar => 1, + every => ($args->{scanName} && $args->{scanName} eq 'playlist'), # record all playists in the db + total => $changedOnlyCount, + } ); + } + + my $handle_changed = sub { + if ( $changedOnly->fetch ) { + $progress && $progress->update($changed); + $changes++; + + changed($changed); + + return 1; + } + else { + markDone( $next => PENDING_CHANGED, $changes ) unless $args->{no_async}; + + $progress && $progress->final; + + return 0; + } + }; + + if ( $args->{no_async} ) { + my $i = 0; + while ( $handle_changed->() ) { + if (++$i % 200 == 0) { + Slim::Schema->forceCommit; + } + } + } + else { + Slim::Utils::Scheduler::add_ordered_task( $handle_changed ); + } + } + + # Scan other directories found via shortcuts or aliases + if ( scalar @{$others} ) { + if ( $args->{no_async} ) { + $class->rescan( $others, $args ); + } + else { + Slim::Utils::Timers::setTimer( $class, AnyEvent->now, \&rescan, $others, $args ); + } + } + + # If nothing changed, send a rescan done event + elsif ( !$inDBOnlyCount && !$onDiskOnlyCount && !$changedOnlyCount ) { + if ( !main::SCANNER && !$args->{no_async} ) { + Slim::Music::Import->setIsScanning(0); + Slim::Control::Request::notifyFromArray( undef, [ 'rescan', 'done' ] ); + } + } + } ); +=cut + +} + +=pod +sub deleted { + my $url = shift; + + my $dbh = Slim::Schema->dbh; + + my $work; + + my $content_type = _content_type($url); + + if ( Slim::Music::Info::isSong($url, $content_type) ) { + $log->error("Handling deleted track $url") unless main::SCANNER && $main::progress; + + # XXX no DBIC objects + my $track = Slim::Schema->rs('Track')->search( url => $url )->single; + + if ( $track ) { + $work = sub { + my $album = $track->album; + my @contribs = $track->contributors->all; + my $year = $track->year; + my @genres = map { $_->id } $track->genres; + + # plugin hook + if ( my $handler = $pluginHandlers->{onDeletedTrackHandler} ) { + $handler->( { id => $track->id, obj => $track, url => $url } ); + } + + # delete() will cascade to: + # contributor_track + # genre_track + # comments + $track->delete; + + # Tell Contributors to rescan, if no other tracks left, remove contributor. + # This will also remove entries from contributor_track and contributor_album + for my $contrib ( @contribs ) { + Slim::Schema::Contributor->rescan( $contrib->id ); + } + + + if ( $album ) { + # Reset compilation status as it may have changed from VA -> non-VA + # due to this track being deleted. Also checks in_storage in case + # the album was deleted by the $album->rescan. + if ( $album->in_storage && $album->compilation ) { + $album->compilation(undef); + $album->update; + + # Re-check VA status for the album, + # this will also save the album + Slim::Schema->mergeSingleVAAlbum( $album->id ); + } + + # Tell Album to rescan, by looking for remaining tracks in album. If none, remove album. + Slim::Schema::Album->rescan( $album->id ); + } + + # Tell Year to rescan + if ( $year ) { + Slim::Schema::Year->rescan($year); + } + + # Tell Genre to rescan + Slim::Schema::Genre->rescan( @genres ); + }; + } + } + elsif ( Slim::Music::Info::isCUE($url, $content_type) ) { + $log->error("Handling deleted cue sheet $url") unless main::SCANNER && $main::progress; + + $work = sub { + my $sth = $dbh->prepare_cached( qq{ + SELECT * FROM tracks WHERE url = ? + } ); + $sth->execute($url); + my ($playlist) = $sth->fetchrow_hashref; + $sth->finish; + + # Get the list of all virtual tracks from the cue sheet + # This has to be done before deleting the playlist because + # it cascades to deleting the playlist_track entries + $sth = $dbh->prepare_cached( qq{ + SELECT id, album, year FROM tracks + WHERE url IN ( + SELECT track + FROM playlist_track + WHERE playlist = ? + ) + } ); + $sth->execute( $playlist->{id} ); + my $ptracks = $sth->fetchall_arrayref( {} ); + $sth->finish; + + # Bug 10636, FLAC+CUE doesn't use playlist_track entries for some reason + # so we need to find the virtual tracks by looking at the URL + if ( !scalar @{$ptracks} ) { + $sth = $dbh->prepare( qq{ + SELECT id, album, year + FROM tracks + WHERE url LIKE '$url#%' + AND virtual = 1 + } ); + $sth->execute; + $ptracks = $sth->fetchall_arrayref( {} ); + $sth->finish; + } + + # plugin hook + if ( my $handler = $pluginHandlers->{onDeletedPlaylistHandler} ) { + $handler->( { id => $playlist->{id}, url => $url } ); + } + + # Delete the playlist + # This will cascade to remove the playlist_track entries + $sth = $dbh->prepare_cached( qq{ + DELETE FROM tracks WHERE id = ? + } ); + $sth->execute( $playlist->{id} ); + + # Continue cue handling after playlist/playlist_tracks have been deleted + + # Get contributors for tracks before we delete them + my $ids = join( ',', map { $_->{id} } @{$ptracks} ); + my $contribs = $dbh->selectall_arrayref( qq{ + SELECT DISTINCT(contributor) + FROM contributor_track + WHERE track IN ($ids) + }, { Slice => {} } ); + + # Get genres for tracks before we delete them + my $genres = $dbh->selectall_arrayref( qq{ + SELECT DISTINCT(genre) + FROM genre_track + WHERE track IN ($ids) + }, { Slice => {} } ); + + # 1. Delete the virtual tracks from this cue sheet + # This will cascade to: + # contributor_track + # genre_track + # comments + $sth = $dbh->prepare_cached( qq{ + DELETE FROM tracks WHERE id = ? + } ); + for my $ptrack ( @{$ptracks} ) { + $sth->execute( $ptrack->{id} ); + } + $sth->finish; + + # 2. Rescan the album(s) created from the cue sheet + my %seen; + my @albums = grep { defined $_ && !$seen{$_}++ } map { $_->{album} } @{$ptracks}; + Slim::Schema::Album->rescan( @albums ); + + # 3. Rescan contributors created from the cue sheet + Slim::Schema::Contributor->rescan( map { $_->{contributor} } @{$contribs} ); + + # 4. Rescan genres created from the cue sheet + Slim::Schema::Genre->rescan( map { $_->{genre} } @{$genres} ); + + # 5. Rescan years created from the cue sheet + %seen = (); + my @years = grep { defined $_ && !$seen{$_}++ } map { $_->{year} } @{$ptracks}; + Slim::Schema::Year->rescan( @years ); + }; + } + elsif ( Slim::Music::Info::isList($url, $content_type) ) { + $log->error("Handling deleted playlist $url") unless main::SCANNER && $main::progress; + + $work = sub { + # Get the playlist details + my $sth = $dbh->prepare_cached( qq{ + SELECT * FROM tracks WHERE url = ? + } ); + $sth->execute($url); + my ($playlist) = $sth->fetchrow_hashref; + $sth->finish; + + # plugin hook + if ( my $handler = $pluginHandlers->{onDeletedPlaylistHandler} ) { + $handler->( { id => $playlist->{id}, url => $url } ); + } + + # Delete the playlist + # This will cascade to remove the playlist_track entries + $sth = $dbh->prepare_cached( qq{ + DELETE FROM tracks WHERE id = ? + } ); + $sth->execute( $playlist->{id} ); + }; + } + + if ( $work ) { + if ( $dbh->{AutoCommit} ) { + Slim::Schema->txn_do($work); + } + else { + $work->(); + } + } +} +=cut + +sub new { + my $result = shift; + + my $work; + + if ( $result->type == 1 ) { # Video + $work = sub { + main::INFOLOG && $log->is_info && !(main::SCANNER && $main::progress) && $log->info("Handling new video " . $result->path); + + my $id = Slim::Schema::Video->updateOrCreateFromResult($result); + + if ( !defined $id ) { + $log->error( 'ERROR SCANNING VIDEO ' . $result->path . ': ' . Slim::Schema->lastError ); + return; + } + + # plugin hook + # XXX document video handlers + if ( my $handler = $pluginHandlers->{onNewVideoHandler} ) { + $handler->( { id => $id, path => $result->path } ); + } + }; + } + elsif ( $result->type == 3 ) { # Image + $work = sub { + main::INFOLOG && $log->is_info && !(main::SCANNER && $main::progress) && $log->info("Handling new image " . $result->path); + + my $id = Slim::Schema::Image->updateOrCreateFromResult($result); + + if ( !defined $id ) { + $log->error( 'ERROR SCANNING IMAGE ' . $result->path . ': ' . Slim::Schema->lastError ); + return; + } + + # plugin hook + # XXX document image handlers + if ( my $handler = $pluginHandlers->{onNewImageHandler} ) { + $handler->( { id => $id, path => $result->path } ); + } + }; + } + else { + warn "File not scanned: " . Data::Dump::dump($result->as_hash) . "\n"; + } + + # Cache all thumbnails that were generated by Media::Scan + for my $thumb ( @{ $result->thumbnails } ) { + my $cached = { + content_type => $thumb->{codec} eq 'JPEG' ? 'jpg' : 'png', + mtime => $result->mtime, + original_path => $result->path, + data_ref => \$thumb->{data}, + }; + + my $width = $thumb->{width}; + my $height = $thumb->{height}; + + # XXX thumbs need refactoring to include width, height, type + # For now, only cache the first one. Cache uses /music/hash to + # take advantage of existing artwork code + my $key = 'music/' . $result->hash . "/cover_${width}x${width}_o"; + Slim::Utils::ArtworkCache->new->set( $key, $cached ); + + main::INFOLOG && $log->is_info && !(main::SCANNER && $main::progress) + && $log->info("Cached thumbnail for $key ($width x $height)"); + } + +=pod + if ( Slim::Music::Info::isSong($url) ) { + + # This costs too much to do all the time, and it fills the log + main::INFOLOG && $log->is_info && !(main::SCANNER && $main::progress) && $log->info("Handling new track $url"); + + $work = sub { + # We need to make a quick check to make sure this track has not already + # been entered due to being referenced in a cue sheet. + if ( _content_type($url) eq 'cur' ) { # cur = cue referenced + main::INFOLOG && $log->is_info && $log->info("Skipping track because it's referenced by a cue sheet"); + return; + } + + # Scan tags & create track row and other related rows. + my $trackid = Slim::Schema->updateOrCreateBase( { + url => $url, + readTags => 1, + new => 1, + checkMTime => 0, + commit => 0, + } ); + + if ( !defined $trackid ) { + $log->error( "ERROR SCANNING $url: " . Slim::Schema->lastError ); + return; + } + + # plugin hook + if ( my $handler = $pluginHandlers->{onNewTrackHandler} ) { + $handler->( { id => $trackid, url => $url } ); + } + + # XXX iTunes, use onNewTrack + }; + } + elsif ( + Slim::Music::Info::isCUE($url) + || + ( Slim::Music::Info::isPlaylist($url) && Slim::Utils::Misc::inPlaylistFolder($url) ) + ) { + # Only read playlist files if we're in the playlist dir. Read cue sheets from anywhere. + $log->error("Handling new playlist $url") unless main::SCANNER && $main::progress; + + $work = sub { + # XXX no DBIC objects + my $playlist = Slim::Schema->updateOrCreate( { + url => $url, + readTags => 1, + new => 1, + playlist => 1, + checkMTime => 0, + commit => 0, + attributes => { + MUSICMAGIC_MIXABLE => 1, + }, + } ); + + if ( !defined $playlist ) { + $log->error( "ERROR SCANNING $url: " . Slim::Schema->lastError ); + return; + } + + scanPlaylistFileHandle( + $playlist, + FileHandle->new( Slim::Utils::Misc::pathFromFileURL($url) ), + ); + + # plugin hook + if ( my $handler = $pluginHandlers->{onNewPlaylistHandler} ) { + $handler->( { id => $playlist->id, obj => $playlist, url => $url } ); + } + }; + } +=cut + + if ( $work ) { + if ( Slim::Schema->dbh->{AutoCommit} ) { + Slim::Schema->txn_do($work); + } + else { + $work->(); + } + } +} + +=pod XXX +sub changed { + my $url = shift; + + my $dbh = Slim::Schema->dbh; + + my $isDebug = main::DEBUGLOG && $log->is_debug; + + my $content_type = _content_type($url); + + if ( Slim::Music::Info::isSong($url, $content_type) ) { + $log->error("Handling changed track $url") unless main::SCANNER && $main::progress; + + my $work = sub { + # Fetch some original track, album, contributors, and genre information + # so we can compare with the new data and decide what other data needs to be refreshed + my $sth = $dbh->prepare_cached( qq{ + SELECT tracks.id, tracks.year, albums.id AS album_id, albums.artwork + FROM tracks + JOIN albums ON (tracks.album = albums.id) + WHERE tracks.url = ? + } ); + $sth->execute($url); + my $origTrack = $sth->fetchrow_hashref; + $sth->finish; + + my $orig = { + year => $origTrack->{year}, + }; + + # Fetch all contributor IDs used on the original track + $sth = $dbh->prepare_cached( qq{ + SELECT DISTINCT(contributor) FROM contributor_track WHERE track = ? + } ); + $sth->execute( $origTrack->{id} ); + $orig->{contribs} = $sth->fetchall_arrayref; + $sth->finish; + + # Fetch all genres used on the original track + $sth = $dbh->prepare_cached( qq{ + SELECT genre FROM genre_track WHERE track = ? + } ); + $sth->execute( $origTrack->{id} ); + $orig->{genres} = $sth->fetchall_arrayref; + $sth->finish; + + # Scan tags & update track row + # XXX no DBIC objects + my $track = Slim::Schema->updateOrCreate( { + url => $url, + readTags => 1, + checkMTime => 0, # not needed as we already know it's changed + commit => 0, + } ); + + if ( !defined $track ) { + $log->error( "ERROR SCANNING $url: " . Slim::Schema->lastError ); + return; + } + + # Tell Contributors to rescan, if no other tracks left, remove contributor. + # This will also remove entries from contributor_track and contributor_album + for my $contrib ( @{ $orig->{contribs} } ) { + Slim::Schema::Contributor->rescan( $contrib->[0] ); + } + + my $album = $track->album; + + # XXX Check for newer cover.jpg here? + + # Add/replace coverid + $track->coverid(undef); + $track->cover_cached(undef); + $track->update; + + # Make sure album.artwork points to this track, so the album + # uses the newest available artwork + if ( my $coverid = $track->coverid ) { + if ( $album->artwork ne $coverid ) { + $album->artwork($coverid); + } + } + + # Reset compilation status as it may have changed + if ( $album ) { + # XXX no longer works after album code ported to native DBI + $album->compilation(undef); + $album->update; + + # Auto-rescan mode, immediately merge VA + Slim::Schema->mergeSingleVAAlbum( $album->id ); + } + + # XXX + # Rescan comments + + # Rescan genre, to check for no longer used genres + my $origGenres = join( ',', sort map { $_->[0] } @{ $orig->{genres} } ); + my $newGenres = join( ',', sort map { $_->id } $track->genres ); + + if ( $origGenres ne $newGenres ) { + main::DEBUGLOG && $isDebug && $log->debug( "Rescanning changed genre(s) $origGenres -> $newGenres" ); + + Slim::Schema::Genre->rescan( @{ $orig->{genres} } ); + } + + # Bug 8034, Rescan years if year value changed, to remove the old year + if ( $orig->{year} != $track->year ) { + main::DEBUGLOG && $isDebug && $log->debug( "Rescanning changed year " . $orig->{year} . " -> " . $track->year ); + + Slim::Schema::Year->rescan( $orig->{year} ); + } + + # plugin hook + if ( my $handler = $pluginHandlers->{onChangedTrackHandler} ) { + $handler->( { id => $track->id, obj => $track, url => $url } ); + } + }; + + if ( Slim::Schema->dbh->{AutoCommit} ) { + Slim::Schema->txn_do($work); + } + else { + $work->(); + } + } + elsif ( Slim::Music::Info::isCUE($url, $content_type) ) { + $log->error("Handling changed cue sheet $url") unless main::SCANNER && $main::progress; + + # XXX could probably be more intelligent but this works for now + deleted($url); + new($url); + } + elsif ( Slim::Music::Info::isList($url, $content_type) ) { + $log->error("Handling changed playlist $url") unless main::SCANNER && $main::progress; + + # For a changed playlist, just delete it and then re-scan it + deleted($url); + new($url); + } +} +=cut + +=pod +# Check if we're done with all our rescan tasks +sub markDone { + my ( $path, $type, $changes ) = @_; + + main::DEBUGLOG && $log->is_debug && $log->debug("Finished scan type $type for $path"); + + $pending{$path} &= ~$type; + + # Check all pending tasks, make sure all are done before notifying + for my $task ( keys %pending ) { + if ( $pending{$task} > 0 ) { + return; + } + } + + main::DEBUGLOG && $log->is_debug && $log->debug("All rescan tasks finished (total changes: $changes)"); + + # plugin hook + if ( my $handler = $pluginHandlers->{onFinishedHandler} ) { + $handler->($changes); + } + + # Done with all tasks + if ( !main::SCANNER ) { + +//=pod + # try to autocomplete artwork from mysqueezebox.com + Slim::Music::Artwork->downloadArtwork( sub { +//=cut + + # Precache artwork, when done send rescan done event + Slim::Music::Artwork->precacheAllArtwork( sub { + # Update the last rescan time if any changes were made + if ($changes) { + main::DEBUGLOG && $log->is_debug && $log->debug("Scanner made $changes changes, updating last rescan timestamp"); + Slim::Music::Import->setLastScanTime(); + Slim::Schema->wipeCaches(); + } + + # Persist the count of "changes since last optimization" + # so for example adding 50 tracks, then 50 more would trigger optimize + $changes += _getChangeCount(); + if ( $changes >= OPTIMIZE_THRESHOLD ) { + main::DEBUGLOG && $log->is_debug && $log->debug("Scan change count reached $changes, optimizing database"); + Slim::Schema->optimizeDB(); + _setChangeCount(0); + } + else { + _setChangeCount($changes); + } + + Slim::Music::Import->setIsScanning(0); + Slim::Control::Request::notifyFromArray( undef, [ 'rescan', 'done' ] ); + } ); + } + + %pending = (); +} +=cut + +=head2 scanPlaylistFileHandle( $playlist, $playlistFH ) + +Scan a playlist filehandle using L. + +=cut + +=pod +sub scanPlaylistFileHandle { + my $playlist = shift; + my $playlistFH = shift || return; + + my $url = $playlist->url; + my $parentDir = undef; + + if (Slim::Music::Info::isFileURL($url)) { + + #XXX This was removed before in 3427, but it really works best this way + #XXX There is another method that comes close if this shouldn't be used. + $parentDir = Slim::Utils::Misc::fileURLFromPath( Path::Class::file($playlist->path)->parent ); + + main::DEBUGLOG && $log->is_debug && $log->debug("Will scan $url, base: $parentDir"); + } + + my @playlistTracks = Slim::Formats::Playlists->parseList( + $url, + $playlistFH, + $parentDir, + $playlist->content_type, + ); + + # Be sure to remove the reference to this handle. + if (ref($playlistFH) eq 'IO::String') { + untie $playlistFH; + } + + undef $playlistFH; + + if (scalar @playlistTracks) { + $playlist->setTracks(\@playlistTracks); + + # plugin hook + if ( my $handler = $pluginHandlers->{onNewTrackHandler} ) { + for my $track ( @playlistTracks ) { + $handler->( { id => $track->id, obj => $track, url => $track->url } ); + main::idleStreams(); + } + } + } + + # Create a playlist container + if (!$playlist->title) { + + my $title = Slim::Utils::Misc::unescape(basename($url)); + $title =~ s/\.\w{3}$//; + + $playlist->title($title); + $playlist->titlesort( Slim::Utils::Text::ignoreCaseArticles( $title ) ); + } + + # With the special url if the playlist is in the + # designated playlist folder. Otherwise, Dean wants + # people to still be able to browse into playlists + # from the Music Folder, but for those items not to + # show up under Browse Playlists. + # + # Don't include the Shoutcast playlists or cuesheets + # in our Browse Playlist view either. + my $ct = Slim::Schema->contentType($playlist); + + if (Slim::Music::Info::isFileURL($url) && Slim::Utils::Misc::inPlaylistFolder($url)) { + main::DEBUGLOG && $log->is_debug && $log->debug( "Playlist item $url changed from $ct to ssp content-type" ); + $ct = 'ssp'; + } + + $playlist->content_type($ct); + $playlist->update; + + # Copy playlist title to all items if they are remote URLs and do not already have a title + # XXX: still needed? + for my $track ( @playlistTracks ) { + if ( blessed($track) && $track->remote ) { + my $curTitle = $track->title; + if ( !$curTitle || Slim::Music::Info::isURL($curTitle) ) { + $track->title( $playlist->title ); + $track->update; + + if ( main::DEBUGLOG && $log->is_debug ) { + $log->debug( 'Playlist item ' . $track->url . ' given title ' . $track->title ); + } + } + } + } + + if ( main::DEBUGLOG && $log->is_debug ) { + + $log->debug(sprintf("Found %d items in playlist: ", scalar @playlistTracks)); + + for my $track (@playlistTracks) { + + $log->debug(sprintf(" %s", blessed($track) ? $track->url : '')); + } + } + + return wantarray ? @playlistTracks : \@playlistTracks; +} +=cut + +=pod +sub _content_type { + my $url = shift; + + my $sth = Slim::Schema->dbh->prepare_cached( qq{ + SELECT content_type FROM tracks WHERE url = ? + } ); + $sth->execute($url); + my ($content_type) = $sth->fetchrow_array; + $sth->finish; + + return $content_type || ''; +} +=cut + +sub _getChangeCount { + my $sth = Slim::Schema->dbh->prepare_cached("SELECT value FROM metainformation WHERE name = 'scanChangeCount'"); + $sth->execute; + my ($count) = $sth->fetchrow_array; + $sth->finish; + + return $count || 0; +} + +sub _setChangeCount { + my $changes = shift; + + my $dbh = Slim::Schema->dbh; + + my $sth = $dbh->prepare_cached("SELECT 1 FROM metainformation WHERE name = 'scanChangeCount'"); + $sth->execute; + if ( $sth->fetchrow_array ) { + my $sta = $dbh->prepare_cached( "UPDATE metainformation SET value = ? WHERE name = 'scanChangeCount'" ); + $sta->execute($changes); + } + else { + my $sta = $dbh->prepare_cached( "INSERT INTO metainformation (name, value) VALUES (?, ?)" ); + $sta->execute( 'scanChangeCount', $changes ); + } + + $sth->finish; +} + +1; + diff --git a/Slim/Utils/Scanner/Local.pm b/Slim/Utils/Scanner/Local.pm index fdbac61d4d9..092c07b783f 100644 --- a/Slim/Utils/Scanner/Local.pm +++ b/Slim/Utils/Scanner/Local.pm @@ -2,7 +2,7 @@ package Slim::Utils::Scanner::Local; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. diff --git a/Slim/Utils/Scanner/Local/AIO.pm b/Slim/Utils/Scanner/Local/AIO.pm index 376840b893f..c3547277f77 100644 --- a/Slim/Utils/Scanner/Local/AIO.pm +++ b/Slim/Utils/Scanner/Local/AIO.pm @@ -2,7 +2,7 @@ package Slim::Utils::Scanner::Local::AIO; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. @@ -38,7 +38,7 @@ sub find { if ( $args->{progress} ) { $progress = Slim::Utils::Progress->new( { type => 'importer', - name => $args->{scanName} ? 'discovering_' . $args->{scanName} : 'discovering_files', + name => $path . '|' . ($args->{scanName} ? 'discovering_' . $args->{scanName} : 'discovering_files'), } ); } diff --git a/Slim/Utils/Scanner/Local/Async.pm b/Slim/Utils/Scanner/Local/Async.pm index d4a3fade341..87483b0a632 100644 --- a/Slim/Utils/Scanner/Local/Async.pm +++ b/Slim/Utils/Scanner/Local/Async.pm @@ -2,7 +2,7 @@ package Slim::Utils::Scanner::Local::Async; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. # @@ -52,7 +52,7 @@ sub find { if ( $args->{progress} ) { $progress = Slim::Utils::Progress->new( { type => 'importer', - name => $args->{scanName} ? 'discovering_' . $args->{scanName} : 'discovering_files', + name => $path . '|' . ($args->{scanName} ? 'discovering_' . $args->{scanName} : 'discovering_files'), } ); } diff --git a/Slim/Utils/Scanner/Remote.pm b/Slim/Utils/Scanner/Remote.pm index 25f6dd6c816..5704165e9b6 100644 --- a/Slim/Utils/Scanner/Remote.pm +++ b/Slim/Utils/Scanner/Remote.pm @@ -2,7 +2,7 @@ package Slim::Utils::Scanner::Remote; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2. diff --git a/Slim/Utils/Scheduler.pm b/Slim/Utils/Scheduler.pm index 146d18286b7..70407df661f 100644 --- a/Slim/Utils/Scheduler.pm +++ b/Slim/Utils/Scheduler.pm @@ -2,7 +2,7 @@ package Slim::Utils::Scheduler; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/ServiceManager.pm b/Slim/Utils/ServiceManager.pm index b45099da082..2f503856430 100644 --- a/Slim/Utils/ServiceManager.pm +++ b/Slim/Utils/ServiceManager.pm @@ -1,6 +1,6 @@ package Slim::Utils::ServiceManager; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -64,7 +64,7 @@ sub init { return bless $self, $class; } -# Determine how the user wants to start Squeezebox Server +# Determine how the user wants to start Logitech Media Server sub getStartupType { return SC_STARTUP_TYPE_NONE; } diff --git a/Slim/Utils/ServiceManager/OSX.pm b/Slim/Utils/ServiceManager/OSX.pm index 5f5770100a4..03cd378a95f 100644 --- a/Slim/Utils/ServiceManager/OSX.pm +++ b/Slim/Utils/ServiceManager/OSX.pm @@ -1,6 +1,6 @@ package Slim::Utils::ServiceManager::OSX; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/ServiceManager/Win32.pm b/Slim/Utils/ServiceManager/Win32.pm index 52bf534b4d0..362b29bdcf7 100644 --- a/Slim/Utils/ServiceManager/Win32.pm +++ b/Slim/Utils/ServiceManager/Win32.pm @@ -1,6 +1,6 @@ package Slim::Utils::ServiceManager::Win32; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -32,7 +32,7 @@ sub init { return $class; } -# Determine how the user wants to start Squeezebox Server +# Determine how the user wants to start Logitech Media Server sub getStartupType { my %services; diff --git a/Slim/Utils/SoundCheck.pm b/Slim/Utils/SoundCheck.pm index 3013b743ad7..9459383bf6b 100644 --- a/Slim/Utils/SoundCheck.pm +++ b/Slim/Utils/SoundCheck.pm @@ -2,7 +2,7 @@ package Slim::Utils::SoundCheck; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Strings.pm b/Slim/Utils/Strings.pm index 8450a8215cc..de7b0402d93 100644 --- a/Slim/Utils/Strings.pm +++ b/Slim/Utils/Strings.pm @@ -2,7 +2,7 @@ package Slim::Utils::Strings; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Text.pm b/Slim/Utils/Text.pm index 51a09cc9b8c..b8bfa6051d9 100644 --- a/Slim/Utils/Text.pm +++ b/Slim/Utils/Text.pm @@ -5,7 +5,7 @@ package Slim::Utils::Text; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Timers.pm b/Slim/Utils/Timers.pm index 493a7e0f3a4..6eac851d187 100644 --- a/Slim/Utils/Timers.pm +++ b/Slim/Utils/Timers.pm @@ -2,7 +2,7 @@ package Slim::Utils::Timers; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/UPnPMediaServer.pm b/Slim/Utils/UPnPMediaServer.pm index 67f0518c5d4..abf64eeb737 100644 --- a/Slim/Utils/UPnPMediaServer.pm +++ b/Slim/Utils/UPnPMediaServer.pm @@ -1,6 +1,6 @@ package Slim::Utils::UPnPMediaServer; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -267,7 +267,7 @@ sub gotContainer { if ( $node =~ m{]*>([^<]+)} ) { $url = $1; - # If the UPnP server is running on the same PC as Squeezebox Server, URL may be localhost + # If the UPnP server is running on the same PC as the server, URL may be localhost if ( my ($host) = $url =~ /(127.0.0.1|localhost)/ ) { my $realIP = Slim::Utils::IPDetect::IP(); $url =~ s/$host/$realIP/; @@ -320,7 +320,7 @@ sub gotContainer { if ( $node =~ m{]*>([^<]+)} ) { $url = $1; - # If the UPnP server is running on the same PC as Squeezebox Server, URL may be localhost + # If the UPnP server is running on the same PC as the server, URL may be localhost if ( my ($host) = $url =~ /(127.0.0.1|localhost)/ ) { my $realIP = Slim::Utils::IPDetect::IP(); $url =~ s/$host/$realIP/; diff --git a/Slim/Utils/Update.pm b/Slim/Utils/Update.pm index 01e432a7533..72f25cb4298 100644 --- a/Slim/Utils/Update.pm +++ b/Slim/Utils/Update.pm @@ -25,8 +25,10 @@ my $versionFile; sub checkVersion { # clean up old download location - Slim::Utils::Misc::deleteFiles($prefs->get('cachedir'), qr/^(?:Squeezebox|SqueezeCenter).*\.(dmg|exe)(\.tmp)?$/i); + Slim::Utils::Misc::deleteFiles($prefs->get('cachedir'), qr/^(?:Squeezebox|SqueezeCenter|LogitechMediaServer).*\.(dmg|exe)(\.tmp)?$/i); +# XXX - disable update checks until we're set up on the server side +return; return unless $prefs->get('checkVersion'); $versionFile = catdir( scalar($os->dirsFor('updates')), 'server.version' ); @@ -99,7 +101,7 @@ sub checkVersionCB { my $version = Slim::Utils::Unicode::utf8decode( $http->content() ); chomp($version); - main::DEBUGLOG && $log->debug($version || 'No new Squeezebox Server version available'); + main::DEBUGLOG && $log->debug($version || 'No new Logitech Media Server version available'); # reset the update flag setUpdateInstaller(); @@ -107,7 +109,7 @@ sub checkVersionCB { # trigger download of the installer if available if ($version && $prefs->get('autoDownloadUpdate')) { - main::INFOLOG && $log->info('Triggering automatic Squeezebox Server update download...'); + main::INFOLOG && $log->info('Triggering automatic Logitech Media Server update download...'); getUpdate($version); } @@ -207,12 +209,12 @@ sub downloadAsyncDone { # make sure we got the file if (!-e $tmpFile) { - $log->warn("Squeezebox Server installer download failed: file '$tmpFile' not stored on disk?!?"); + $log->warn("Logitech Media Server installer download failed: file '$tmpFile' not stored on disk?!?"); return; } if (-s _ != $http->headers->content_length()) { - $log->warn( sprintf("Squeezebox Server installer file size mismatch: expected size %s bytes, actual size %s bytes", $http->headers->content_length(), -s _) ); + $log->warn( sprintf("Logitech Media Server installer file size mismatch: expected size %s bytes, actual size %s bytes", $http->headers->content_length(), -s _) ); unlink $tmpFile; return; } diff --git a/Slim/Utils/Validate.pm b/Slim/Utils/Validate.pm index 3ac3e6c85d3..8a962854076 100644 --- a/Slim/Utils/Validate.pm +++ b/Slim/Utils/Validate.pm @@ -2,7 +2,7 @@ package Slim::Utils::Validate; # $Id: Validate.pm 11972 2007-05-12 07:32:19Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Utils/Versions.pm b/Slim/Utils/Versions.pm index 555b9278610..f0480d96d29 100644 --- a/Slim/Utils/Versions.pm +++ b/Slim/Utils/Versions.pm @@ -2,7 +2,7 @@ package Slim::Utils::Versions; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License, version 2. diff --git a/Slim/Web/Cometd.pm b/Slim/Web/Cometd.pm index 23691780dbb..75cfcb403fb 100644 --- a/Slim/Web/Cometd.pm +++ b/Slim/Web/Cometd.pm @@ -2,7 +2,7 @@ package Slim::Web::Cometd; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -398,7 +398,7 @@ sub handler { } } elsif ( $obj->{channel} eq '/slim/subscribe' ) { - # A request to execute & subscribe to some Squeezebox Server event + # A request to execute & subscribe to some Logitech Media Server event # A valid /slim/subscribe message looks like this: # { @@ -482,7 +482,7 @@ sub handler { } } elsif ( $obj->{channel} eq '/slim/unsubscribe' ) { - # A request to unsubscribe from a Squeezebox Server event, this is not the same as /meta/unsubscribe + # A request to unsubscribe from a Logitech Media Server event, this is not the same as /meta/unsubscribe # A valid /slim/unsubscribe message looks like this: # { @@ -515,7 +515,7 @@ sub handler { }; } elsif ( $obj->{channel} eq '/slim/request' ) { - # A request to execute a one-time Squeezebox Server event + # A request to execute a one-time Logitech Media Server event # A valid /slim/request message looks like this: # { diff --git a/Slim/Web/Cometd/Manager.pm b/Slim/Web/Cometd/Manager.pm index d62b086b638..ca4c85f76cf 100644 --- a/Slim/Web/Cometd/Manager.pm +++ b/Slim/Web/Cometd/Manager.pm @@ -2,7 +2,7 @@ package Slim::Web::Cometd::Manager; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Graphics.pm b/Slim/Web/Graphics.pm index dc838cdcbed..3c5abd5d2c4 100644 --- a/Slim/Web/Graphics.pm +++ b/Slim/Web/Graphics.pm @@ -144,14 +144,19 @@ sub artworkRequest { # If path begins with "music" it's a cover path using either coverid # or the old trackid format - elsif ( $path =~ m{^music/([^/]+)/} ) { - my $id = $1; + elsif ( $path =~ m{^(music)/([^/]+)/} || $path =~ m{^(image)/([0-9a-f]{8})/} ) { + my ($type, $id) = ($1, $2); # Fetch the url and cover values my $sth; my ($url, $cover); - if ( $id =~ /^[0-9a-f]{8}$/ ) { + if ( $type eq 'image' ) { + $sth = Slim::Schema->dbh->prepare_cached( qq{ + SELECT url, hash FROM images WHERE hash = ? + } ); + } + elsif ( $id =~ /^[0-9a-f]{8}$/ ) { # ID is a coverid $sth = Slim::Schema->dbh->prepare_cached( qq{ SELECT url, cover FROM tracks WHERE coverid = ? @@ -199,7 +204,12 @@ sub artworkRequest { if ( !$url || !$cover ) { # Invalid ID or no cover available, use generic CD image - $path = $id =~ /^-/ ? 'html/images/radio_' : 'html/images/cover_'; + if ($type eq 'image') { + $path = 'html/images/icon_grey_'; + } + else { + $path = $id =~ /^-/ ? 'html/images/radio_' : 'html/images/cover_'; + } $path .= $spec; $path =~ s/\.\w+//; $path =~ s/_$//; @@ -226,10 +236,10 @@ sub artworkRequest { my $skin = $params->{skinOverride} || $prefs->get('skin'); $fullpath = $skinMgr->fixHttpPath($skin, $path); } - else { + elsif ( $path =~ /^music/ ) { # Image to resize is either a cover path or the audio file if cover is # a number (length of embedded art) - $fullpath = $cover =~ /^\d+$/ + $fullpath = ($cover =~ /^\d+$/ || $type eq 'image') ? Slim::Utils::Misc::pathFromFileURL($url) : $cover; } diff --git a/Slim/Web/HTTP.pm b/Slim/Web/HTTP.pm index b4823dc679f..264d85af58f 100644 --- a/Slim/Web/HTTP.pm +++ b/Slim/Web/HTTP.pm @@ -2,7 +2,7 @@ package Slim::Web::HTTP; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -557,7 +557,7 @@ sub processHTTP { # CSRF: make list of params passed by HTTP client my %csrfReqParams; - # XXX - unfortunately Squeezebox Server uses a query form + # XXX - unfortunately Logitech Media Server uses a query form # that can have a key without a value, yet it's # differnet from a key with an empty value. So we have # to parse out like this. @@ -645,7 +645,7 @@ sub processHTTP { $path =~ s|^/+||; - if ( !main::WEBUI || $path =~ m{^(?:html|music|plugins|apps|settings|firmware|clixmlbrowser)/}i || Slim::Web::Pages->isRawDownload($path) ) { + if ( !main::WEBUI || $path =~ m{^(?:html|music|video|image|plugins|apps|settings|firmware|clixmlbrowser)/}i || Slim::Web::Pages->isRawDownload($path) ) { # not a skin } elsif ($path =~ m|^([a-zA-Z0-9]+)$| && $skinMgr->isaSkin($1)) { @@ -983,7 +983,7 @@ sub generateHTTPResponse { $contentType = 'application/octet-stream'; } - if ( $path =~ /music\/\d+\/download/ ) { + if ( $path =~ /(?:music|video|image)\/[0-9a-f]+\/download/ ) { # Avoid generating templates for download URLs $contentType = 'application/octet-stream'; } @@ -1160,7 +1160,7 @@ sub generateHTTPResponse { return 0; - } elsif ($path =~ m{music/([^/]+)/(cover|thumb)} || + } elsif ($path =~ m{(?:image|music)/([^/]+)/(cover|thumb)} || $path =~ m{^plugins/cache/icons} || $path =~ /\/\w+_(X|\d+)x(X|\d+) (?:_([mpsSfFco]))? # resizeMode, given by a single character @@ -1222,17 +1222,31 @@ sub generateHTTPResponse { $response, ); - } elsif ($path =~ /music\/(\d+)\/download/) { + } elsif ($path =~ /(?:music|video|image)\/([0-9a-f]+)\/download/) { # Bug 10730 my $id = $1; - main::INFOLOG && $log->is_info && $log->info("Disabling keep-alive for file download"); - delete $keepAlives{$httpClient}; - Slim::Utils::Timers::killTimers( $httpClient, \&closeHTTPSocket ); - $response->header( Connection => 'close' ); + if ( $path =~ /music|video/ ) { + main::INFOLOG && $log->is_info && $log->info("Disabling keep-alive for large file download"); + delete $keepAlives{$httpClient}; + Slim::Utils::Timers::killTimers( $httpClient, \&closeHTTPSocket ); + $response->header( Connection => 'close' ); + } - if ( downloadMusicFile($httpClient, $response, $id) ) { - return 0; + if ( $path =~ /music/ ) { + if ( downloadMusicFile($httpClient, $response, $id) ) { + return 0; + } + } + elsif ( $path =~ /video/ ) { + if ( downloadVideoFile($httpClient, $response, $id) ) { + return 0; + } + } + elsif ( $path =~ /image/ ) { + if ( downloadImageFile($httpClient, $response, $id) ) { + return 0; + } } } elsif ($path =~ /(server|scanner|perfmon|log)\.(?:log|txt)/) { @@ -1664,7 +1678,7 @@ sub _stringifyHeaders { $data .= sprintf("%s %s %s%s", $response->protocol(), $code, HTTP::Status::status_message($code) || "", $CRLF); - $data .= sprintf("Server: Squeezebox Server (%s - %s)%s", $::VERSION, $::REVISION, $CRLF); + $data .= sprintf("Server: Logitech Media Server (%s - %s)%s", $::VERSION, $::REVISION, $CRLF); $data .= $response->headers_as_string($CRLF); @@ -2677,6 +2691,34 @@ sub downloadMusicFile { return; } +sub downloadVideoFile { + my ($httpClient, $response, $id) = @_; + + require Slim::Schema::Video; + my $video = Slim::Schema::Video->findhash($id); + + if ($video) { + Slim::Web::HTTP::sendStreamingFile( $httpClient, $response, $video->{mime_type}, Slim::Utils::Misc::pathFromFileURL($video->{url}) ); + return 1; + } + + return; +} + +sub downloadImageFile { + my ($httpClient, $response, $hash) = @_; + + require Slim::Schema::Image; + my $image = Slim::Schema::Image->findhash($hash); + + if ($image) { + Slim::Web::HTTP::sendStreamingFile( $httpClient, $response, $image->{mime_type}, Slim::Utils::Misc::pathFromFileURL($image->{url}) ); + return 1; + } + + return; +} + 1; __END__ diff --git a/Slim/Web/HTTP/CSRF.pm b/Slim/Web/HTTP/CSRF.pm index 436cb45a71f..55797b6cad8 100644 --- a/Slim/Web/HTTP/CSRF.pm +++ b/Slim/Web/HTTP/CSRF.pm @@ -1,8 +1,8 @@ package Slim::Web::HTTP::CSRF; -# $Id: $ +# $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -266,7 +266,7 @@ sub protectName { } -# normal Squeezebox Server commands can be accessed with URLs like +# normal Logitech Media Server commands can be accessed with URLs like # http://localhost:9000/status.html?p0=pause&player=00%3A00%3A00%3A00%3A00%3A00 # http://localhost:9000/status.html?command=pause&player=00%3A00%3A00%3A00%3A00%3A00 # Use the protectCommand() API to prevent CSRF attacks on commands -- including commands diff --git a/Slim/Web/JSONRPC.pm b/Slim/Web/JSONRPC.pm index a9ac84d50d9..570436a9585 100644 --- a/Slim/Web/JSONRPC.pm +++ b/Slim/Web/JSONRPC.pm @@ -2,7 +2,7 @@ package Slim::Web::JSONRPC; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages.pm b/Slim/Web/Pages.pm index ac8893a3678..4d35ae015d0 100644 --- a/Slim/Web/Pages.pm +++ b/Slim/Web/Pages.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/BrowseDB.pm b/Slim/Web/Pages/BrowseDB.pm index df75949622c..8fbaf16a27c 100644 --- a/Slim/Web/Pages/BrowseDB.pm +++ b/Slim/Web/Pages/BrowseDB.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::BrowseDB; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/Common.pm b/Slim/Web/Pages/Common.pm index 2024a7bb9d6..86afa25762d 100644 --- a/Slim/Web/Pages/Common.pm +++ b/Slim/Web/Pages/Common.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::Common; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -63,8 +63,11 @@ sub addLibraryStats { if (my $p = Slim::Schema->rs('Progress')->search({ 'type' => 'importer', 'active' => 1 })->first) { + my $name = $p->name; + $name =~ s/(.*)\|//; + $params->{'progress'} = { - 'name' => $p->name, + 'name' => $name, 'bar' => Slim::Web::Pages::Progress::progressBar($p, 40), 'obj' => $p, } diff --git a/Slim/Web/Pages/EditPlaylist.pm b/Slim/Web/Pages/EditPlaylist.pm index a162f0d3304..e7867eb10d6 100644 --- a/Slim/Web/Pages/EditPlaylist.pm +++ b/Slim/Web/Pages/EditPlaylist.pm @@ -1,6 +1,6 @@ package Slim::Web::Pages::EditPlaylist; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/History.pm b/Slim/Web/Pages/History.pm index 605bb818bb1..59f7493d504 100644 --- a/Slim/Web/Pages/History.pm +++ b/Slim/Web/Pages/History.pm @@ -1,6 +1,6 @@ package Slim::Web::Pages::History; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/Home.pm b/Slim/Web/Pages/Home.pm index cf490aece3c..e0c11f7746f 100644 --- a/Slim/Web/Pages/Home.pm +++ b/Slim/Web/Pages/Home.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::Home; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/Playlist.pm b/Slim/Web/Pages/Playlist.pm index 4788571ee06..4de4be96fbe 100644 --- a/Slim/Web/Pages/Playlist.pm +++ b/Slim/Web/Pages/Playlist.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::Playlist; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/Progress.pm b/Slim/Web/Pages/Progress.pm index 617f9b0358b..6aa2b31da82 100644 --- a/Slim/Web/Pages/Progress.pm +++ b/Slim/Web/Pages/Progress.pm @@ -51,10 +51,19 @@ sub progress { my $sec = $runtime - 3600 * $hrs - 60 * $mins; my $item = { - 'obj' => $p, + 'obj' => {}, 'bar' => $bar, 'time' => sprintf("%02d:%02d:%02d", $hrs, $mins, $sec), }; + + foreach ($p->columns) { + $item->{obj}->{$_} = $p->$_(); + } + + if ($p->name =~ /(.*)\|(.*)/) { + $item->{fullname} = string($2 . '_PROGRESS') . string('COLON') . ' ' . $1; + $item->{obj}->{name} = $2; + } $total_time += $runtime; diff --git a/Slim/Web/Pages/Search.pm b/Slim/Web/Pages/Search.pm index e2958d67e20..32b3f7e3c69 100644 --- a/Slim/Web/Pages/Search.pm +++ b/Slim/Web/Pages/Search.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::Search; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/Status.pm b/Slim/Web/Pages/Status.pm index 76238b5eaa0..d0b75be14c6 100644 --- a/Slim/Web/Pages/Status.pm +++ b/Slim/Web/Pages/Status.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::Status; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Pages/Trackinfo.pm b/Slim/Web/Pages/Trackinfo.pm index f27c2b3cddc..dcb8ee18572 100644 --- a/Slim/Web/Pages/Trackinfo.pm +++ b/Slim/Web/Pages/Trackinfo.pm @@ -2,7 +2,7 @@ package Slim::Web::Pages::Trackinfo; # $Id: Trackinfo.pm 30446 2010-03-31 12:11:29Z ayoung1 $ -# Squeezebox Server Copyright 2010 Logitech. +# Logitech Media Server Copyright 2003-2010 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings.pm b/Slim/Web/Settings.pm index 53e9613c3b6..ad668f41704 100644 --- a/Slim/Web/Settings.pm +++ b/Slim/Web/Settings.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Alarm.pm b/Slim/Web/Settings/Player/Alarm.pm index e3e3e17215c..fc47916996f 100644 --- a/Slim/Web/Settings/Player/Alarm.pm +++ b/Slim/Web/Settings/Player/Alarm.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Player::Alarm; # $Id: Basic.pm 10633 2006-11-09 04:26:27Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Audio.pm b/Slim/Web/Settings/Player/Audio.pm index 0e65b08bb66..476ed9a1b5f 100644 --- a/Slim/Web/Settings/Player/Audio.pm +++ b/Slim/Web/Settings/Player/Audio.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Player::Audio; # $Id: Basic.pm 10633 2006-11-09 04:26:27Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Basic.pm b/Slim/Web/Settings/Player/Basic.pm index 82eb9a737cc..2de0f777e79 100644 --- a/Slim/Web/Settings/Player/Basic.pm +++ b/Slim/Web/Settings/Player/Basic.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Player::Basic; # $Id: Basic.pm 10633 2006-11-09 04:26:27Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Display.pm b/Slim/Web/Settings/Player/Display.pm index 24451568071..2e7251dbc22 100644 --- a/Slim/Web/Settings/Player/Display.pm +++ b/Slim/Web/Settings/Player/Display.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Player::Display; # $Id: Basic.pm 10633 2006-11-09 04:26:27Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Menu.pm b/Slim/Web/Settings/Player/Menu.pm index bf1a9d14944..6176fdeca2b 100644 --- a/Slim/Web/Settings/Player/Menu.pm +++ b/Slim/Web/Settings/Player/Menu.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Player::Menu; # $Id: Basic.pm 10633 2006-11-09 04:26:27Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Remote.pm b/Slim/Web/Settings/Player/Remote.pm index b49482b9f18..cb674d8ae39 100644 --- a/Slim/Web/Settings/Player/Remote.pm +++ b/Slim/Web/Settings/Player/Remote.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Player::Remote; # $Id: Basic.pm 10633 2006-11-09 04:26:27Z kdf $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Player/Synchronization.pm b/Slim/Web/Settings/Player/Synchronization.pm index 5f0f77dfd09..f63ff856fce 100644 --- a/Slim/Web/Settings/Player/Synchronization.pm +++ b/Slim/Web/Settings/Player/Synchronization.pm @@ -1,6 +1,6 @@ package Slim::Web::Settings::Player::Synchronization; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Basic.pm b/Slim/Web/Settings/Server/Basic.pm index daca4da9016..41c6bfeac6f 100644 --- a/Slim/Web/Settings/Server/Basic.pm +++ b/Slim/Web/Settings/Server/Basic.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Basic; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -24,7 +24,7 @@ sub page { } sub prefs { - return ($prefs, qw(language audiodir playlistdir libraryname) ); + return ($prefs, qw(language playlistdir libraryname) ); } # FIXME - add importers back as these are in different namespaces... perhaps they should be in the server namespace... @@ -54,7 +54,7 @@ sub handler { $rescanType = [qw(rescan playlists)]; } - for my $pref (qw(audiodir playlistdir)) { + for my $pref (qw(playlistdir)) { my (undef, $ok) = $prefs->set($pref, $paramRef->{"pref_$pref"}); @@ -90,10 +90,26 @@ sub handler { $client->currentPlaylistChangeTime(Time::HiRes::time()); } } + + # handle paths + my @paths; + my %oldPaths = map { $_ => 1 } @{ $prefs->get('mediadirs') || [] }; + + for (my $i = 0; defined $paramRef->{"pref_mediadirs$i"}; $i++) { + if (my $path = $paramRef->{"pref_mediadirs$i"}) { + delete $oldPaths{$path}; + push @paths, $path; + } + } + + my $oldCount = scalar @{ $prefs->get('mediadirs') || [] }; + $prefs->set('mediadirs', \@paths) if keys %oldPaths || !$oldCount || scalar @paths != $oldCount; } $paramRef->{'newVersion'} = $::newVersion; $paramRef->{'languageoptions'} = Slim::Utils::Strings::languageOptions(); + + $paramRef->{'prefs'}->{ 'pref_mediadirs' } = [ @{ $prefs->get('mediadirs') || [] }, '' ]; return $class->SUPER::handler($client, $paramRef); } diff --git a/Slim/Web/Settings/Server/Behavior.pm b/Slim/Web/Settings/Server/Behavior.pm index 67f952309a1..b50a5ed9a0d 100644 --- a/Slim/Web/Settings/Server/Behavior.pm +++ b/Slim/Web/Settings/Server/Behavior.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Behavior; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Debugging.pm b/Slim/Web/Settings/Server/Debugging.pm index 6a24c98febe..bd70a10d998 100644 --- a/Slim/Web/Settings/Server/Debugging.pm +++ b/Slim/Web/Settings/Server/Debugging.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Debugging; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/FileSelector.pm b/Slim/Web/Settings/Server/FileSelector.pm index 84b0240d013..4b00bf84e2d 100644 --- a/Slim/Web/Settings/Server/FileSelector.pm +++ b/Slim/Web/Settings/Server/FileSelector.pm @@ -1,6 +1,6 @@ package Slim::Web::Settings::Server::FileSelector; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/FileTypes.pm b/Slim/Web/Settings/Server/FileTypes.pm index ee802249bda..3f09b8c20de 100644 --- a/Slim/Web/Settings/Server/FileTypes.pm +++ b/Slim/Web/Settings/Server/FileTypes.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::FileTypes; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -27,12 +27,41 @@ sub page { sub handler { my ($class, $client, $paramRef, $pageSetup) = @_; + my $ignoreFolders = { + audio => { map { $_, 1 } @{Slim::Utils::Misc::getDirsPref('ignoreInAudioScan')} }, + video => { map { $_, 1 } @{Slim::Utils::Misc::getDirsPref('ignoreInVideoScan')} }, + image => { map { $_, 1 } @{Slim::Utils::Misc::getDirsPref('ignoreInImageScan')} }, + }; + + $paramRef->{mediadirs} = []; + foreach ( @{Slim::Utils::Misc::getMediaDirs()} ) { + push @{$paramRef->{mediadirs}}, { + path => $_, + audio => $ignoreFolders->{audio}->{$_}, + video => $ignoreFolders->{video}->{$_}, + image => $ignoreFolders->{image}->{$_}, + } + } + # If this is a settings update if ($paramRef->{'saveSettings'}) { $prefs->set('disabledextensionsaudio', $paramRef->{'disabledextensionsaudio'}); + $prefs->set('disabledextensionsvideo', $paramRef->{'disabledextensionsvideo'}); + $prefs->set('disabledextensionsimages', $paramRef->{'disabledextensionsimages'}); $prefs->set('disabledextensionsplaylist', $paramRef->{'disabledextensionsplaylist'}); + for ( my $x = 0; $x < scalar @{ $paramRef->{mediadirs} }; $x++ ) { + $paramRef->{mediadirs}->[$x]->{audio} = $paramRef->{"pref_ignoreInAudioScan$x"} ? 0 : 1; + $paramRef->{mediadirs}->[$x]->{video} = $paramRef->{"pref_ignoreInVideoScan$x"} ? 0 : 1; + $paramRef->{mediadirs}->[$x]->{image} = $paramRef->{"pref_ignoreInImageScan$x"} ? 0 : 1; + } + + $prefs->set('ignoreInAudioScan', [ map { $_->{path} } grep { $_->{audio} } @{$paramRef->{mediadirs}} ]); + $prefs->set('ignoreInVideoScan', [ map { $_->{path} } grep { $_->{video} } @{$paramRef->{mediadirs}} ]); + $prefs->set('ignoreInImageScan', [ map { $_->{path} } grep { $_->{image} } @{$paramRef->{mediadirs}} ]); + + my %disabledformats = map { $_ => 1 } @{ $prefs->get('disabledformats') }; my @disabled = (); @@ -117,6 +146,8 @@ sub handler { $paramRef->{'formats'} = \@formats; $paramRef->{'disabledextensionsaudio'} = $prefs->get('disabledextensionsaudio'); + $paramRef->{'disabledextensionsvideo'} = $prefs->get('disabledextensionsvideo'); + $paramRef->{'disabledextensionsimages'} = $prefs->get('disabledextensionsimages'); $paramRef->{'disabledextensionsplaylist'} = $prefs->get('disabledextensionsplaylist'); return $class->SUPER::handler($client, $paramRef, $pageSetup); diff --git a/Slim/Web/Settings/Server/Index.pm b/Slim/Web/Settings/Server/Index.pm index e43f307b6b8..8ceccf9b61a 100644 --- a/Slim/Web/Settings/Server/Index.pm +++ b/Slim/Web/Settings/Server/Index.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Index; # $Id: UserInterface.pm 13299 2007-09-27 08:59:36Z mherger $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Network.pm b/Slim/Web/Settings/Server/Network.pm index 8ed100069f5..2207d027911 100644 --- a/Slim/Web/Settings/Server/Network.pm +++ b/Slim/Web/Settings/Server/Network.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Network; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Performance.pm b/Slim/Web/Settings/Server/Performance.pm index 6b75d8f24ef..cb0a43abf95 100644 --- a/Slim/Web/Settings/Server/Performance.pm +++ b/Slim/Web/Settings/Server/Performance.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Performance; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Plugins.pm b/Slim/Web/Settings/Server/Plugins.pm index d3b2a2db52c..74939a9b04c 100644 --- a/Slim/Web/Settings/Server/Plugins.pm +++ b/Slim/Web/Settings/Server/Plugins.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Plugins; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Security.pm b/Slim/Web/Settings/Server/Security.pm index db4755ee583..b598e5a15f7 100644 --- a/Slim/Web/Settings/Server/Security.pm +++ b/Slim/Web/Settings/Server/Security.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Security; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Software.pm b/Slim/Web/Settings/Server/Software.pm index 62edb0d1ef2..5540cb688c0 100644 --- a/Slim/Web/Settings/Server/Software.pm +++ b/Slim/Web/Settings/Server/Software.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Software; # $Id: Software.pm 15258 2007-12-13 15:29:14Z mherger $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/SqueezeNetwork.pm b/Slim/Web/Settings/Server/SqueezeNetwork.pm index 31fcc615d2a..35424647cb8 100644 --- a/Slim/Web/Settings/Server/SqueezeNetwork.pm +++ b/Slim/Web/Settings/Server/SqueezeNetwork.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::SqueezeNetwork; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Status.pm b/Slim/Web/Settings/Server/Status.pm index e41ed2fde98..83a04be1adc 100644 --- a/Slim/Web/Settings/Server/Status.pm +++ b/Slim/Web/Settings/Server/Status.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::Status; # $Id: Basic.pm 13299 2007-09-27 08:59:36Z mherger $ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/TextFormatting.pm b/Slim/Web/Settings/Server/TextFormatting.pm index dd45da4dc3e..3a385af773b 100644 --- a/Slim/Web/Settings/Server/TextFormatting.pm +++ b/Slim/Web/Settings/Server/TextFormatting.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::TextFormatting; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/UserInterface.pm b/Slim/Web/Settings/Server/UserInterface.pm index 7ee36632dc6..43cdb7bc8c1 100644 --- a/Slim/Web/Settings/Server/UserInterface.pm +++ b/Slim/Web/Settings/Server/UserInterface.pm @@ -2,7 +2,7 @@ package Slim::Web::Settings::Server::UserInterface; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Settings/Server/Wizard.pm b/Slim/Web/Settings/Server/Wizard.pm index 01e9287041e..5ad9219070d 100644 --- a/Slim/Web/Settings/Server/Wizard.pm +++ b/Slim/Web/Settings/Server/Wizard.pm @@ -1,6 +1,6 @@ package Slim::Web::Settings::Server::Wizard; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -22,7 +22,7 @@ my $log = Slim::Utils::Log->addLogCategory({ }); my $serverPrefs = preferences('server'); -my @prefs = ('audiodir', 'playlistdir'); +my @prefs = ('mediadirs', 'playlistdir'); sub page { return 'settings/server/wizard.html'; @@ -89,9 +89,10 @@ sub handler { if ($paramRef->{saveSettings}) { # if a scan is running and one of the music sources has changed, abort scan - if ($pref =~ /^(?:audiodir|playlistdir)$/ - && $paramRef->{$pref} ne $serverPrefs->get($pref) - && Slim::Music::Import->stillScanning) + if ( + ( ($pref eq 'playlistdir' && $paramRef->{$pref} ne $serverPrefs->get($pref)) + || ($pref eq 'mediadirs' && scalar (grep { $_ ne $paramRef->{$pref} } @{ $serverPrefs->get($pref) })) + ) && Slim::Music::Import->stillScanning ) { main::DEBUGLOG && $log->debug('Aborting running scan, as user re-configured music source in the wizard'); Slim::Music::Import->abortScan(); @@ -103,13 +104,25 @@ sub handler { $paramRef->{$pref} = $paramRef->{$pref} ? 0 : 1; } - $serverPrefs->set($pref, $paramRef->{$pref}); + if ($pref eq 'mediadirs') { + $serverPrefs->set($pref, [ $paramRef->{$pref} ]); + } + else { + $serverPrefs->set($pref, $paramRef->{$pref}); + } } if (main::DEBUGLOG && $log->is_debug) { $log->debug("$pref: " . $serverPrefs->get($pref)); } - $paramRef->{prefs}->{$pref} = $serverPrefs->get($pref); + + if ($pref eq 'mediadirs') { + my $mediadirs = $serverPrefs->get($pref); + $paramRef->{prefs}->{$pref} = scalar @$mediadirs ? $mediadirs->[0] : ''; + } + else { + $paramRef->{prefs}->{$pref} = $serverPrefs->get($pref); + } } $paramRef->{useiTunes} = preferences('plugin.itunes')->get('itunes'); diff --git a/Slim/Web/Setup.pm b/Slim/Web/Setup.pm index d20dd4f2cca..63cfefb90df 100644 --- a/Slim/Web/Setup.pm +++ b/Slim/Web/Setup.pm @@ -2,7 +2,7 @@ package Slim::Web::Setup; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Template/Context.pm b/Slim/Web/Template/Context.pm index b746ddfb447..6f91bd49ec0 100644 --- a/Slim/Web/Template/Context.pm +++ b/Slim/Web/Template/Context.pm @@ -2,7 +2,7 @@ package Slim::Web::Template::Context; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Template/NoWeb.pm b/Slim/Web/Template/NoWeb.pm index 09dd7321810..ebdaf3016ef 100644 --- a/Slim/Web/Template/NoWeb.pm +++ b/Slim/Web/Template/NoWeb.pm @@ -1,8 +1,8 @@ package Slim::Web::Template::NoWeb; -# $Id: $ +# $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/Template/SkinManager.pm b/Slim/Web/Template/SkinManager.pm index e29daec1d87..42f2c91308b 100644 --- a/Slim/Web/Template/SkinManager.pm +++ b/Slim/Web/Template/SkinManager.pm @@ -2,7 +2,7 @@ package Slim::Web::Template::SkinManager; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/Web/UPnPMediaServer.pm b/Slim/Web/UPnPMediaServer.pm index 19590e4d573..446391bd780 100644 --- a/Slim/Web/UPnPMediaServer.pm +++ b/Slim/Web/UPnPMediaServer.pm @@ -1,6 +1,6 @@ package Slim::Web::UPnPMediaServer; -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -163,7 +163,7 @@ sub gotContainer { my $infohref = 'href="' . $params->{webroot} . 'upnpinfo.html' . $args - . '&metadata=1"'; + . '&metadata=0"'; push @{ $params->{browse_items} }, { hierarchy => $hier, @@ -212,8 +212,9 @@ sub gotContainer { else { $output = Slim::Web::HTTP::filltemplatefile( 'browsedb.html', $params ); } - $callback->( $client, $params, $output, $httpClient, $response ); + } 1; + diff --git a/Slim/Web/XMLBrowser.pm b/Slim/Web/XMLBrowser.pm index a1eb1c1c70f..f5a1de49966 100644 --- a/Slim/Web/XMLBrowser.pm +++ b/Slim/Web/XMLBrowser.pm @@ -2,7 +2,7 @@ package Slim::Web::XMLBrowser; # $Id$ -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. diff --git a/Slim/bootstrap.pm b/Slim/bootstrap.pm index c38dad05541..23991865b96 100644 --- a/Slim/bootstrap.pm +++ b/Slim/bootstrap.pm @@ -2,7 +2,7 @@ package Slim::bootstrap; # $Id$ # -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2011 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, version 2 @@ -38,7 +38,7 @@ use Slim::Utils::OSDetect; # same, Dynaloader fails. # # The workaround is to munge @INC and eval'ing the known modules that -# we include with Squeezebox Server, first checking our CPAN path, then if +# we include with Logitech Media Server, first checking our CPAN path, then if # there are any modules that couldn't be loaded, splicing CPAN/ out, # and attempting to load the system version of the module. When we are # done, put our CPAN/ path back in @INC. @@ -204,7 +204,7 @@ If 7.6 is outdated by the time you read this, Replace "7.6" with the major versi You should never need to do this if you're on Windows or Mac OSX. If the installers don't work for you, ask for help and/or report a bug. -of Squeezebox Server you are running. +of Logitech Media Server you are running. ******* @@ -223,7 +223,7 @@ of Squeezebox Server you are running. my $failed = check_valid_versions(); if ( scalar keys %{$failed} ) { - print "The following CPAN modules were found but cannot work with Squeezebox Server:\n"; + print "The following CPAN modules were found but cannot work with Logitech Media Server:\n"; for my $module ( sort keys %{$failed} ) { if ( $failed->{$module}->{loaded} eq $failed->{$module}->{need} && $failed->{$module}->{msg} ) { @@ -238,7 +238,7 @@ of Squeezebox Server you are running. print "To fix this problem you have several options:\n"; print "1. Install the latest version of the module(s) using CPAN: sudo cpan Some::Module\n"; print "2. Update the module's package using apt-get, yum, etc.\n"; - print "3. Run the .tar.gz version of Squeezebox Server which includes all required CPAN modules.\n"; + print "3. Run the .tar.gz version of Logitech Media Server which includes all required CPAN modules.\n"; print "\n"; exit; @@ -294,8 +294,8 @@ sub tryModuleLoad { # NB: More FC5 / SELinux - in case the above chcon doesn't work. if ($@ =~ /cannot restore segment prot after reloc/) { - print STDERR "** Squeezebox Server Error:\n"; - print STDERR "** SELinux settings prevented Squeezebox Server from starting.\n"; + print STDERR "** Logitech Media Server Error:\n"; + print STDERR "** SELinux settings prevented Logitech Media Server from starting.\n"; print STDERR "** See http://wiki.slimdevices.com/index.cgi?RPM for more information.\n\n"; exit; } @@ -435,7 +435,7 @@ sub sigquit { exit(); } -# Aliased to END in Squeezebox Server & scanner, as Log::Log4perl installs an END +# Aliased to END in the server & scanner, as Log::Log4perl installs an END # handler, which needs to run last. sub theEND { diff --git a/cleanup.pl b/cleanup.pl index edc5137155d..7ac27ff86fa 100755 --- a/cleanup.pl +++ b/cleanup.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -ICPAN -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2009 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -13,7 +13,7 @@ require 5.008_001; -use constant SPLASH_LOGO => 'logitech-squeezebox.png'; +use constant SPLASH_LOGO => 'logitech-media-server.png'; # don't use Wx, if script is run using perl on OSX, it needs to be run using wxperl my $splash; diff --git a/convert.conf b/convert.conf index b2302950bb1..0df33e2ff76 100644 --- a/convert.conf +++ b/convert.conf @@ -3,8 +3,8 @@ # Configuration file for transcoding # # If you wish to create custom transcoding entries that won't be overwritten -# by a new release of Squeezebox Server, create a custom-convert.conf file in the -# Squeezebox Server root directory, or the root of the Plugins directory. +# by a new release of Logitech Media Server, create a custom-convert.conf file in the +# Logitech Media Server root directory, or the root of the Plugins directory. # # On Debian, you can also create this file in # /etc/slimserver/custom-convert.conf # diff --git a/lib/README b/lib/README index adb3fafc05b..c868e382ad0 100644 --- a/lib/README +++ b/lib/README @@ -1,11 +1,11 @@ -$Id$ +$Id: /sd/slim/7.6/branches/lms/server/lib/README 78224 2011-06-22T16:26:39.511256Z mherger $ ------ -This directory contains library modules from CPAN which have been modified for Squeezebox Server. +This directory contains library modules from CPAN which have been modified for Logitech Media Server. We've made every effort to send patches to the upstream authors, but either -the changes are Squeezebox Server specific, or we simply haven't heard back from +the changes are Logitech Media Server specific, or we simply haven't heard back from the author, reside in a separate directory than the pristine top level CPAN/ dir. If a patch has been accepted by the author, then the module should be moved diff --git a/modules.conf b/modules.conf index 832e845c730..3cd9d85b384 100644 --- a/modules.conf +++ b/modules.conf @@ -1,5 +1,5 @@ # This file contains required minimum module versions and is checked -# every time Squeezebox Server starts up. +# every time Logitech Media Server starts up. # # Format: # [ ] @@ -28,6 +28,7 @@ JSON::XS 2.3 JSON::XS::VersionOneAndTwo 0.31 Log::Log4perl 1.23 LWP 5.805 +Media::Scan 0.01 Path::Class 0.17 Proc::Background 1.08 SQL::Abstract 1.56 diff --git a/scanner.pl b/scanner.pl index 6aa38633687..387b9492aaa 100755 --- a/scanner.pl +++ b/scanner.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2009 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -71,7 +71,6 @@ BEGIN use Slim::Utils::Prefs; use Slim::Music::Import; use Slim::Music::Info; -use Slim::Music::MusicFolderScan; use Slim::Music::PlaylistFolderScan; use Slim::Player::ProtocolHandlers; use Slim::Utils::Misc; @@ -80,6 +79,7 @@ BEGIN use Slim::Utils::Progress; use Slim::Utils::Scanner; use Slim::Utils::Strings qw(string); +use Slim::Media::MediaFolderScan; if ( INFOLOG || DEBUGLOG ) { require Data::Dump; @@ -193,7 +193,7 @@ sub main { ($REVISION, $BUILDDATE) = Slim::Utils::Misc::parseRevision(); - $log->error("Starting Squeezebox Server scanner (v$VERSION, r$REVISION, $BUILDDATE) perl $]"); + $log->error("Starting Logitech Media Server scanner (v$VERSION, r$REVISION, $BUILDDATE) perl $]"); # Bring up strings, database, etc. initializeFrameworks($log); @@ -214,7 +214,7 @@ sub main { } if ( $sqlHelperClass ) { - main::INFOLOG && $log->info("Squeezebox Server SQL init..."); + main::INFOLOG && $log->info("Server SQL init..."); $sqlHelperClass->init(); } @@ -251,8 +251,8 @@ sub main { } else { + Slim::Media::MediaFolderScan->init; Slim::Music::PlaylistFolderScan->init; - Slim::Music::MusicFolderScan->init; } # Load any plugins that define import modules @@ -262,7 +262,7 @@ sub main { checkDataSource(); - main::INFOLOG && $log->info("Squeezebox Server Scanner done init...\n"); + main::INFOLOG && $log->info("Scanner done init...\n"); # Perform pre-scan steps specific to the database type, i.e. SQLite needs to copy to a new file $sqlHelperClass->beforeScan(); @@ -371,23 +371,23 @@ sub main { sub initializeFrameworks { my $log = shift; - main::INFOLOG && $log->info("Squeezebox Server OSDetect init..."); + main::INFOLOG && $log->info("Server OSDetect init..."); Slim::Utils::OSDetect::init(); Slim::Utils::OSDetect::getOS->initSearchPath(); - # initialize Squeezebox Server subsystems - main::INFOLOG && $log->info("Squeezebox Server settings init..."); + # initialize Server subsystems + main::INFOLOG && $log->info("Server settings init..."); Slim::Utils::Prefs::init(); Slim::Utils::Prefs::makeCacheDir(); - main::INFOLOG && $log->info("Squeezebox Server strings init..."); + main::INFOLOG && $log->info("Server strings init..."); Slim::Utils::Strings::init(catdir($Bin,'strings.txt'), "EN"); - main::INFOLOG && $log->info("Squeezebox Server Info init..."); + main::INFOLOG && $log->info("Server Info init..."); Slim::Music::Info::init(); @@ -464,13 +464,18 @@ sub cleanup { } sub checkDataSource { - my $audiodir = Slim::Utils::Misc::getAudioDir(); + my $mediadirs = Slim::Utils::Misc::getMediaDirs(); + my $modified = 0; - if (defined $audiodir && $audiodir =~ m|[/\\]$|) { - $audiodir =~ s|[/\\]$||; - $prefs->set('audiodir',$audiodir); + foreach my $audiodir (@$mediadirs) { + if (defined $audiodir && $audiodir =~ m|[/\\]$|) { + $audiodir =~ s|[/\\]$||; + $modified++; + } } + $prefs->set('mediadirs', $mediadirs) if $modified; + return if !Slim::Schema::hasLibrary(); $sqlHelperClass->checkDataSource(); diff --git a/slimserver.pl b/slimserver.pl index de76b6cfbc6..e442c464eda 100755 --- a/slimserver.pl +++ b/slimserver.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Squeezebox Server Copyright 2001-2009 Logitech. +# Logitech Media Server Copyright 2001-2009 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -36,8 +36,8 @@ package PerlSvc; our %Config = ( - DisplayName => 'Squeezebox Server', - Description => "Squeezebox Server - streaming music server", + DisplayName => 'Logitech Media Server', + Description => "Logitech Media Server - streaming media server", ServiceName => "squeezesvc", StartNow => 0, ); @@ -346,7 +346,7 @@ sub init { my $log = logger('server'); - $log->error("Starting Squeezebox Server (v$VERSION, r$REVISION, $BUILDDATE) perl $]"); + $log->error("Starting Logitech Media Server (v$VERSION, r$REVISION, $BUILDDATE) perl $]"); if ($diag) { eval "use diagnostics"; @@ -369,13 +369,13 @@ sub init { Slim::Utils::OSDetect::init(); - # initialize Squeezebox Server subsystems + # initialize server subsystems initSettings(); # Redirect STDERR to the log file. tie *STDERR, 'Slim::Utils::Log::Trapper'; - main::INFOLOG && $log->info("Squeezebox Server OS Specific init..."); + main::INFOLOG && $log->info("OS Specific init..."); unless (main::ISWINDOWS) { $SIG{'HUP'} = \&initSettings; @@ -409,7 +409,7 @@ sub init { # background if requested if (!main::ISWINDOWS && $daemon) { - main::INFOLOG && $log->info("Squeezebox Server daemonizing..."); + main::INFOLOG && $log->info("Server daemonizing..."); daemonize(); } else { @@ -422,7 +422,7 @@ sub init { # Change UID/GID after the pid & logfiles have been opened. unless (Slim::Utils::OSDetect::getOS->dontSetUserAndGroup() || defined($user) eq "root") { - main::INFOLOG && $log->info("Squeezebox Server settings effective user and group if requested..."); + main::INFOLOG && $log->info("Server settings effective user and group if requested..."); changeEffectiveUserAndGroup(); } @@ -439,14 +439,14 @@ sub init { $prefs->set( server_uuid => UUID::Tiny::create_UUID_as_string( UUID::Tiny::UUID_V4() ) ); } - main::INFOLOG && $log->info("Squeezebox Server binary search path init..."); + main::INFOLOG && $log->info("Server binary search path init..."); Slim::Utils::OSDetect::getOS->initSearchPath(); # Find plugins and process any new ones now so we can load their strings - main::INFOLOG && $log->info("Squeezebox Server PluginManager init..."); + main::INFOLOG && $log->info("Server PluginManager init..."); Slim::Utils::PluginManager->init(); - main::INFOLOG && $log->info("Squeezebox Server strings init..."); + main::INFOLOG && $log->info("Server strings init..."); Slim::Utils::Strings::init(); # Load appropriate DB module @@ -458,7 +458,7 @@ sub init { } if ( $sqlHelperClass ) { - main::INFOLOG && $log->info("Squeezebox Server SQL init ($sqlHelperClass)..."); + main::INFOLOG && $log->info("Server SQL init ($sqlHelperClass)..."); $sqlHelperClass->init(); } @@ -475,23 +475,23 @@ sub init { main::INFOLOG && $log->info("Firmware init..."); Slim::Utils::Firmware->init; - main::INFOLOG && $log->info("Squeezebox Server Info init..."); + main::INFOLOG && $log->info("Server Info init..."); Slim::Music::Info::init(); - main::INFOLOG && $log->info("Squeezebox Server IR init..."); + main::INFOLOG && $log->info("Server IR init..."); Slim::Hardware::IR::init(); - main::INFOLOG && $log->info("Squeezebox Server Request init..."); + main::INFOLOG && $log->info("Server Request init..."); Slim::Control::Request::init(); - main::INFOLOG && $log->info("Squeezebox Server Queries init..."); + main::INFOLOG && $log->info("Server Queries init..."); Slim::Control::Queries->init(); - main::INFOLOG && $log->info("Squeezebox Server Buttons init..."); + main::INFOLOG && $log->info("Server Buttons init..."); Slim::Buttons::Common::init(); if ($stdio) { - main::INFOLOG && $log->info("Squeezebox Server Stdio init..."); + main::INFOLOG && $log->info("Server Stdio init..."); Slim::Control::Stdio::init(\*STDIN, \*STDOUT); } @@ -512,9 +512,9 @@ sub init { } # Load the relevant importers - necessary to ensure that Slim::Schema::init() is called. - if (Slim::Utils::Misc::getAudioDir()) { - require Slim::Music::MusicFolderScan; - Slim::Music::MusicFolderScan->init(); + if (Slim::Utils::Misc::getMediaDirs()) { + require Slim::Media::MediaFolderScan; + Slim::Media::MediaFolderScan->init(); } if (Slim::Utils::Misc::getPlaylistDir()) { require Slim::Music::PlaylistFolderScan; @@ -523,7 +523,7 @@ sub init { initClass('Slim::Plugin::iTunes::Importer') if Slim::Utils::PluginManager->isConfiguredEnabled('iTunes'); initClass('Slim::Plugin::MusicMagic::Importer') if Slim::Utils::PluginManager->isConfiguredEnabled('MusicMagic'); - main::INFOLOG && $log->info("Squeezebox Server HTTP init..."); + main::INFOLOG && $log->info("Server HTTP init..."); Slim::Web::HTTP::init(); if (main::TRANSCODING) { @@ -533,7 +533,7 @@ sub init { } if (WEBUI && !$nosetup) { - main::INFOLOG && $log->info("Squeezebox Server Web Settings init..."); + main::INFOLOG && $log->info("Server Web Settings init..."); require Slim::Web::Setup; Slim::Web::Setup::initSetup(); } @@ -549,14 +549,14 @@ sub init { Slim::Menu::FolderInfo->init(); Slim::Menu::GlobalSearch->init(); - main::INFOLOG && $log->info('Squeezebox Server Alarms init...'); + main::INFOLOG && $log->info('Server Alarms init...'); Slim::Utils::Alarm->init(); # load plugins before Jive init so MusicIP hooks to cached artist/genre queries from Jive->init() will take root - main::INFOLOG && $log->info("Squeezebox Server Load Plugins..."); + main::INFOLOG && $log->info("Server Load Plugins..."); Slim::Utils::PluginManager->load(); - main::INFOLOG && $log->info("Squeezebox Server Jive init..."); + main::INFOLOG && $log->info("Server Jive init..."); Slim::Control::Jive->init(); main::INFOLOG && $log->info("Remote Metadata init..."); @@ -568,7 +568,7 @@ sub init { Slim::Utils::Log->reInit; } - main::INFOLOG && $log->info("Squeezebox Server checkDataSource..."); + main::INFOLOG && $log->info("Server checkDataSource..."); checkDataSource(); if ( $prefs->get('autorescan') ) { @@ -585,7 +585,7 @@ sub init { } # regular server has a couple more initial operations. - main::INFOLOG && $log->info("Squeezebox Server persist playlists..."); + main::INFOLOG && $log->info("Server persist playlists..."); if ($prefs->get('persistPlaylists')) { @@ -610,7 +610,7 @@ sub init { } if ( main::PERFMON ) { - main::INFOLOG && $log->info("Squeezebox Server Perfwarn init..."); + main::INFOLOG && $log->info("Server Perfwarn init..."); require Slim::Utils::PerfMon; Slim::Utils::PerfMon->init($perfwarn); } @@ -621,7 +621,7 @@ sub init { \&Slim::Utils::Update::checkVersion, ); - main::INFOLOG && $log->info("Squeezebox Server HTTP enable..."); + main::INFOLOG && $log->info("Server HTTP enable..."); Slim::Web::HTTP::init2(); # otherwise, get ready to loop @@ -629,7 +629,7 @@ sub init { $inInit = 0; - main::INFOLOG && $log->info("Squeezebox Server done init..."); + main::INFOLOG && $log->info("Server done init..."); } sub main { @@ -723,7 +723,7 @@ sub showUsage { [--logging ] [--noinfolog | --nodebuglog] --help => Show this usage information. - --cachedir => Directory for Squeezebox Server to save cached music and web data + --cachedir => Directory for Logitech Media Server to save cached music and web data --diag => Use diagnostics, shows more verbose errors. Also slows down library processing considerably --logdir => Specify folder location for log file @@ -957,7 +957,7 @@ sub changeEffectiveUserAndGroup { # Try starting as 'squeezeboxserver' instead. if (!defined($user)) { $user = 'squeezeboxserver'; - print STDERR "Squeezebox Server must not be run as root! Trying user $user instead.\n"; + print STDERR "Logitech Media Server must not be run as root! Trying user $user instead.\n"; } @@ -994,7 +994,7 @@ sub changeEffectiveUserAndGroup { # Check that we're definately not trying to start as root, e.g. if # we were passed '--user root' or any other used with uid 0. if ($uid == 0) { - print STDERR "Squeezebox Server must not be run as root! Only do this if you know what you're doing!!\n"; + print STDERR "Logitech Media Server must not be run as root! Only do this if you know what you're doing!!\n"; } @@ -1033,23 +1033,37 @@ sub changeEffectiveUserAndGroup { sub checkDataSource { - my $audiodir = Slim::Utils::Misc::getAudioDir(); + my $mediadirs = Slim::Utils::Misc::getMediaDirs(); + my $modified = 0; - if (defined $audiodir && $audiodir =~ m|[/\\]$|) { - $audiodir =~ s|[/\\]$||; - $prefs->set('audiodir',$audiodir); + foreach my $audiodir (@$mediadirs) { + if (defined $audiodir && $audiodir =~ m|[/\\]$|) { + $audiodir =~ s|[/\\]$||; + $modified++; + } } + $prefs->set('mediadirs', $mediadirs) if $modified; + return if !Slim::Schema::hasLibrary(); $sqlHelperClass->checkDataSource(); # Don't launch an initial scan on SqueezeOS, it will be handled by AutoRescan return if Slim::Utils::OSDetect::isSqueezeOS(); + + # Count entries for all media types, run scan if all are empty + my $dbh = Slim::Schema->dbh; + my ($tc, $vc, $ic) = $dbh->selectrow_array( qq{ + SELECT + (SELECT COUNT(*) FROM tracks where audio = 1) as tc, + (SELECT COUNT(*) FROM videos) as vc, + (SELECT COUNT(*) FROM images) as ic + } ); - if (Slim::Schema->schemaUpdated || Slim::Schema->count('Track', { 'me.audio' => 1 }) == 0) { + if (Slim::Schema->schemaUpdated || (!$tc && !$vc && !$ic)) { - logWarning("Schema updated or no tracks in the database, initiating scan."); + logWarning("Schema updated or no media found in the database, initiating scan."); Slim::Control::Request::executeRequest(undef, ['wipecache']); } @@ -1066,7 +1080,7 @@ sub forceStopServer { sub stopServer { my $restart = shift; - logger('')->info( 'Squeezebox Server ' . ($restart && !$::norestart ? 'restarting...' : 'shutting down.') ); + logger('')->info( 'Logitech Media Server ' . ($restart && !$::norestart ? 'restarting...' : 'shutting down.') ); $::stop = 1; @@ -1083,7 +1097,7 @@ sub stopServer { } sub cleanup { - logger('')->info("Squeezebox Server cleaning up."); + logger('')->info("Logitech Media Server cleaning up."); $::stop = 1; @@ -1116,7 +1130,7 @@ sub cleanup { sub save_pid_file { my $process_id = shift || $$; - logger('')->info("Squeezebox Server saving pid file."); + logger('')->info("Logitech Media Server saving pid file."); if (defined $pidfile) { File::Slurp::write_file($pidfile, $process_id); diff --git a/slimservice.pl b/slimservice.pl index d758b5a5fff..bd3f84f76ea 100755 --- a/slimservice.pl +++ b/slimservice.pl @@ -1,6 +1,6 @@ #!/opt/sdi/bin/perl -# Squeezebox Server Copyright (C) 2001-2009 Logitech. +# Logitech Media Server Copyright (C) 2001-2009 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. @@ -290,8 +290,8 @@ sub init { 'debug' => $debug, }); - # initialize slimserver subsystems - msg("SlimServer settings init...\n"); + # initialize server subsystems + msg("Server settings init...\n"); initSettings(); # Redirect STDERR to the log file. @@ -299,7 +299,7 @@ sub init { my $log = logger('server'); - main::INFOLOG && $log->info("SlimServer OS Specific init..."); + main::INFOLOG && $log->info("Server OS Specific init..."); unless (main::ISWINDOWS) { $SIG{'HUP'} = \&initSettings; @@ -354,25 +354,25 @@ sub init { =cut # Find plugins and process any new ones now so we can load their strings - main::INFOLOG && $log->info("Squeezebox Server PluginManager init..."); + main::INFOLOG && $log->info("Server PluginManager init..."); Slim::Utils::PluginManager->init(); - main::INFOLOG && $log->info("SlimServer strings init..."); + main::INFOLOG && $log->info("Server strings init..."); Slim::Utils::Strings::init(); - main::INFOLOG && $log->info("SlimServer Info init..."); + main::INFOLOG && $log->info("Server Info init..."); Slim::Music::Info::init(); - main::INFOLOG && $log->info("SlimServer IR init..."); + main::INFOLOG && $log->info("Server IR init..."); Slim::Hardware::IR::init(); - main::INFOLOG && $log->info("SlimServer Request init..."); + main::INFOLOG && $log->info("Server Request init..."); Slim::Control::Request::init(); - main::INFOLOG && $log->info("SlimServer Buttons init..."); + main::INFOLOG && $log->info("Server Buttons init..."); Slim::Buttons::Common::init(); - main::INFOLOG && $log->info("SlimServer Graphic Fonts init..."); + main::INFOLOG && $log->info("Server Graphic Fonts init..."); Slim::Display::Lib::Fonts::init(); main::INFOLOG && $log->info("Slimproto Init..."); @@ -394,14 +394,14 @@ sub init { Slim::Menu::PlaylistInfo->init(); Slim::Menu::GlobalSearch->init(); - main::INFOLOG && $log->info('Squeezebox Server Alarms init...'); + main::INFOLOG && $log->info('Server Alarms init...'); Slim::Utils::Alarm->init(); # load plugins before Jive init so MusicIP hooks to cached artist/genre queries from Jive->init() will take root - main::INFOLOG && $log->info("Squeezebox Server Load Plugins..."); + main::INFOLOG && $log->info("Server Load Plugins..."); Slim::Utils::PluginManager->load(); - main::INFOLOG && $log->info("Squeezebox Server Jive init..."); + main::INFOLOG && $log->info("Server Jive init..."); Slim::Control::Jive->init(); main::INFOLOG && $log->info("Remote Metadata init..."); @@ -437,7 +437,7 @@ sub init { $inInit = 0; - main::INFOLOG && $log->info("SlimServer done init..."); + main::INFOLOG && $log->info("Logitech Media Server done init..."); } sub main { @@ -524,7 +524,7 @@ sub showUsage { --help => Show this usage information. --audiodir => The path to a directory of your MP3 files. --playlistdir => The path to a directory of your playlist files. - --cachedir => Directory for SlimServer to save cached music and web data + --cachedir => Directory for Logitech Media Server to save cached music and web data --diag => Use diagnostics, shows more verbose errors. Also slows down library processing considerably --logfile => Specify a file for error logging. --noLogTimestamp => Don't add timestamp to log output @@ -653,14 +653,14 @@ sub forceStopServer { # sub stopServer { - logger('')->info("SlimServer shutting down."); + logger('')->info("Logitech Media Server shutting down."); cleanup(); exit(); } sub cleanup { - logger('')->info("SlimServer cleaning up."); + logger('')->info("Logitech Media Server cleaning up."); # Make sure to flush anything in the database to disk. if ($INC{'Slim/Schema.pm'}) { diff --git a/strings.txt b/strings.txt index dd39927b4be..dfdce5fa717 100644 --- a/strings.txt +++ b/strings.txt @@ -1,9 +1,9 @@ -# Main Squeezebox Server strings file +# Main Logitech Media Server strings file # $Id$ # -# This tab-delimited file contains all the text strings used in Squeezebox Server +# This tab-delimited file contains all the text strings used in Logitech Media Server # The format should be self explanatory. To submit a new language, or a better # translation of an existing string, please email your changes to # @@ -156,19 +156,19 @@ CHOOSE_A_LANGUAGE ZH_CN 请选择语言 LOADING_SQUEEZEBOX_SERVER - CS Nahrávání Squeezebox Server... - DA Indlæser Squeezebox Server... - DE Squeezebox Server wird geladen... - EN Loading Squeezebox Server... - ES Cargando Squeezebox Server... - FI Ladataan Squeezebox Server... - FR Chargement du Squeezebox Server en cours... - IT Caricamento di Squeezebox Server in corso... - NL Squeezebox Server wordt geladen... - NO Laster inn Squeezebox Server ... - PL Trwa ładowanie programu Squeezebox Server... - RU Загрузка Squeezebox Server... - SV Squeezebox Server startas + CS Nahrávání Logitech Media Server... + DA Indlæser Logitech Media Server... + DE Logitech Media Server wird geladen... + EN Loading Logitech Media Server... + ES Cargando Logitech Media Server... + FI Ladataan Logitech Media Server... + FR Chargement du Logitech Media Server en cours... + IT Caricamento di Logitech Media Server in corso... + NL Logitech Media Server wordt geladen... + NO Laster inn Logitech Media Server ... + PL Trwa ładowanie programu Logitech Media Server... + RU Загрузка Logitech Media Server... + SV Logitech Media Server startas EN_SKIN # SLT: please use "Light" as in "light weight", not "illumination" @@ -243,20 +243,20 @@ DEFAULT_MAP ZH_CN 标准 SERVER_VERSION - CS Verze Squeezebox Serveru - DA Squeezebox Server version - DE Squeezebox Server-Version - EN Squeezebox Server Version - ES Versión de Squeezebox Server - FR Version du Squeezebox Server - HE גרסת Squeezebox Server‏ - IT Versione Squeezebox Server + CS Verze Logitech Media Serveru + DA Logitech Media Server version + DE Logitech Media Server-Version + EN Logitech Media Server Version + ES Versión de Logitech Media Server + FR Version du Logitech Media Server + HE גרסת Logitech Media Server‏ + IT Versione Logitech Media Server JA スリムサーバー・バージョン - NL Squeezebox Server-versie - NO Squeezebox Server-versjon - PT Versão do Squeezebox Server - SV Squeezebox Server-version - ZH_CN Squeezebox Server版本 + NL Logitech Media Server-versie + NO Logitech Media Server-versjon + PT Versão do Logitech Media Server + SV Logitech Media Server-version + ZH_CN Logitech Media Server版本 PERL_VERSION CS Verze Perl @@ -451,7 +451,7 @@ LIBRARY_CONTAINS CS Vaše hudební knihovna obsahuje DA Dit musikbibliotek indeholder DE Die Musikbibliothek enthält - EN Your music library contains + EN Your media library contains ES La biblioteca de música contiene FI Musiikkikirjaston sisältö: FR La collection contient @@ -482,6 +482,12 @@ MUSIC RU Музыка SV Musik +VIDEO + EN Video + +PICTURES + EN Pictures + SETTINGS CS Nastavení DA Indstillinger @@ -916,38 +922,38 @@ PAUSED ZH_CN 已暂停 SQUEEZEBOX_SERVER - CS Squeezebox Server - DA Squeezebox Server - DE Squeezebox Server - EN Squeezebox Server - ES Squeezebox Server - FI Squeezebox Server - FR Squeezebox Server - HE Squeezebox Server - IT Squeezebox Server - NL Squeezebox Server - NO Squeezebox Server - PL Squeezebox Server - RU Squeezebox Server - SV Squeezebox Server - ZH_CN Squeezebox Server + CS Logitech Media Server + DA Logitech Media Server + DE Logitech Media Server + EN Logitech Media Server + ES Logitech Media Server + FI Logitech Media Server + FR Logitech Media Server + HE Logitech Media Server + IT Logitech Media Server + NL Logitech Media Server + NO Logitech Media Server + PL Logitech Media Server + RU Logitech Media Server + SV Logitech Media Server + ZH_CN Logitech Media Server ABOUT - CS Squeezebox Server V.%s, autor: - DA Squeezebox Server V.%s, skrevet af: - DE Squeezebox Server V.%s, entwickelt von: - EN Squeezebox Server V.%s, written by: - ES Squeezebox Server v. %s, escrito por: - FI Squeezebox Server V.%s, tekijä: - FR Squeezebox Server V.%s, écrit par : - HE Squeezebox Server V.%s, נוצר על-ידי: - IT Squeezebox Server V.%s, scritto da: - JA Squeezebox Server V.%s, 製作: - NL Squeezebox Server V.%s, geschreven door: - NO Squeezebox Server V.%s, skrevet av: - PT Squeezebox Server v.%s, escrito por - SV Squeezebox Server v.%s, skriven av: - ZH_CN Squeezebox Server V.%s, 制作: + CS Logitech Media Server V.%s, autor: + DA Logitech Media Server V.%s, skrevet af: + DE Logitech Media Server V.%s, entwickelt von: + EN Logitech Media Server V.%s, written by: + ES Logitech Media Server v. %s, escrito por: + FI Logitech Media Server V.%s, tekijä: + FR Logitech Media Server V.%s, écrit par : + HE Logitech Media Server V.%s, נוצר על-ידי: + IT Logitech Media Server V.%s, scritto da: + JA Logitech Media Server V.%s, 製作: + NL Logitech Media Server V.%s, geschreven door: + NO Logitech Media Server V.%s, skrevet av: + PT Logitech Media Server v.%s, escrito por + SV Logitech Media Server v.%s, skriven av: + ZH_CN Logitech Media Server V.%s, 制作: REMOVING_FROM_PLAYLIST CS Odstraňování ze seznamu skladeb: @@ -1205,25 +1211,6 @@ PLAYLIST_CANT_WRITE RU Не удалось сохранить плей-лист. SV Spellistan gick inte att spara. -BROWSING_MUSIC - CS Procházení hudby... - DA Gennemser musik... - DE Musik wird durchsucht ... - EN Browsing music... - ES Examinando música... - FI Tarkistetaan musiikkia... - FR Parcours des morceaux... - HE עיון במוסיקה... - IT Ricerca musica... - JA 曲をブラウズしています... - NL Bezig met bladeren door muziek... - NO Blar gjennom musikk... - PL Przeglądanie muzyki... - PT Lista de músicas... - RU Просмотр музыки... - SV Bläddrar ... - ZH_CN 浏览音乐... - NOW_PLAYING_FROM CS Právě hraje z: DA Spiller nu fra: @@ -2476,23 +2463,23 @@ WELCOME_TO_SLIMP3 ZH_CN 欢迎使用SLIMP3 WELCOME_TO_SQUEEZEBOX_SERVER - CS Vítejte do Squeezebox Server - DA Velkommen til Squeezebox Server + CS Vítejte do Logitech Media Server + DA Velkommen til Logitech Media Server DE Willkommen! - EN Welcome to Squeezebox Server - ES Bienvenido a Squeezebox Server - FI Tervetuloa Squeezebox Serveriin - FR Bienvenue dans le Squeezebox Server - HE ברוך הבא ל-Squeezebox Server - IT Benvenuti in Squeezebox Server - JA Squeezebox Serverへようこそ - NL Welkom bij Squeezebox Server - NO Velkommen til Squeezebox Server - PL Squeezebox Server — Zapraszamy - PT Bem-vindo ao Squeezebox Server - RU Добро пожаловать в Squeezebox Server - SV Välkommen till Squeezebox Server - ZH_CN 欢迎使用Squeezebox Server + EN Welcome to Logitech Media Server + ES Bienvenido a Logitech Media Server + FI Tervetuloa Logitech Media Serveriin + FR Bienvenue dans le Logitech Media Server + HE ברוך הבא ל-Logitech Media Server + IT Benvenuti in Logitech Media Server + JA Logitech Media Serverへようこそ + NL Welkom bij Logitech Media Server + NO Velkommen til Logitech Media Server + PL Logitech Media Server — Zapraszamy + PT Bem-vindo ao Logitech Media Server + RU Добро пожаловать в Logitech Media Server + SV Välkommen till Logitech Media Server + ZH_CN 欢迎使用Logitech Media Server WELCOME_TO_SQUEEZEBOX CS Vítejte ve Squeezeboxu @@ -3530,22 +3517,22 @@ SETUP_GROUP_TCP_PARAMS ZH_CN TCP参数 SETUP_GROUP_TCP_PARAMS_DESC - CS Tato nastavení upravují parametry sítě TCP/IP ve Squeezebox Server. - DA Disse indstillinger påvirker hvordan Squeezebox Server håndterer TCP/IP-parametrene. - DE Diese Einstellung passt die TCP/IP-Netzwerk-Einstellungen von Squeezebox Server an. - EN These settings adjust the parameters of the TCP/IP networking in Squeezebox Server. - ES Estos parámetros cambiarán las opciones de TCP/IP en Squeezebox Server. - FI Näillä asetuksilla säädetään TCP/IP-verkkoyhteyden parametrejä Squeezebox Serverissä. + CS Tato nastavení upravují parametry sítě TCP/IP ve Logitech Media Server. + DA Disse indstillinger påvirker hvordan Logitech Media Server håndterer TCP/IP-parametrene. + DE Diese Einstellung passt die TCP/IP-Netzwerk-Einstellungen von Logitech Media Server an. + EN These settings adjust the parameters of the TCP/IP networking in Logitech Media Server. + ES Estos parámetros cambiarán las opciones de TCP/IP en Logitech Media Server. + FI Näillä asetuksilla säädetään TCP/IP-verkkoyhteyden parametrejä Logitech Media Serverissä. FR Ces réglages permettent d'ajuster les paramètres du réseau TCP pour le serveur. HE הגדרות אלה מכוונות את הפרמטרים של רשת TCP/IP בשרת. - IT Queste impostazioni regolano i parametri di rete TCP/IP in Squeezebox Server. + IT Queste impostazioni regolano i parametri di rete TCP/IP in Logitech Media Server. JA これらのセッティングはサーバーのTCP/IPパラメータを調節します - NL Hiermee kun je de parameters van het TCP/IP-netwerk in Squeezebox Server aanpassen. - NO Disse innstillingene justerer parametrene for TCP/IP-nettverket i Squeezebox Server. - PL Te ustawienia umożliwiają dostosowanie parametrów sieci TCP/IP w programie Squeezebox Server. + NL Hiermee kun je de parameters van het TCP/IP-netwerk in Logitech Media Server aanpassen. + NO Disse innstillingene justerer parametrene for TCP/IP-nettverket i Logitech Media Server. + PL Te ustawienia umożliwiają dostosowanie parametrów sieci TCP/IP w programie Logitech Media Server. PT Estas configurações ajustam os parâmetros de rede TCP do servidor. - RU Эти настройки служат для регулировки параметров работы в сети по протоколу TCP/IP в Squeezebox Server. - SV De här inställningarna justerar TCP/IP-parametrarna för Squeezebox Server. + RU Эти настройки служат для регулировки параметров работы в сети по протоколу TCP/IP в Logitech Media Server. + SV De här inställningarna justerar TCP/IP-parametrarna för Logitech Media Server. ZH_CN 适用于调节服务器上TCP/IP网络参数的配置。 SETUP_GROUP_TITLEFORMATS_DESC @@ -3890,19 +3877,19 @@ SETUP_GROUP_PLUGINS SV Plugin-program SETUP_GROUP_PLUGINS_DESC - CS Squeezebox Server obsahuje některé zásuvné moduly (pluginy), které můžete využívat s pomocí dálkového ovládání nebo webového rozhraní. Níže můžete povolit nebo zakázat jednotlivé zásuvné moduly.

              Poznámka: Aby změny začaly platit, je nutné restartovat aplikaci. - DA Der findes en række udvidelsesmoduler til Squeezebox Server som kan styres vha. fjernbetjeningen og via den webbaserede brugerflade. Du kan vælge at slå de enkelte udvidelsesmoduler til og fra nedenfor.

              Bemærk: Programmet skal genstartes før ændringerne bliver synlige. - DE Squeezebox Server enthält einige Plugins, die Sie mit der Fernbedienung oder in der Web-Benutzeroberfläche nutzen können. Sie können diese Plugins unten aktivieren bzw. deaktivieren.

              Hinweis: Sie müssen den Server neu starten, damit diese Änderungen in Kraft treten. - EN Squeezebox Server includes some plugins that you can use with your remote or in the web interface. You can choose to enable or disable individual plugins below.

              Note: You will need to restart the application to see the effect of these changes. - ES Squeezebox Server incluye algunos complementos que se pueden usar con el mando a distancia o en la interfaz Web. Puede activar o desactivar complementos individuales a continuación.

              Nota: deberá reiniciar el servidor para que estos cambios entren en vigor. - FI Squeezebox Server sisältää laajennuksia, joita voi käyttää kaukosäätimellä tai internet-liittymän välityksellä. Yksittäiset laajennukset voidaan ottaa käyttöön tai poistaa käytöstä alla.

              Huomaa: Sovellus täytyy käynnistää uudelleen, jotta muutosten vaikutukset näkyvät. - FR Le Squeezebox Server inclut certains plugins à utiliser avec la télécommande ou à partir de l'interface Web. Vous pouvez activer ou désactiver des plugins ci-dessous.

              Remarque: Vous devez redémarrer le serveur pour que les modifications prennent effet. - IT In Squeezebox Server sono disponibili alcuni plugin utilizzabili con il telecomando o nell'interfaccia Web. È possibile attivare o disattivare i singoli plugin sottostanti.

              Nota: per rendere effettive le modifiche, è necessario riavviare l'applicazione. - NL Squeezebox Server bevat een aantal plug-ins die je met je afstandsbediening of in de webinterface kunt gebruiken. Met de onderstaande knoppen kun je afzonderlijke plug-ins in- of uitschakelen.

              N.B. Je moet Squeezebox Server opnieuw opstarten om de wijzigingen door te voeren. - NO Squeezebox Server har plugin-moduler som du kan bruke med fjernkontrollen, eller i nettgrensesnittet. Du kan velge å aktivere eller deaktivere plugin-moduler enkeltvis nedenfor.

              Merk: Du må starte programmet på nytt før disse endringene trer i kraft. - PL Program Squeezebox Server zawiera dodatki, których można używać za pomocą pilota lub w interfejsie internetowym. Poszczególne dodatki można włączyć lub wyłączyć poniżej.

              Uwaga: aby zobaczyć efekt wprowadzenia zmian, należy ponownie uruchomić aplikację. - RU Squeezebox Server содержит несколько подключаемых модулей, которыми можно управлять с помощью пульта ДУ или веб-интерфейса. Можно включать и выключать отдельные подключаемые модули.

              Примечание: чтобы увидеть результат изменений, перезагрузите приложение. - SV Det finns ett antal plugin-program för Squeezebox Server som du kan använda från fjärrkontrollen eller i webbgränssnittet. Nedan kan aktivera och avaktivera enskilda plugin-program.

              Obs! Ändringarna träder inte i kraft förrän du startar om programmet. + CS Logitech Media Server obsahuje některé zásuvné moduly (pluginy), které můžete využívat s pomocí dálkového ovládání nebo webového rozhraní. Níže můžete povolit nebo zakázat jednotlivé zásuvné moduly.

              Poznámka: Aby změny začaly platit, je nutné restartovat aplikaci. + DA Der findes en række udvidelsesmoduler til Logitech Media Server som kan styres vha. fjernbetjeningen og via den webbaserede brugerflade. Du kan vælge at slå de enkelte udvidelsesmoduler til og fra nedenfor.

              Bemærk: Programmet skal genstartes før ændringerne bliver synlige. + DE Logitech Media Server enthält einige Plugins, die Sie mit der Fernbedienung oder in der Web-Benutzeroberfläche nutzen können. Sie können diese Plugins unten aktivieren bzw. deaktivieren.

              Hinweis: Sie müssen den Server neu starten, damit diese Änderungen in Kraft treten. + EN Logitech Media Server includes some plugins that you can use with your remote or in the web interface. You can choose to enable or disable individual plugins below.

              Note: You will need to restart the application to see the effect of these changes. + ES Logitech Media Server incluye algunos complementos que se pueden usar con el mando a distancia o en la interfaz Web. Puede activar o desactivar complementos individuales a continuación.

              Nota: deberá reiniciar el servidor para que estos cambios entren en vigor. + FI Logitech Media Server sisältää laajennuksia, joita voi käyttää kaukosäätimellä tai internet-liittymän välityksellä. Yksittäiset laajennukset voidaan ottaa käyttöön tai poistaa käytöstä alla.

              Huomaa: Sovellus täytyy käynnistää uudelleen, jotta muutosten vaikutukset näkyvät. + FR Le Logitech Media Server inclut certains plugins à utiliser avec la télécommande ou à partir de l'interface Web. Vous pouvez activer ou désactiver des plugins ci-dessous.

              Remarque: Vous devez redémarrer le serveur pour que les modifications prennent effet. + IT In Logitech Media Server sono disponibili alcuni plugin utilizzabili con il telecomando o nell'interfaccia Web. È possibile attivare o disattivare i singoli plugin sottostanti.

              Nota: per rendere effettive le modifiche, è necessario riavviare l'applicazione. + NL Logitech Media Server bevat een aantal plug-ins die je met je afstandsbediening of in de webinterface kunt gebruiken. Met de onderstaande knoppen kun je afzonderlijke plug-ins in- of uitschakelen.

              N.B. Je moet Logitech Media Server opnieuw opstarten om de wijzigingen door te voeren. + NO Logitech Media Server har plugin-moduler som du kan bruke med fjernkontrollen, eller i nettgrensesnittet. Du kan velge å aktivere eller deaktivere plugin-moduler enkeltvis nedenfor.

              Merk: Du må starte programmet på nytt før disse endringene trer i kraft. + PL Program Logitech Media Server zawiera dodatki, których można używać za pomocą pilota lub w interfejsie internetowym. Poszczególne dodatki można włączyć lub wyłączyć poniżej.

              Uwaga: aby zobaczyć efekt wprowadzenia zmian, należy ponownie uruchomić aplikację. + RU Logitech Media Server содержит несколько подключаемых модулей, которыми можно управлять с помощью пульта ДУ или веб-интерфейса. Можно включать и выключать отдельные подключаемые модули.

              Примечание: чтобы увидеть результат изменений, перезагрузите приложение. + SV Det finns ett antal plugin-program för Logitech Media Server som du kan använda från fjärrkontrollen eller i webbgränssnittet. Nedan kan aktivera och avaktivera enskilda plugin-program.

              Obs! Ändringarna träder inte i kraft förrän du startar om programmet. SETUP_GROUP_PLUGINS_NEEDS_RESTART CS K uskutečnění změny je nutné restartovat. @@ -3920,34 +3907,34 @@ SETUP_GROUP_PLUGINS_NEEDS_RESTART SV Du måste starta om för att ändringen ska börja gälla. SETUP_PLUGINS_SAFEMODE - CS Vezměte na vědomí: protože Squeezebox Server běží v bezpečném režimu, nejsou k dispozici pluginy. Můžete je stále povolit / zakázat za účelem nápravy problémů, které máte s instalací. - DA Bemærk: Da Squeezebox Server kører i fejlsikret tilstand, kan du ikke bruge udvidelsesmodulerne. Du kan stadig slå dem til og fra for at løse problemer med installationen. - DE Hinweis: Da Sie Squeezebox Server im abgesicherten Modus ausführen, sind die Plugins nicht verfügbar. Sie können Sie trotzdem aktivieren bzw. deaktivieren, wenn es Probleme mit der Installation gibt. - EN Please note: as you're running Squeezebox Server in safe mode, the plugins are not available. You can still enable/disable them in order to fix problems you have with your installation. - ES Tenga en cuenta que: está ejecutando Squeezebox Server en modo seguro, los complementos no están disponibles. Pero puede activarlos/desactivarlos para solucionar problemas con la instalación. - FI Huomaa: koska käytät Squeezebox Serveriä vikasietotilassa, laajennukset eivät ole käytettävissä. Voit yhä ottaa ne käyttöön tai poistaa ne käytöstä korjataksesi ongelmat, joita asennuksen kanssa esiintyy. - FR Remarque: en mode sans échec, les plugins du Squeezebox Server ne sont pas disponibles. Toutefois, vous pouvez toujours les activer ou les désactiver de manière à résoudre tout problème lié à l'installation. - IT Nota: i plugin non sono disponibili poiché si sta eseguendo Squeezebox Server in modalità provvisoria. Per risolvere i problemi di installazione è comunque possibile attivarli o disattivarli. - NL Let op: omdat Squeezebox Server in veilige modus uitgevoerd wordt, zijn de plug-ins niet beschikbaar. Je kunt ze wel in- en uitschakelen om problemen met de installatie op te lossen. - NO Merk: Siden du kjører Squeezebox Server i sikkermodus, er plugin-modulene ikke tilgjengelige. Du kan allikevel aktivere/deaktivere dem for å løse problemer med installeringen. - PL Uwaga: po uruchomieniu programu Squeezebox Server w trybie bezpiecznym dodatki będą niedostępne. Możliwe jest włączenie lub wyłączenie tych dodatków, aby rozwiązać problemy z instalacją. - RU Примечание: поскольку Squeezebox Server выполняется в безопасном режиме, подключаемые модули недоступны. При этом их по-прежнему можно включать и отключать, чтобы решить проблемы с установкой. - SV Tänk på att plugin-programmen inte är tillgängliga när du kör Squeezebox Server i felsäkert läge. Du kan fortfarande aktivera/avaktivera dem för att åtgärda problemen du hade under installationen. + CS Vezměte na vědomí: protože Logitech Media Server běží v bezpečném režimu, nejsou k dispozici pluginy. Můžete je stále povolit / zakázat za účelem nápravy problémů, které máte s instalací. + DA Bemærk: Da Logitech Media Server kører i fejlsikret tilstand, kan du ikke bruge udvidelsesmodulerne. Du kan stadig slå dem til og fra for at løse problemer med installationen. + DE Hinweis: Da Sie Logitech Media Server im abgesicherten Modus ausführen, sind die Plugins nicht verfügbar. Sie können Sie trotzdem aktivieren bzw. deaktivieren, wenn es Probleme mit der Installation gibt. + EN Please note: as you're running Logitech Media Server in safe mode, the plugins are not available. You can still enable/disable them in order to fix problems you have with your installation. + ES Tenga en cuenta que: está ejecutando Logitech Media Server en modo seguro, los complementos no están disponibles. Pero puede activarlos/desactivarlos para solucionar problemas con la instalación. + FI Huomaa: koska käytät Logitech Media Serveriä vikasietotilassa, laajennukset eivät ole käytettävissä. Voit yhä ottaa ne käyttöön tai poistaa ne käytöstä korjataksesi ongelmat, joita asennuksen kanssa esiintyy. + FR Remarque: en mode sans échec, les plugins du Logitech Media Server ne sont pas disponibles. Toutefois, vous pouvez toujours les activer ou les désactiver de manière à résoudre tout problème lié à l'installation. + IT Nota: i plugin non sono disponibili poiché si sta eseguendo Logitech Media Server in modalità provvisoria. Per risolvere i problemi di installazione è comunque possibile attivarli o disattivarli. + NL Let op: omdat Logitech Media Server in veilige modus uitgevoerd wordt, zijn de plug-ins niet beschikbaar. Je kunt ze wel in- en uitschakelen om problemen met de installatie op te lossen. + NO Merk: Siden du kjører Logitech Media Server i sikkermodus, er plugin-modulene ikke tilgjengelige. Du kan allikevel aktivere/deaktivere dem for å løse problemer med installeringen. + PL Uwaga: po uruchomieniu programu Logitech Media Server w trybie bezpiecznym dodatki będą niedostępne. Możliwe jest włączenie lub wyłączenie tych dodatków, aby rozwiązać problemy z instalacją. + RU Примечание: поскольку Logitech Media Server выполняется в безопасном режиме, подключаемые модули недоступны. При этом их по-прежнему можно включать и отключать, чтобы решить проблемы с установкой. + SV Tänk på att plugin-programmen inte är tillgängliga när du kör Logitech Media Server i felsäkert läge. Du kan fortfarande aktivera/avaktivera dem för att åtgärda problemen du hade under installationen. INSTALLERROR_INVALID_VERSION - CS Tento zásuvný modul není kompatibilní s touto verzí Squeezebox Server. Prosím aktualizujte. - DA Udvidelsesmodulet er inkompatibelt med denne version af Squeezebox Server. Det skal opdateres. - DE Plugin ist nicht kompatibel mit dieser Version von Squeezebox Server. Aktualisieren Sie die Anwendung. - EN Plugin is incompatible with this version of Squeezebox Server. Please update. - ES El complemento no es compatible con esta versión de Squeezebox Server. Realice una actualización. - FI Laajennus ei ole yhteensopiva tämän Squeezebox Server -version kanssa. Päivitä. - FR Le plugin n'est pas compatible avec cette version de Squeezebox Server. Veuillez mettre à jour. - IT Plugin incompatibile con questa versione di Squeezebox Server. Aggiornarlo. - NL Plug-in is incompatibel met deze versie van Squeezebox Server. Werk de plug-in bij. - NO Plugin-modulen er ikke kompatibel med denne versjonen av Squeezebox Server. Du bør oppdatere. - PL Dodatek jest niezgodny z tą wersją programu Squeezebox Server. Dokonaj aktualizacji. - RU Плагин несовместим с данной версией Squeezebox Server. Обновите программу. - SV Plugin-programmet är inte kompatibelt med den här versionen av Squeezebox Server. Uppdatera. + CS Tento zásuvný modul není kompatibilní s touto verzí Logitech Media Server. Prosím aktualizujte. + DA Udvidelsesmodulet er inkompatibelt med denne version af Logitech Media Server. Det skal opdateres. + DE Plugin ist nicht kompatibel mit dieser Version von Logitech Media Server. Aktualisieren Sie die Anwendung. + EN Plugin is incompatible with this version of Logitech Media Server. Please update. + ES El complemento no es compatible con esta versión de Logitech Media Server. Realice una actualización. + FI Laajennus ei ole yhteensopiva tämän Logitech Media Server -version kanssa. Päivitä. + FR Le plugin n'est pas compatible avec cette version de Logitech Media Server. Veuillez mettre à jour. + IT Plugin incompatibile con questa versione di Logitech Media Server. Aggiornarlo. + NL Plug-in is incompatibel met deze versie van Logitech Media Server. Werk de plug-in bij. + NO Plugin-modulen er ikke kompatibel med denne versjonen av Logitech Media Server. Du bør oppdatere. + PL Dodatek jest niezgodny z tą wersją programu Logitech Media Server. Dokonaj aktualizacji. + RU Плагин несовместим с данной версией Logitech Media Server. Обновите программу. + SV Plugin-programmet är inte kompatibelt med den här versionen av Logitech Media Server. Uppdatera. INSTALLERROR_INCOMPATIBLE_PLATFORM CS Plugin není kompatibilní s vaší platformou. @@ -3998,22 +3985,22 @@ SETUP_GROUP_FORMATS_CONVERSION ZH_CN 文件格式转换设置 SETUP_GROUP_FORMATS_CONVERSION_DESC - CS Squeezebox Server může převádět formáty audio souborů průběžně (on-the-fly) pro přehrávání na vašem přehrávači. Níže můžete zrušením zaškrtnutí zakázat určité formáty. Je zde zobrazen pouze název binárního souboru. Chcete-li vidět nebo editovat celou příkazovou řádku, otevřete convert.conf. Změny uložíte klepnutím na tlačítko Změnit. - DA Squeezebox Server kan konvertere lydfilerne mens de spilles på afspilleren. Du kan fravælge filformater nedenfor ved at fjerne markeringen ud for dem. Det er kun navnet på binære filer som vises her. Hvis du vil se og eventuelt redigere hele kommandolinjen, skal du åbne convert.conf. Klik på Skift for at gemme indstillingerne. - DE Squeezebox Server kann während der Wiedergabe Audiodateiformate konvertieren. Sie können bestimmte Formate ausschließen, indem Sie das entsprechende Kontrollkästchen deaktivieren. Hier wird nur der Name der ausführbaren Datei angezeigt. Wenn Sie die gesamte Befehlszeile sehen möchten, müssen Sie 'convert.conf' öffnen. Klicken Sie auf 'Ändern', um die Änderungen zu speichern. - EN Squeezebox Server can convert audio file formats on-the-fly for playback on your player. You can disable specific formats below by unchecking them. Only the name of the binary is shown here. To see/edit the entire command line, you will need to open convert.conf. Click Change to save your changes. - ES Squeezebox Server puede convertir formatos de archivo de audio al instante para reproducirlos en el reproductor. A continuación, puede anular la selección de formatos específicos para desactivarlos. Aquí sólo se muestra el nombre del binario. Para ver/editar la línea de comandos entera, deberá abrir convert.conf. Haga clic en Cambiar para guardar los cambios. - FI Squeezebox Server voi muuntaa äänitiedostomuotoja vauhdista soittimella toistoa varten. Voit poistaa tiedostomuotoja käytöstä alla lisäämällä niiden kohdalle valintamerkin. Tässä näkyy vain binaarin nimi. Jos haluat tarkastella/muokata koko komentoriviä, avaa convert.conf. Tallenna muutokset valitsemalla Muuta. - FR Le Squeezebox Server peut convertir à la volée certains types de fichiers audio afin de les lire sur votre platine. Vous pouvez annuler la conversion d'un type de fichier spécifique en le désélectionnant ci-dessous. Seul le nom du binaire s'affiche ici. Pour afficher ou modifier la ligne de commande en entier, vous devez ouvrir le fichier convert.conf. Cliquez sur Modifier pour enregistrer les modifications. - HE Squeezebox Server יכול להמיר תבניות של קובצי שמע במהלך השמעה של מוסיקה בנגן. באפשרותך להשבית את ההפעלה של תבניות ספציפיות מהרשימה שלהלן באמצעות ביטול הסימון שלהן. כאן מוצג רק השם של הנתונים הבינאריים. כדי להציג/לערוך את כל שורת הפקודה, יהיה עליך לפתוח את convert.conf. לחץ על 'שנה' לשמירת השינויים. - IT Squeezebox Server consente di convertire rapidamente i formati dei file audio per eseguirne la riproduzione tramite il lettore. È possibile disattivare i formati riportati di seguito deselezionandoli. Qui è visualizzato solo il nome del file binario. Per visualizzare/modificare l'intera riga di comando, è necessario aprire il file convert.conf. Per salvare le modifiche, fare clic su Cambia. - JA Squeezebox Serverはオーディオファイル フォーマットを自動的に変換することができます。特定のフォーマットを無効にするにはチェックマークを消してください。フォーマット名のみが出ていますが、コマンドライン全てを見るまたは編集するには、convert.conf を開いてください。変更をセーブするには「変更」をクリックして下さい。 - NL Squeezebox Server kan audioformaten direct tijdens het afspelen converteren. Je kunt specifieke formaten hieronder uitschakelen door het vinkje weg te halen. Alleen de naam van het programmabestand wordt weergegeven. Als je de hele opdrachtregel wilt zien, moet je 'convert.conf' openen. Klik op 'Veranderen' om je wijzigingen op te slaan. - NO Squeezebox Server kan konvertere lydfilformater på direkten, slik at filene kan spilles av på spilleren. Du kan deaktivere formater nedenfor, ved å fjerne markeringen ved dem. Bare binærnavnet vises her. Hvis du vil se/redigere hele kommandolinjen, må du åpne convert.conf. Klikk Endre for å lagre endringene. - PL Program Squeezebox Server może przekonwertować formaty plików audio w locie w celu umożliwienia odtworzenia. Poszczególne formaty można wyłączyć poniżej, usuwając zaznaczenie pól wyboru. W tym miejscu widoczna jest tylko nazwa pliku binarnego. Aby wyświetlić/edytować tekst w całym wierszu polecenia, należy otworzyć plik convert.conf. Kliknij przycisk Zmień, aby zapisać zmiany. - RU Squeezebox Server может в реальном времени преобразовывать форматы аудиофайлов для воспроизведения на плеере. Можно отключить те или иные форматы, сняв соответствующие флажки. Здесь отображается только имя двоичного файла. Чтобы просмотреть или изменить всю командную строку, нужно открыть файл convert.conf. Щелкните "Изменить", чтобы сохранить изменения. - SV Squeezebox Server kan konvertera ljudfiler under uppspelning. Du kan avaktivera specifika format nedan genom att avmarkera dem. Här visas endast namnet på den binära filen. Om du vill se eller redigera hela kommandoraden måste du öppna convert.conf. Spara ändringarna genom att klicka på Ändra. - ZH_CN Squeezebox Server能对音像文件进行即时的格式转换以便在播放机上播放。如要撤销某些格式,请清除其复选框中的标记。此处只显示有关的可执行文件。如要查看或编辑完整的命令行,请查看convert.conf。请点击《更动》以保存您所作的设定。 + CS Logitech Media Server může převádět formáty audio souborů průběžně (on-the-fly) pro přehrávání na vašem přehrávači. Níže můžete zrušením zaškrtnutí zakázat určité formáty. Je zde zobrazen pouze název binárního souboru. Chcete-li vidět nebo editovat celou příkazovou řádku, otevřete convert.conf. Změny uložíte klepnutím na tlačítko Změnit. + DA Logitech Media Server kan konvertere lydfilerne mens de spilles på afspilleren. Du kan fravælge filformater nedenfor ved at fjerne markeringen ud for dem. Det er kun navnet på binære filer som vises her. Hvis du vil se og eventuelt redigere hele kommandolinjen, skal du åbne convert.conf. Klik på Skift for at gemme indstillingerne. + DE Logitech Media Server kann während der Wiedergabe Audiodateiformate konvertieren. Sie können bestimmte Formate ausschließen, indem Sie das entsprechende Kontrollkästchen deaktivieren. Hier wird nur der Name der ausführbaren Datei angezeigt. Wenn Sie die gesamte Befehlszeile sehen möchten, müssen Sie 'convert.conf' öffnen. Klicken Sie auf 'Ändern', um die Änderungen zu speichern. + EN Logitech Media Server can convert audio file formats on-the-fly for playback on your player. You can disable specific formats below by unchecking them. Only the name of the binary is shown here. To see/edit the entire command line, you will need to open convert.conf. Click Change to save your changes. + ES Logitech Media Server puede convertir formatos de archivo de audio al instante para reproducirlos en el reproductor. A continuación, puede anular la selección de formatos específicos para desactivarlos. Aquí sólo se muestra el nombre del binario. Para ver/editar la línea de comandos entera, deberá abrir convert.conf. Haga clic en Cambiar para guardar los cambios. + FI Logitech Media Server voi muuntaa äänitiedostomuotoja vauhdista soittimella toistoa varten. Voit poistaa tiedostomuotoja käytöstä alla lisäämällä niiden kohdalle valintamerkin. Tässä näkyy vain binaarin nimi. Jos haluat tarkastella/muokata koko komentoriviä, avaa convert.conf. Tallenna muutokset valitsemalla Muuta. + FR Le Logitech Media Server peut convertir à la volée certains types de fichiers audio afin de les lire sur votre platine. Vous pouvez annuler la conversion d'un type de fichier spécifique en le désélectionnant ci-dessous. Seul le nom du binaire s'affiche ici. Pour afficher ou modifier la ligne de commande en entier, vous devez ouvrir le fichier convert.conf. Cliquez sur Modifier pour enregistrer les modifications. + HE Logitech Media Server יכול להמיר תבניות של קובצי שמע במהלך השמעה של מוסיקה בנגן. באפשרותך להשבית את ההפעלה של תבניות ספציפיות מהרשימה שלהלן באמצעות ביטול הסימון שלהן. כאן מוצג רק השם של הנתונים הבינאריים. כדי להציג/לערוך את כל שורת הפקודה, יהיה עליך לפתוח את convert.conf. לחץ על 'שנה' לשמירת השינויים. + IT Logitech Media Server consente di convertire rapidamente i formati dei file audio per eseguirne la riproduzione tramite il lettore. È possibile disattivare i formati riportati di seguito deselezionandoli. Qui è visualizzato solo il nome del file binario. Per visualizzare/modificare l'intera riga di comando, è necessario aprire il file convert.conf. Per salvare le modifiche, fare clic su Cambia. + JA Logitech Media Serverはオーディオファイル フォーマットを自動的に変換することができます。特定のフォーマットを無効にするにはチェックマークを消してください。フォーマット名のみが出ていますが、コマンドライン全てを見るまたは編集するには、convert.conf を開いてください。変更をセーブするには「変更」をクリックして下さい。 + NL Logitech Media Server kan audioformaten direct tijdens het afspelen converteren. Je kunt specifieke formaten hieronder uitschakelen door het vinkje weg te halen. Alleen de naam van het programmabestand wordt weergegeven. Als je de hele opdrachtregel wilt zien, moet je 'convert.conf' openen. Klik op 'Veranderen' om je wijzigingen op te slaan. + NO Logitech Media Server kan konvertere lydfilformater på direkten, slik at filene kan spilles av på spilleren. Du kan deaktivere formater nedenfor, ved å fjerne markeringen ved dem. Bare binærnavnet vises her. Hvis du vil se/redigere hele kommandolinjen, må du åpne convert.conf. Klikk Endre for å lagre endringene. + PL Program Logitech Media Server może przekonwertować formaty plików audio w locie w celu umożliwienia odtworzenia. Poszczególne formaty można wyłączyć poniżej, usuwając zaznaczenie pól wyboru. W tym miejscu widoczna jest tylko nazwa pliku binarnego. Aby wyświetlić/edytować tekst w całym wierszu polecenia, należy otworzyć plik convert.conf. Kliknij przycisk Zmień, aby zapisać zmiany. + RU Logitech Media Server может в реальном времени преобразовывать форматы аудиофайлов для воспроизведения на плеере. Можно отключить те или иные форматы, сняв соответствующие флажки. Здесь отображается только имя двоичного файла. Чтобы просмотреть или изменить всю командную строку, нужно открыть файл convert.conf. Щелкните "Изменить", чтобы сохранить изменения. + SV Logitech Media Server kan konvertera ljudfiler under uppspelning. Du kan avaktivera specifika format nedan genom att avmarkera dem. Här visas endast namnet på den binära filen. Om du vill se eller redigera hela kommandoraden måste du öppna convert.conf. Spara ändringarna genom att klicka på Ändra. + ZH_CN Logitech Media Server能对音像文件进行即时的格式转换以便在播放机上播放。如要撤销某些格式,请清除其复选框中的标记。此处只显示有关的可执行文件。如要查看或编辑完整的命令行,请查看convert.conf。请点击《更动》以保存您所作的设定。 SETUP_FORMATSLIST_MISSING_BINARY CS Požadovaný binární soubor nebyl nalezen: @@ -4086,22 +4073,36 @@ SETUP_DISABLEDEXTENSIONSAUDIO SV Avaktiverade filtillägg för ljudfiler ZH_CN 撤销音频文件扩展名 +SETUP_DISABLEDEXTENSIONSVIDEO + DE Deaktivierte Video-Dateinamenerweiterungen + EN Disabled Video File Extensions + +SETUP_DISABLEDEXTENSIONSIMAGES + DE Deaktivierte Photo-Dateinamenerweiterungen + EN Disabled Picture File Extensions + SETUP_DISABLEDEXTENSIONSAUDIO_DESC - CS Squeezebox Server vyhledá ve složce Hudba všechny podporované typy souborů (audio soubory a kompilační listy (cue sheets)). Chcete-li zakázat zpracování některých typů souborů při prohledávání složky Hudba, zadejte níže seznam přípon souborů oddělený čárkami. Například: cue, mp4, aac - DA Squeezebox Server søger efter understøttede filtyper (lydfiler og afspilningslister) i mappen Musik. Hvis du vil forhindre at bestemte filtyper bliver behandlet når mappen bliver gennemsøgt, skal du angive filtypenavnene i en kommaadskilt liste nedenfor. For eksempel: cue, mp4, aac - DE Squeezebox Server durchsucht den Musikordner nach allen unterstützten Dateitypen (Audiodateien und Cue Sheets). Zum Deaktivieren bestimmter Dateitypen geben Sie unten eine durch Kommas getrennte Liste ein. Beispiel: cue, mp4, aac - EN Squeezebox Server will look in the Music Folder for all supported file types (audio files and cue sheets). To disable specific file types from being processed when scanning the Music Folder, enter a comma separated list of file extensions below. E.g.: cue, mp4, aac - ES Squeezebox Server buscará en la carpeta de música todos los tipos de archivo compatibles (archivos de audio y archivos CUE). Para desactivar tipos de archivos específicos del proceso de examen de la carpeta de música, introduzca una lista separada por comas de extensiones de archivo a continuación. Por ejemplo: cue, mp4, aac - FI Squeezebox Server etsii musiikkikansiosta kaikkia tuettuja tiedostotyyppejä (äänitiedostoja ja päivän ohjelmia). Jos haluat poistaa käytöstä tiettyjen tiedostotyyppien käsittelyn musiikkikansiohaun aikana, kirjoita alle pilkuilla erotettu luettelo tiedostotunnisteista, esim: cue, mp4, aac. - FR Le Squeezebox Server recherche tous les types de fichiers audio et de cue sheets pris en charge dans le dossier de musique. Pour exclure un type de fichier audio de l'analyse, spécifiez une liste d'extensions séparées par une virgule ci-dessous. Exemple: cue, mp4, aac - HE Squeezebox Server יבצע חיפוש בתיקיית המוסיקה אחר כל סוגי הקבצים הנתמכים (קבצים וגיליונות סימנים של שמע). כדי להשבית סוגי קבצים ספציפיים כך שלא יעובדו בעת סריקה של תיקיית המוסיקה, הזן בשדה שלהלן רשימה המופרדת באמצעות פסיקים של סיומות קבצים. לדוגמה: cue, mp4, aac - IT Squeezebox Server cercherà nella cartella Musica tutti i tipi di file supportati (file audio e cue sheet). Per ignorare tipi di file specifici, inserire qui sotto l'elenco delle estensioni corrispondenti separate da una virgola. Ad esempio, cue, mp4, aac - NL Squeezebox Server zoekt in de muziekmap naar alle ondersteunde bestandstypen (audio- en cue-bestanden). Je kunt hieronder een kommagescheiden lijst met bestandsextensies invoeren om ervoor te zorgen dat specifieke bestandstypen bij het scannen worden overgeslagen. Bijv.: cue, mp4, aac - NO Squeezebox Server leter etter alle støttede filtyper i musikkmappen (lydfiler og tidsskjema). Hvis du vil utelukke bestemte filtyper fra søket, kan du angi de relevante filnavnene nedenfor, atskilt med komma. Eksempel: cue, mp4, aac - PL Program Squeezebox Server wyszuka w folderze muzyki wszystkie obsługiwane typy plików (pliki audio i informacyjne). Aby wyłączyć przetwarzanie określonych typów plików podczas przeszukiwania folderu muzyki, wprowadź listę rozszerzeń plików rozdzieloną przecinkami poniżej, np.: cue, mp4, aac - RU Squeezebox Server выполняет в папке "Музыка" поиск всех поддерживаемых типов файлов (аудиофайлов и микрофонных материалов). Чтобы отключить обработку определенных типов файлов при сканировании папки "Музыка", введите список файловых расширений через запятую. Например: cue, mp4, aac - SV Squeezebox Server söker igenom musikmappen efter alla filtyper som stöds (ljudfiler och cue-filer). Om du inte vill att alla filtyper ska bearbetas vid sökningen av musikmappen kan du ange filtilläggen för de filer som ska undantas nedan i en kommaavgränsad lista. Exempel: cue, mp4, aac - ZH_CN Squeezebox Server会在音乐文件夹内寻找各式所支持的音频或cue sheet文件。 如想要把某些格式除外,便在以下输入其格式扩展名,以逗号为分隔。例如: cue, mp4, aac + CS Logitech Media Server vyhledá ve složce Hudba všechny podporované typy souborů (audio soubory a kompilační listy (cue sheets)). Chcete-li zakázat zpracování některých typů souborů při prohledávání složky Hudba, zadejte níže seznam přípon souborů oddělený čárkami. Například: cue, mp4, aac + DA Logitech Media Server søger efter understøttede filtyper (lydfiler og afspilningslister) i mappen Musik. Hvis du vil forhindre at bestemte filtyper bliver behandlet når mappen bliver gennemsøgt, skal du angive filtypenavnene i en kommaadskilt liste nedenfor. For eksempel: cue, mp4, aac + DE Logitech Media Server durchsucht den Musikordner nach allen unterstützten Dateitypen (Audiodateien und Cue Sheets). Zum Deaktivieren bestimmter Dateitypen geben Sie unten eine durch Kommas getrennte Liste ein. Beispiel: cue, mp4, aac + EN Logitech Media Server will look in the Media Folders for all supported file types (audio files and cue sheets). To disable specific file types from being processed when scanning the Music Folder, enter a comma separated list of file extensions below. E.g.: cue, mp4, aac + ES Logitech Media Server buscará en la carpeta de música todos los tipos de archivo compatibles (archivos de audio y archivos CUE). Para desactivar tipos de archivos específicos del proceso de examen de la carpeta de música, introduzca una lista separada por comas de extensiones de archivo a continuación. Por ejemplo: cue, mp4, aac + FI Logitech Media Server etsii musiikkikansiosta kaikkia tuettuja tiedostotyyppejä (äänitiedostoja ja päivän ohjelmia). Jos haluat poistaa käytöstä tiettyjen tiedostotyyppien käsittelyn musiikkikansiohaun aikana, kirjoita alle pilkuilla erotettu luettelo tiedostotunnisteista, esim: cue, mp4, aac. + FR Le Logitech Media Server recherche tous les types de fichiers audio et de cue sheets pris en charge dans le dossier de musique. Pour exclure un type de fichier audio de l'analyse, spécifiez une liste d'extensions séparées par une virgule ci-dessous. Exemple: cue, mp4, aac + HE Logitech Media Server יבצע חיפוש בתיקיית המוסיקה אחר כל סוגי הקבצים הנתמכים (קבצים וגיליונות סימנים של שמע). כדי להשבית סוגי קבצים ספציפיים כך שלא יעובדו בעת סריקה של תיקיית המוסיקה, הזן בשדה שלהלן רשימה המופרדת באמצעות פסיקים של סיומות קבצים. לדוגמה: cue, mp4, aac + IT Logitech Media Server cercherà nella cartella Musica tutti i tipi di file supportati (file audio e cue sheet). Per ignorare tipi di file specifici, inserire qui sotto l'elenco delle estensioni corrispondenti separate da una virgola. Ad esempio, cue, mp4, aac + NL Logitech Media Server zoekt in de muziekmap naar alle ondersteunde bestandstypen (audio- en cue-bestanden). Je kunt hieronder een kommagescheiden lijst met bestandsextensies invoeren om ervoor te zorgen dat specifieke bestandstypen bij het scannen worden overgeslagen. Bijv.: cue, mp4, aac + NO Logitech Media Server leter etter alle støttede filtyper i musikkmappen (lydfiler og tidsskjema). Hvis du vil utelukke bestemte filtyper fra søket, kan du angi de relevante filnavnene nedenfor, atskilt med komma. Eksempel: cue, mp4, aac + PL Program Logitech Media Server wyszuka w folderze muzyki wszystkie obsługiwane typy plików (pliki audio i informacyjne). Aby wyłączyć przetwarzanie określonych typów plików podczas przeszukiwania folderu muzyki, wprowadź listę rozszerzeń plików rozdzieloną przecinkami poniżej, np.: cue, mp4, aac + RU Logitech Media Server выполняет в папке "Музыка" поиск всех поддерживаемых типов файлов (аудиофайлов и микрофонных материалов). Чтобы отключить обработку определенных типов файлов при сканировании папки "Музыка", введите список файловых расширений через запятую. Например: cue, mp4, aac + SV Logitech Media Server söker igenom musikmappen efter alla filtyper som stöds (ljudfiler och cue-filer). Om du inte vill att alla filtyper ska bearbetas vid sökningen av musikmappen kan du ange filtilläggen för de filer som ska undantas nedan i en kommaavgränsad lista. Exempel: cue, mp4, aac + ZH_CN Logitech Media Server会在音乐文件夹内寻找各式所支持的音频或cue sheet文件。 如想要把某些格式除外,便在以下输入其格式扩展名,以逗号为分隔。例如: cue, mp4, aac + +SETUP_DISABLEDEXTENSIONSVIDEO_DESC + EN The server will look in the Media Folders for all supported video file types. To disable specific file types from being processed when scanning the Music Folder, enter a comma separated list of file extensions below. E.g.: mov, mkv + +SETUP_DISABLEDEXTENSIONSIMAGES_DESC + EN The server will look in the Media Folders for all supported picture file types. To disable specific file types from being processed when scanning the Music Folder, enter a comma separated list of file extensions below. E.g.: bmp, gif SETUP_DISABLEDEXTENSIONSPLAYLIST CS Přípony souborů v seznamu skladeb nepovoleny @@ -4121,21 +4122,21 @@ SETUP_DISABLEDEXTENSIONSPLAYLIST ZH_CN 撤销播放表文件扩展名 SETUP_DISABLEDEXTENSIONSPLAYLIST_DESC - CS Squeezebox Server vyhledá ve složce Seznamy skladeb všechny podporované typy souborů (soubory seznamů skladeb a kompilační listy (cue sheets)). Chcete-li zakázat zpracování některých typů souborů při prohledávání složky Seznamy skladeb, zadejte níže seznam přípon souborů oddělený čárkami. Například: m3u, pls, cue - DA Squeezebox Server søger efter understøttede filtyper (afspilningslister og cue-ark) i mappen Afspilningslister. Hvis du vil forhindre at bestemte filtyper bliver behandlet når mappen bliver gennemsøgt, skal du angive filtypenavnene i en kommaadskilt liste nedenfor. For eksempel: m3u, pls, cue - DE Squeezebox Server durchsucht den Wiedergabelistenordner nach allen unterstützten Dateitypen (Wiedergabelistendateien und Cue Sheets). Zum Deaktivieren bestimmter Dateitypen geben Sie unten eine durch Kommas getrennte Liste ein. Beispiel: cue, m3u, pls - EN Squeezebox Server will look in the Playlist Folder for all supported file types (playlist files and cue sheets). To disable specific file types from being processed when scanning the Playlist Folder, enter a comma separated list of file extensions below. E.g.: m3u, pls, cue - ES Squeezebox Server buscará en la carpeta de listas de reproducción todos los tipos de archivo compatibles (archivos de pista de reproducción y archivos CUE). Para desactivar tipos de archivos específicos del proceso de examen de la carpeta de listas de reproducción, introduzca una lista separada por comas de extensiones de archivo a continuación. Por ejemplo: m3u, pls, cue - FI Squeezebox Server etsii soittoluettelokansiosta kaikkia tuettuja tiedostotyyppejä (soittoluettelotiedostoja ja päivän ohjelmia). Jos haluat poistaa käytöstä tiettyjen tiedostotyyppien käsittelyn soittoluettelokansiohaun aikana, kirjoita alle pilkuilla erotettu luettelo tiedostotunnisteista, esim: m3u, pls, cue. - FR Le Squeezebox Server recherche tous les types de fichiers audio et de cue sheets pris en charge dans le dossier des listes de lecture. Pour exclure un type de fichier audio de l'analyse, spécifiez une liste d'extensions séparées par une virgule ci-dessous. Exemple: m3u, pls, cue - HE Squeezebox Server יבצע חיפוש בתיקיית המוסיקה ההשמעה אחר כל סוגי הקבצים הנתמכים (קבצים וגיליונות סימנים של רשימות השמעה). כדי להשבית סוגי קבצים ספציפיים כך שלא יעובדו בעת סריקה של תיקיית רשימות ההשמעה, הזן בשדה שלהלן רשימה המופרדת באמצעות פסיקים של סיומות קבצים. לדוגמה: m3u, pls, cue - IT Squeezebox Server cercherà nella cartella delle playlist tutti i tipi di file supportati (playlist e cue sheet.). Per ignorare tipi di file specifici, inserire qui sotto l'elenco delle estensioni corrispondenti separate da una virgola. Ad esempio, m3u, pls, cue - NL Squeezebox Server zoekt in de playlistmap naar alle ondersteunde bestandstypen (playlist- en cue-bestanden). Je kunt hieronder een kommagescheiden lijst met bestandsextensies invoeren om ervoor te zorgen dat specifieke bestandstypen bij het scannen worden overgeslagen. Bijv.: m3u, pls, cue - NO Squeezebox Server leter etter alle støttede filtyper i spillelistemappen (spillelistefiler og tidsskjema). Hvis du vil utelukke bestemte filtyper fra søket, kan du angi de relevante filnavnene nedenfor, atskilt med komma. Eksempel: m3u, pls, cue - PL Program Squeezebox Server wyszuka w folderze list odtwarzania wszystkie obsługiwane typy plików (pliki list odtwarzania i informacyjne). Aby wyłączyć przetwarzanie określonych typów plików podczas przeszukiwania folderu list odtwarzania, wprowadź poniżej listę rozszerzeń plików rozdzieloną przecinkami, np.: m3u, pls, cue. - RU Squeezebox Server выполняет в папке "Плей-листы" поиск всех поддерживаемых типов файлов (файлов плей-листов и микрофонных материалов). Чтобы отключить обработку определенных типов файлов при сканировании папки "Плей-листы", введите список файловых расширений через запятую. Например: m3u, pls, cue - SV Squeezebox Server söker igenom mappen med spellistor efter filer av alla de typer som stöds (spellistefiler och cue-filer). Om du inte vill att alla filtyper ska bearbetas vid sökningen av spellistemappen kan du ange en kommaseparerad lista över filtillägg nedan. Exempel: m3u, pls, cue - ZH_CN Squeezebox Server会在播放表文件夹内寻找各式所支持的播放表或cue sheet文件。 如想要把某些格式除外,便在以下输入其格式扩展名,以逗号为分隔。例如: m3u, pls, cue + CS Logitech Media Server vyhledá ve složce Seznamy skladeb všechny podporované typy souborů (soubory seznamů skladeb a kompilační listy (cue sheets)). Chcete-li zakázat zpracování některých typů souborů při prohledávání složky Seznamy skladeb, zadejte níže seznam přípon souborů oddělený čárkami. Například: m3u, pls, cue + DA Logitech Media Server søger efter understøttede filtyper (afspilningslister og cue-ark) i mappen Afspilningslister. Hvis du vil forhindre at bestemte filtyper bliver behandlet når mappen bliver gennemsøgt, skal du angive filtypenavnene i en kommaadskilt liste nedenfor. For eksempel: m3u, pls, cue + DE Logitech Media Server durchsucht den Wiedergabelistenordner nach allen unterstützten Dateitypen (Wiedergabelistendateien und Cue Sheets). Zum Deaktivieren bestimmter Dateitypen geben Sie unten eine durch Kommas getrennte Liste ein. Beispiel: cue, m3u, pls + EN Logitech Media Server will look in the Playlist Folder for all supported file types (playlist files and cue sheets). To disable specific file types from being processed when scanning the Playlist Folder, enter a comma separated list of file extensions below. E.g.: m3u, pls, cue + ES Logitech Media Server buscará en la carpeta de listas de reproducción todos los tipos de archivo compatibles (archivos de pista de reproducción y archivos CUE). Para desactivar tipos de archivos específicos del proceso de examen de la carpeta de listas de reproducción, introduzca una lista separada por comas de extensiones de archivo a continuación. Por ejemplo: m3u, pls, cue + FI Logitech Media Server etsii soittoluettelokansiosta kaikkia tuettuja tiedostotyyppejä (soittoluettelotiedostoja ja päivän ohjelmia). Jos haluat poistaa käytöstä tiettyjen tiedostotyyppien käsittelyn soittoluettelokansiohaun aikana, kirjoita alle pilkuilla erotettu luettelo tiedostotunnisteista, esim: m3u, pls, cue. + FR Le Logitech Media Server recherche tous les types de fichiers audio et de cue sheets pris en charge dans le dossier des listes de lecture. Pour exclure un type de fichier audio de l'analyse, spécifiez une liste d'extensions séparées par une virgule ci-dessous. Exemple: m3u, pls, cue + HE Logitech Media Server יבצע חיפוש בתיקיית המוסיקה ההשמעה אחר כל סוגי הקבצים הנתמכים (קבצים וגיליונות סימנים של רשימות השמעה). כדי להשבית סוגי קבצים ספציפיים כך שלא יעובדו בעת סריקה של תיקיית רשימות ההשמעה, הזן בשדה שלהלן רשימה המופרדת באמצעות פסיקים של סיומות קבצים. לדוגמה: m3u, pls, cue + IT Logitech Media Server cercherà nella cartella delle playlist tutti i tipi di file supportati (playlist e cue sheet.). Per ignorare tipi di file specifici, inserire qui sotto l'elenco delle estensioni corrispondenti separate da una virgola. Ad esempio, m3u, pls, cue + NL Logitech Media Server zoekt in de playlistmap naar alle ondersteunde bestandstypen (playlist- en cue-bestanden). Je kunt hieronder een kommagescheiden lijst met bestandsextensies invoeren om ervoor te zorgen dat specifieke bestandstypen bij het scannen worden overgeslagen. Bijv.: m3u, pls, cue + NO Logitech Media Server leter etter alle støttede filtyper i spillelistemappen (spillelistefiler og tidsskjema). Hvis du vil utelukke bestemte filtyper fra søket, kan du angi de relevante filnavnene nedenfor, atskilt med komma. Eksempel: m3u, pls, cue + PL Program Logitech Media Server wyszuka w folderze list odtwarzania wszystkie obsługiwane typy plików (pliki list odtwarzania i informacyjne). Aby wyłączyć przetwarzanie określonych typów plików podczas przeszukiwania folderu list odtwarzania, wprowadź poniżej listę rozszerzeń plików rozdzieloną przecinkami, np.: m3u, pls, cue. + RU Logitech Media Server выполняет в папке "Плей-листы" поиск всех поддерживаемых типов файлов (файлов плей-листов и микрофонных материалов). Чтобы отключить обработку определенных типов файлов при сканировании папки "Плей-листы", введите список файловых расширений через запятую. Например: m3u, pls, cue + SV Logitech Media Server söker igenom mappen med spellistor efter filer av alla de typer som stöds (spellistefiler och cue-filer). Om du inte vill att alla filtyper ska bearbetas vid sökningen av spellistemappen kan du ange en kommaseparerad lista över filtillägg nedan. Exempel: m3u, pls, cue + ZH_CN Logitech Media Server会在播放表文件夹内寻找各式所支持的播放表或cue sheet文件。 如想要把某些格式除外,便在以下输入其格式扩展名,以逗号为分隔。例如: m3u, pls, cue PLAYER_TYPE CS Typ přehrávače @@ -4886,20 +4887,20 @@ SETUP_MAXWMARATE ZH_CN 最高WMA频流比特率 SETUP_MAXWMARATE_DESC - CS Některé datové proudy WMA mají několik hodnot bitrate (přenosové rychlosti) pro přehrávání datových proudů. Standardně Squeezebox Server vybírá proud s nejvyšší hodnotou bitrate, který je k dispozici, ale pokud máte pomalejší připojení k Internetu, můžete zde nastavit nižší hodnotu a omezit tak maximální rychlost, kterou lze vybrat z těchto proudů s několika hodnotami bitrate. - DA Nogle WMA-streams sendes med flere forskellige bit-hastigheder. Som standard vil Squeezebox Server vælge den højeste bithastighed som er tilgængelig. Hvis du har en langsom internetforbindelse, kan du angive en lavere værdi her for at begrænse den maksimale bithastighed som kan vælges når der er flere muligheder. - DE Bei bestimmten WMA-Datenströmen stehen mehrere Bitraten zur Übertragung zur Verfügung. Standardmäßig wählt Squeezebox Server die höchste verfügbare Bitrate. Dies kann jedoch bei langsameren Internetverbindungen zu Problemen führen. Daher können Sie hier die maximal zulässige Bitrate festlegen. - EN Some WMA streams have multiple bitrates available for streaming. By default, Squeezebox Server will select the highest bitrate stream available, but if you have a slower Internet connection, you may set a lower value here to limit the maximum rate that can be chosen from these multiple rate streams. - ES Algunas secuencias WMA tienen varias velocidades de bits disponibles para el envío por secuencias. De forma predeterminada, Squeezebox Server seleccionará la secuencia con la velocidad de bits más alta disponible pero, si tiene una conexión a Internet lenta, puede establecer aquí un valor inferior para limitar la velocidad máxima que se puede elegir entre esas secuencias con diversas velocidades. - FI Joissakin WMA-virroissa on käytettävissä useita bittinopeuksia virtauttamiseen. Squeezebox Server valitsee oletuksena virran, jonka bittinopeus on suurin. Jos sinulla on hidas internet-yhteys, voit määrittää tässä kohdassa pienemmän nopeuden. Näin rajoitat enimmäisnopeutta, jonka Squeezebox Server voi valita erinopeuksisista virroista. - FR Certains flux WMA sont disponibles en plusieurs débits binaires. Par défaut, le Squeezebox Server choisira le débit le plus élevé disponible. Si votre connexion Internet ne le prend pas en charge, vous pouvez spécifier ici le débit maximal à utiliser. - HE זרימות WMA מסוימות כוללות מספר קצבי סיביות זמינים להפעלת זרימות. כברירת מחדל, Squeezebox Server יבחר את הזרימה בקצב הסיביות הגבוה ביותר הזמין, אך אם חיבור האינטרנט שלך איטי יותר, באפשרותך לקבוע כאן ערך נמוך יותר להגבלת הקצב המרבי שניתן לבחור מבין זרימות מרובות-קצבים אלה. - IT Per eseguire lo streaming di alcuni stream WMA sono disponibili diversi bitrate. Per impostazione predefinita in Squeezebox Server viene utilizzato lo stream con il bitrate più elevato, ma se si dispone di una connessione a Internet lenta, è possibile impostare qui un valore più basso per limitare la velocità massima selezionabile per questi stream con velocità molteplici. - NL Sommige WMA-streams hebben meerdere bitsnelheden voor streaming. Squeezebox Server selecteert standaard de hoogste bitsnelheid die voor de stream beschikbaar is. Als je een langzamere internetverbinding hebt, kun je een lagere waarde instellen om de maximumsnelheid die gekozen kan worden, te beperken. - NO Enkelte WMA-strømmer kan strømmes med ulike bithastigheter. Squeezebox Server velger som standard den høyeste bithastigheten som er tilgjengelig, men hvis du har en treg Internett-forbindelse, kan du angi en lavere verdi her, som forteller Squeezebox Server makshastigheten den kan velge. - PL W niektóre strumieniach WMA dostępnych jest kilka szybkości transmisji bitów do przesyłania strumieniowego. Domyślnie program Squeezebox Server wybierze strumień z najwyższą dostępną szybkością transmisji bitów, ale jeżeli używane jest wolniejsze połączenie internetowe, można w tym miejscu ustawić niższą wartość w celu ograniczenia maksymalnej szybkości, jaką można wybrać w przypadku strumieni o kilku szybkościach. - RU В некоторых потоках WMA доступно несколько скоростей передачи для потокового воспроизведения. По умолчанию Squeezebox Server выбирает поток с самой высокой скоростью передачи. Но при медленном соединении с Интернетом можно ограничить максимально доступное значение скорости передачи, сделав его более низким. - SV Vissa WMA-strömmar har flera olika bithastigheter. Som standard väljer Squeezebox Server den högsta tillgängliga bithastigheten. Om du har en långsammare internetuppkoppling kan du ange ett lägre värde här, så sänks gränsen för hur snabba hastigheter som kan väljas. + CS Některé datové proudy WMA mají několik hodnot bitrate (přenosové rychlosti) pro přehrávání datových proudů. Standardně Logitech Media Server vybírá proud s nejvyšší hodnotou bitrate, který je k dispozici, ale pokud máte pomalejší připojení k Internetu, můžete zde nastavit nižší hodnotu a omezit tak maximální rychlost, kterou lze vybrat z těchto proudů s několika hodnotami bitrate. + DA Nogle WMA-streams sendes med flere forskellige bit-hastigheder. Som standard vil Logitech Media Server vælge den højeste bithastighed som er tilgængelig. Hvis du har en langsom internetforbindelse, kan du angive en lavere værdi her for at begrænse den maksimale bithastighed som kan vælges når der er flere muligheder. + DE Bei bestimmten WMA-Datenströmen stehen mehrere Bitraten zur Übertragung zur Verfügung. Standardmäßig wählt Logitech Media Server die höchste verfügbare Bitrate. Dies kann jedoch bei langsameren Internetverbindungen zu Problemen führen. Daher können Sie hier die maximal zulässige Bitrate festlegen. + EN Some WMA streams have multiple bitrates available for streaming. By default, Logitech Media Server will select the highest bitrate stream available, but if you have a slower Internet connection, you may set a lower value here to limit the maximum rate that can be chosen from these multiple rate streams. + ES Algunas secuencias WMA tienen varias velocidades de bits disponibles para el envío por secuencias. De forma predeterminada, Logitech Media Server seleccionará la secuencia con la velocidad de bits más alta disponible pero, si tiene una conexión a Internet lenta, puede establecer aquí un valor inferior para limitar la velocidad máxima que se puede elegir entre esas secuencias con diversas velocidades. + FI Joissakin WMA-virroissa on käytettävissä useita bittinopeuksia virtauttamiseen. Logitech Media Server valitsee oletuksena virran, jonka bittinopeus on suurin. Jos sinulla on hidas internet-yhteys, voit määrittää tässä kohdassa pienemmän nopeuden. Näin rajoitat enimmäisnopeutta, jonka Logitech Media Server voi valita erinopeuksisista virroista. + FR Certains flux WMA sont disponibles en plusieurs débits binaires. Par défaut, le Logitech Media Server choisira le débit le plus élevé disponible. Si votre connexion Internet ne le prend pas en charge, vous pouvez spécifier ici le débit maximal à utiliser. + HE זרימות WMA מסוימות כוללות מספר קצבי סיביות זמינים להפעלת זרימות. כברירת מחדל, Logitech Media Server יבחר את הזרימה בקצב הסיביות הגבוה ביותר הזמין, אך אם חיבור האינטרנט שלך איטי יותר, באפשרותך לקבוע כאן ערך נמוך יותר להגבלת הקצב המרבי שניתן לבחור מבין זרימות מרובות-קצבים אלה. + IT Per eseguire lo streaming di alcuni stream WMA sono disponibili diversi bitrate. Per impostazione predefinita in Logitech Media Server viene utilizzato lo stream con il bitrate più elevato, ma se si dispone di una connessione a Internet lenta, è possibile impostare qui un valore più basso per limitare la velocità massima selezionabile per questi stream con velocità molteplici. + NL Sommige WMA-streams hebben meerdere bitsnelheden voor streaming. Logitech Media Server selecteert standaard de hoogste bitsnelheid die voor de stream beschikbaar is. Als je een langzamere internetverbinding hebt, kun je een lagere waarde instellen om de maximumsnelheid die gekozen kan worden, te beperken. + NO Enkelte WMA-strømmer kan strømmes med ulike bithastigheter. Logitech Media Server velger som standard den høyeste bithastigheten som er tilgjengelig, men hvis du har en treg Internett-forbindelse, kan du angi en lavere verdi her, som forteller Logitech Media Server makshastigheten den kan velge. + PL W niektóre strumieniach WMA dostępnych jest kilka szybkości transmisji bitów do przesyłania strumieniowego. Domyślnie program Logitech Media Server wybierze strumień z najwyższą dostępną szybkością transmisji bitów, ale jeżeli używane jest wolniejsze połączenie internetowe, można w tym miejscu ustawić niższą wartość w celu ograniczenia maksymalnej szybkości, jaką można wybrać w przypadku strumieni o kilku szybkościach. + RU В некоторых потоках WMA доступно несколько скоростей передачи для потокового воспроизведения. По умолчанию Logitech Media Server выбирает поток с самой высокой скоростью передачи. Но при медленном соединении с Интернетом можно ограничить максимально доступное значение скорости передачи, сделав его более низким. + SV Vissa WMA-strömmar har flera olika bithastigheter. Som standard väljer Logitech Media Server den högsta tillgängliga bithastigheten. Om du har en långsammare internetuppkoppling kan du ange ett lägre värde här, så sänks gränsen för hur snabba hastigheter som kan väljas. SETUP_SYNCSTARTDELAY CS Synchronizované zpoždění startu přehrávačů (ms) @@ -4917,19 +4918,19 @@ SETUP_SYNCSTARTDELAY SV Fördröjning vid start av synkroniserade spelare (ms) SETUP_SYNCSTARTDELAY_DESC - CS Když je synchronizováno více přehrávačů, Squeezebox Server přikáže každému přehrávači, aby začal přehrávat stopu ve stejnou dobu. Pro to je nutno zajistit, aby každý přehrávač měl čas příjmout příkazu startu před tím, než začnou všechny společně, a tedy odešle příkaz startu předem, aby každý přehrávač čekal na správný okamžik startu. Pokud je přetížená síť, což může nastat zvláště když je na síti příliš mnoho přehrávačů a u bezdrátových sítí, výchozí hodnota prodlevy 100 ms může být příliš krátká. Tuto výchozí hodnotu zde můžete v případě potřeby změnit. - DA Når flere afspillere er synkroniseret, vil Squeezebox Server sikre at alle afspillere starter nummeret på samme tid. For at være sikker på at alle afspillere har modtaget startkommandoen før afspilningen starter, sendes kommandoen forud, og hver afspiller venter til det rigtige tidspunkt før nummeret starter. Hvis netværket er overbelastet, hvilket kan ske hvis der er mange afspillere og/eller hvis netværket er trådløst, vil standardværdien for forsinkelsen på 100 ms måske ikke være tilstrækkelig. Du kan ændre standardværdien her hvis nødvendigt. - DE Wenn mehrere Player synchronisiert sind, gibt Squeezebox Server jedem Player die Anweisung, den Titel zur gleichen Zeit zu starten. Es muss sichergestellt sein, dass jeder Player genügend Zeit hat, den Startbefehl zu empfangen, bevor die gleichzeitige Wiedergabe beginnt. Daher wird der Startbefehl vorzeitig gesendet und die Player können den richtigen Zeitpunkt abwarten. Sollte das Netzwerk überlastet sein, was vor allem auftreten kann, wenn sich viele Player im Netzwerk befinden und drahtlose Netzwerke genutzt werden, reicht die Standardverzögerung von 100 ms evtl. nicht aus. Sie können bei Bedarf den Standardwert hier ändern. - EN When multiple players are synchronized, Squeezebox Server tells each player to start the track at the same time. It needs to make sure that each player has time to receive the start command before they all start together and so it sends the start command ahead of time and the players each wait until the right moment to start. If there is excessive network congestion, which can happen particularly when there are many players on the network and with wireless networks, then the default delay of 100ms may not be sufficient. You can change the default here if necessary. - ES Cuando hay varios reproductores sincronizados, Squeezebox Server indica a cada uno de ellos que comience la reproducción de la pista al mismo tiempo que los otros. A fin de asegurarse de que cada reproductor tiene tiempo de recibir el comando de inicio antes de que todos los reproductores entren en acción, Squeezebox Server envía el comando de inicio por adelantado y todos los reproductores esperan hasta el momento preciso para iniciarse. Si la red está demasiado congestionada (algo especialmente probable cuando hay muchos reproductores en la red, así como en redes inalámbricas), es posible que el retraso predeterminado de 100 ms sea insuficiente. Aquí puede cambiar el valor predeterminado, si es necesario. - FI Jos useita soittimia synkronoidaan, Squeezebox Server käskee kaikkia niistä aloittamaan kappaleen toiston samaan aikaan. Sen täytyy varmistaa, että jokaisella soittimella on riittävästi aikaa aloituskomennon vastaanottamiseen, ennen kuin kaikki soittimet aloittavat toiston yhdessä, joten se lähettää aloituskomennon etuajassa, ja soittimet odottavat oikeaa hetkeä toiston aloittamiseen. Jos verkkoliikenne on ruuhkaista, oletusviive 100 ms ei ole välttämättä riittävä. Näin saattaa tapahtua, jos verkossa on paljon soittimia. Tämä on yleinen ongelma myös langattomissa verkoissa. Voit muuttaa oletusviivettä tarvittaessa. - FR Lorsque plusieurs platines sont synchronisées, le Squeezebox Server indique à chacune de démarrer la lecture du morceau en même temps. Le serveur vérifie que chaque platine dispose d'assez de temps pour recevoir la commande avant de démarrer. Il envoie donc la commande en avance et chaque platine attend le bon moment pour démarrer. Si le réseau est surchargé, comme cela peut être le cas si de nombreuses platines sont présentes et avec des réseaux sans fil, le délai de 100 ms par défaut peut ne pas être suffisant. Vous pouvez modifier la valeur par défaut si nécessaire. - IT Quando più lettori sono sincronizzati, Squeezebox Server ordina a ciascun lettore di avviare la riproduzione del brano simultaneamente. A questo scopo, deve assicurarsi che ciascun lettore abbia il tempo di ricevere il comando di avvio prima dell'inizio della riproduzione, pertanto invia il comando di avvio con un certo anticipo in modo che ciascun lettore sia pronto a iniziare al momento giusto. Se il traffico di rete è eccessivo, come può succedere se sono connessi numerosi utenti in particolare nelle reti senza fili, il ritardo predefinito di 100 ms potrebbe non essere sufficiente. Se necessario, è possibile modificare questo valore predefinito. - NL Wanneer meerdere muzieksystemen worden gesynchroniseerd, geeft Squeezebox Server elk systeem de opdracht het nummer op hetzelfde moment te starten. Squeezebox Server moet ervoor zorgen dat elk systeem genoeg tijd heeft om de startopdracht te ontvangen voordat alle systemen samen starten, en daarom wordt de startopdracht van tevoren verzonden en wacht elk systeem tot het juiste moment om te starten. Als het netwerkverkeer overbelast is, wat voornamelijk kan gebeuren bij netwerken met vele systemen of bij draadloze netwerken, is de standaardvertraging van 100 milliseconden misschien niet voldoende. Je kunt de standaardvertraging hier desgewenst wijzigen. - NO Når flere spillere er synkronisert, sender Squeezebox Server beskjed til hver spiller om å begynne avspilling samtidig. Den må sikre at hver spiller får tid til å motta kommandoen før de alle starter samtidig, så den sender derfor startkommandoen på forhånd, og så venter spillerne til riktig øyeblikk før de starter. Hvis det er mye nettverkstrafikk, noe som kan skje hvis det er mange spillere på nettverket og ved bruk av trådløse nettverk, kan det hende at standardforsinkelsen på 100 ms er for kort. Hvis nødvendig kan du endre standardverdien her. - PL W przypadku zsynchronizowania kilku odtwarzaczy program Squeezebox Server wysyła do każdego odtwarzacza polecenie rozpoczęcia odtwarzania utworu w tym samym czasie. Program musi sprawdzić, czy każdy odtwarzacz ma czas na odebranie polecenia rozpoczęcia przed rozpoczęciem jednoczesnego odtwarzania, więc wysyła wcześniej polecenie rozpoczęcia, a odtwarzacze rozpoczynają pracę w odpowiedniej chwili. W przypadku nadmiernego przeciążenia sieci, które występuje szczególnie wtedy, gdy w sieciach standardowych i bezprzewodowych używana jest duża liczba odtwarzaczy, domyślne opóźnienie o długości 100 ms może być niewystarczające. W razie potrzeby wartość domyślną można zmienić tutaj. - RU При синхронизации нескольких плееров Squeezebox Server дает каждому из них команду начать воспроизведение дорожки в одно и то же время. Для этого необходимо убедиться, что каждый плеер получит команду запуска до всеобщего начала воспроизведения, поэтому данная команда отправляется ему заранее. После получения команды каждый плеер ожидает запуска. При сильной загрузке сети, что особенно характерно для сетей со множеством плееров и для беспроводных сетей, задержка по умолчанию, равная 100 мс, может быть недостаточной. При необходимости это значение можно изменить. - SV När flera spelare synkroniserats ser Squeezebox Server till att alla spelare börjar spela upp låten samtidigt. Det måste finnas tid för startkommandot att gå fram till var och en av spelarna innan låten börjar spelas upp. Därför skickas kommandot i förväg, och spelarna väntar sedan till rätt startögonblick. Om trafiken på nätverket är mycket tät, något som kan hända framför allt när många spelare anslutits och med trådlösa nätverk, kanske inte standardfördröjningen på 100 millisekunder räcker till. Du kan ändra standardinställningen här vid behov. + CS Když je synchronizováno více přehrávačů, Logitech Media Server přikáže každému přehrávači, aby začal přehrávat stopu ve stejnou dobu. Pro to je nutno zajistit, aby každý přehrávač měl čas příjmout příkazu startu před tím, než začnou všechny společně, a tedy odešle příkaz startu předem, aby každý přehrávač čekal na správný okamžik startu. Pokud je přetížená síť, což může nastat zvláště když je na síti příliš mnoho přehrávačů a u bezdrátových sítí, výchozí hodnota prodlevy 100 ms může být příliš krátká. Tuto výchozí hodnotu zde můžete v případě potřeby změnit. + DA Når flere afspillere er synkroniseret, vil Logitech Media Server sikre at alle afspillere starter nummeret på samme tid. For at være sikker på at alle afspillere har modtaget startkommandoen før afspilningen starter, sendes kommandoen forud, og hver afspiller venter til det rigtige tidspunkt før nummeret starter. Hvis netværket er overbelastet, hvilket kan ske hvis der er mange afspillere og/eller hvis netværket er trådløst, vil standardværdien for forsinkelsen på 100 ms måske ikke være tilstrækkelig. Du kan ændre standardværdien her hvis nødvendigt. + DE Wenn mehrere Player synchronisiert sind, gibt Logitech Media Server jedem Player die Anweisung, den Titel zur gleichen Zeit zu starten. Es muss sichergestellt sein, dass jeder Player genügend Zeit hat, den Startbefehl zu empfangen, bevor die gleichzeitige Wiedergabe beginnt. Daher wird der Startbefehl vorzeitig gesendet und die Player können den richtigen Zeitpunkt abwarten. Sollte das Netzwerk überlastet sein, was vor allem auftreten kann, wenn sich viele Player im Netzwerk befinden und drahtlose Netzwerke genutzt werden, reicht die Standardverzögerung von 100 ms evtl. nicht aus. Sie können bei Bedarf den Standardwert hier ändern. + EN When multiple players are synchronized, Logitech Media Server tells each player to start the track at the same time. It needs to make sure that each player has time to receive the start command before they all start together and so it sends the start command ahead of time and the players each wait until the right moment to start. If there is excessive network congestion, which can happen particularly when there are many players on the network and with wireless networks, then the default delay of 100ms may not be sufficient. You can change the default here if necessary. + ES Cuando hay varios reproductores sincronizados, Logitech Media Server indica a cada uno de ellos que comience la reproducción de la pista al mismo tiempo que los otros. A fin de asegurarse de que cada reproductor tiene tiempo de recibir el comando de inicio antes de que todos los reproductores entren en acción, Logitech Media Server envía el comando de inicio por adelantado y todos los reproductores esperan hasta el momento preciso para iniciarse. Si la red está demasiado congestionada (algo especialmente probable cuando hay muchos reproductores en la red, así como en redes inalámbricas), es posible que el retraso predeterminado de 100 ms sea insuficiente. Aquí puede cambiar el valor predeterminado, si es necesario. + FI Jos useita soittimia synkronoidaan, Logitech Media Server käskee kaikkia niistä aloittamaan kappaleen toiston samaan aikaan. Sen täytyy varmistaa, että jokaisella soittimella on riittävästi aikaa aloituskomennon vastaanottamiseen, ennen kuin kaikki soittimet aloittavat toiston yhdessä, joten se lähettää aloituskomennon etuajassa, ja soittimet odottavat oikeaa hetkeä toiston aloittamiseen. Jos verkkoliikenne on ruuhkaista, oletusviive 100 ms ei ole välttämättä riittävä. Näin saattaa tapahtua, jos verkossa on paljon soittimia. Tämä on yleinen ongelma myös langattomissa verkoissa. Voit muuttaa oletusviivettä tarvittaessa. + FR Lorsque plusieurs platines sont synchronisées, le Logitech Media Server indique à chacune de démarrer la lecture du morceau en même temps. Le serveur vérifie que chaque platine dispose d'assez de temps pour recevoir la commande avant de démarrer. Il envoie donc la commande en avance et chaque platine attend le bon moment pour démarrer. Si le réseau est surchargé, comme cela peut être le cas si de nombreuses platines sont présentes et avec des réseaux sans fil, le délai de 100 ms par défaut peut ne pas être suffisant. Vous pouvez modifier la valeur par défaut si nécessaire. + IT Quando più lettori sono sincronizzati, Logitech Media Server ordina a ciascun lettore di avviare la riproduzione del brano simultaneamente. A questo scopo, deve assicurarsi che ciascun lettore abbia il tempo di ricevere il comando di avvio prima dell'inizio della riproduzione, pertanto invia il comando di avvio con un certo anticipo in modo che ciascun lettore sia pronto a iniziare al momento giusto. Se il traffico di rete è eccessivo, come può succedere se sono connessi numerosi utenti in particolare nelle reti senza fili, il ritardo predefinito di 100 ms potrebbe non essere sufficiente. Se necessario, è possibile modificare questo valore predefinito. + NL Wanneer meerdere muzieksystemen worden gesynchroniseerd, geeft Logitech Media Server elk systeem de opdracht het nummer op hetzelfde moment te starten. Logitech Media Server moet ervoor zorgen dat elk systeem genoeg tijd heeft om de startopdracht te ontvangen voordat alle systemen samen starten, en daarom wordt de startopdracht van tevoren verzonden en wacht elk systeem tot het juiste moment om te starten. Als het netwerkverkeer overbelast is, wat voornamelijk kan gebeuren bij netwerken met vele systemen of bij draadloze netwerken, is de standaardvertraging van 100 milliseconden misschien niet voldoende. Je kunt de standaardvertraging hier desgewenst wijzigen. + NO Når flere spillere er synkronisert, sender Logitech Media Server beskjed til hver spiller om å begynne avspilling samtidig. Den må sikre at hver spiller får tid til å motta kommandoen før de alle starter samtidig, så den sender derfor startkommandoen på forhånd, og så venter spillerne til riktig øyeblikk før de starter. Hvis det er mye nettverkstrafikk, noe som kan skje hvis det er mange spillere på nettverket og ved bruk av trådløse nettverk, kan det hende at standardforsinkelsen på 100 ms er for kort. Hvis nødvendig kan du endre standardverdien her. + PL W przypadku zsynchronizowania kilku odtwarzaczy program Logitech Media Server wysyła do każdego odtwarzacza polecenie rozpoczęcia odtwarzania utworu w tym samym czasie. Program musi sprawdzić, czy każdy odtwarzacz ma czas na odebranie polecenia rozpoczęcia przed rozpoczęciem jednoczesnego odtwarzania, więc wysyła wcześniej polecenie rozpoczęcia, a odtwarzacze rozpoczynają pracę w odpowiedniej chwili. W przypadku nadmiernego przeciążenia sieci, które występuje szczególnie wtedy, gdy w sieciach standardowych i bezprzewodowych używana jest duża liczba odtwarzaczy, domyślne opóźnienie o długości 100 ms może być niewystarczające. W razie potrzeby wartość domyślną można zmienić tutaj. + RU При синхронизации нескольких плееров Logitech Media Server дает каждому из них команду начать воспроизведение дорожки в одно и то же время. Для этого необходимо убедиться, что каждый плеер получит команду запуска до всеобщего начала воспроизведения, поэтому данная команда отправляется ему заранее. После получения команды каждый плеер ожидает запуска. При сильной загрузке сети, что особенно характерно для сетей со множеством плееров и для беспроводных сетей, задержка по умолчанию, равная 100 мс, может быть недостаточной. При необходимости это значение можно изменить. + SV När flera spelare synkroniserats ser Logitech Media Server till att alla spelare börjar spela upp låten samtidigt. Det måste finnas tid för startkommandot att gå fram till var och en av spelarna innan låten börjar spelas upp. Därför skickas kommandot i förväg, och spelarna väntar sedan till rätt startögonblick. Om trafiken på nätverket är mycket tät, något som kan hända framför allt när många spelare anslutits och med trådlösa nätverk, kanske inte standardfördröjningen på 100 millisekunder räcker till. Du kan ändra standardinställningen här vid behov. SETUP_STARTDELAY CS Zpoždění spuštění přehrávače (ms) @@ -4947,19 +4948,19 @@ SETUP_STARTDELAY SV Fördröjning för spelarstart (ms) SETUP_STARTDELAY_DESC - CS Přehrávači může trvat nezanedbatelnou dobu, než spustí přehrávání (než začnete poslouchat hudbu) po zpracování příkazu ke startu od Squeezebox Server. To může nastat v případě, když se používají digitální výstupy (v závislosti na připojením zařízení) nebo u softwarových přehrávačů na určitých platformách. V těchto případech lze nastavit zde toto zpoždění tak, aby Squeezebox Server věděl, o kolik dříve musí spustit tento přehrávač, aby hudba ze všech synchronizovaných přehrávačů začala ve stejnou dobu. Poznámka: toto se přičítá k případnému "Zpoždění audia přehrávače" (níže). - DA Det kan vare lidt fra du klikker på startknappen i Squeezebox Server til afspilningen begynder (før du kan høre noget). Det kan forekomme når de digitale udgange bruges (afhængigt af hvad der er tilsluttet) eller i forbindelse med softwareafspillere på nogle platforme. I så fald kan du indstille en forsinkelse her sådan at Squeezebox Server ved hvor meget tidligere afspilleren skal startes sådan at lyden på alle de synkroniserede afspillere startes på samme tid. Bemærk: Denne indstilling er i tillæg til en permanent indstilling af Lydforsinkelse for afspiller (nedenfor). - DE Es kann eine gewisse Zeit dauern, bis ein Player die Wiedergabe beginnt (bis Sie die Musik hören), nachdem der von Squeezebox Server empfangene Startbefehl verarbeitet wurde. Dies kann bei der Nutzung digitaler Ausgänge (abhängig vom angeschlossenen Gerät) oder bei bestimmten Software-Playern unter bestimmten Plattformen vorkommen. Sie können dann diese Verzögerung hier festlegen, damit Squeezebox Server weiß, wie bald dieser Player gestartet werden soll, damit die Wiedergabe aus allen synchronisierten Playern gleichzeitig gestartet wird. Hinweis: Diese Verzögerung gilt zusätzlich zu 'Audioverzögerung des Players' (siehe unten). - EN A player can take a noticeable time to start playing (before you begin to hear the audio) after it processes the start command from Squeezebox Server. This can be the case when using digital outputs (depending upon the connected equipment) or with software players on some platforms. In these cases, this delay can be set here so that Squeezebox Server knows how much in advance to start this player so that the audio from all the synchronized players starts at the same time. Note: this is in addition to any ongoing "Player Audio Delay" (below). - ES Un reproductor puede tardar en iniciar la reproducción (antes de que el usuario oiga el audio) después de procesar el comando de inicio enviado por Squeezebox Server. Éste puede ser el caso al utilizar salidas digitales (según el equipo conectado) o al utilizar ciertos reproductores por software en algunas plataformas. En estos casos, es posible especificar el retraso aquí para que Squeezebox Server sepa con cuánta antelación debe iniciar este reproductor para que el audio de todos los reproductores sincronizados se inicie al mismo tiempo. Nota: este valor es una adición a cualquier configuración de "Retraso de audio de reproductor" (abajo). - FI Saattaa kulua huomattava aika, ennen kuin soitin aloittaa toiston (ennen kuin ääni alkaa kuulua), sen jälkeen, kun Squeezebox Server on antanut aloittamiskomennon. Näin saattaa käydä, jos käytetään digitaalilähtöjä (riippuen yhdistetyistä laitteista). Joissakin käyttöjärjestelmissä esiintyy myös ongelmia soitinohjelmistojen kanssa. Tällaisessa tapauksessa viive voidaan määrittää tässä, jotta Squeezebox Server tietää, kuinka paljon etukäteen soitin pitää käynnistää, jotta ääni alkaa kuulua samanaikaisesti kaikista synkronoiduista soittimista. Huomaa: tämä viive on lisäys soittimen äänen normaaliin viiveeseen (alla). - FR Il est possible qu'une platine mette un certain temps à démarrer (avant d'entendre le morceau lu) après avoir reçu la commande de démarrage du serveur. Tel peut être le cas avec des sorties numériques (en fonction de l'équipement connecté) ou avec des lecteurs logiciels sur certaines plates-formes. Dans de tels cas, il est possible de régler le délai pour que le Squeezebox Server connaisse le délai en fonction duquel il doit démarrer cette platine en avance afin que l'audio de toutes les platines synchronisées démarre en même temps. Remarque: cette valeur est ajoutée à celle définie pour Délai audio de la platine (ci-dessous). - IT L'avvio della riproduzione di un lettore può richiedere un intervallo considerevole (prima che venga emesso l'audio) dopo l'elaborazione del comando di avvio in Squeezebox Server. Un caso del genere può verificarsi quando si utilizzano ingressi digitali (a seconda dell'apparecchiatura collegata) o con lettori software di alcune piattaforme. In questi casi il ritardo qui impostato consente di definire con quanto anticipo Squeezebox Server deve avviare il lettore per consentire l'inizio simultaneo della riproduzione in tutti i lettori sincronizzati. Nota: questo ritardo si aggiunge a quello impostato in "Ritardo audio lettore" (sotto). - NL Nadat een muzieksysteem de startopdracht van Squeezebox Server heeft verwerkt, kan het een tijdje duren voordat het systeem begint met afspelen (voordat je de audio hoort). Dit kan het geval zijn bij gebruik van digitale uitgangen (afhankelijk van de aangesloten apparatuur) of bij softwarespelers op sommige platforms. Deze vertraging kan dan hier worden ingesteld, zodat Squeezebox Server weet hoever van tevoren dit systeem moet worden gestart om de audio uit alle gesynchroniseerde systemen tegelijk te laten beginnen. N.B. Deze optie kan ook ingesteld worden terwijl Audiovertraging muzieksysteem (hieronder) actief is. - NO Det kan ta noe tid før spilleren begynner avspillingen (dvs. før du hører lyden) etter at den har prosessert startkommandoen fra Squeezebox Server. Dette kan skje når du bruker digitale utganger (avhengig av utstyret som er koplet til), eller med spillerprogrammer på enkelte plattformer. Hvis dette skjer, kan du legge inn denne forsinkelsen her, slik at Squeezebox Server vet hvor mye tidligere den må starte denne spilleren for å synkronisere lyden fra alle synkroniserte spillere. Merk: dette kommer i tillegg til eventuell «Lydforsinkelse for spiller» (nedenfor). - PL Rozpoczęcie odtwarzania (zanim usłyszysz dźwięk) po przetworzeniu przez odtwarzacz polecenia uruchomienia z programu Squeezebox Server może być zauważalnie opóźnione. Może to mieć miejsce w przypadku korzystania z wyjść cyfrowych (w zależności od podłączonych urządzeń) lub odtwarzaczy programowych na niektórych platformach. W takich przypadkach opóźnienie to można ustawić tutaj, aby program Squeezebox Server uruchomił odtwarzacz odpowiednio wcześniej w celu jednoczesnego uruchomienia wszystkich zsynchronizowanych odtwarzaczy. Uwaga: opcja ta stanowi dodatek dla ustawienia „Opóźnienie dźwięku odtwarzacza” (poniżej). - RU После обработки команды запуска Squeezebox Server плеер может начать воспроизведение лишь через некоторое время (до того, как появится звук). Обычно это происходит при работе с цифровыми выходами (в зависимости от подключенного оборудования) или с программными плеерами на некоторых платформах. В этих случаях можно настроить длительность задержки таким образом, чтобы Squeezebox Server запускал данный плеер заблаговременно и звук со всех синхронизованных плееров появлялся в одно и то же время. Примечание: этот параметр дополняет любое из текущих значений "Задержка звука плеера" (см. ниже). - SV Det kan ta en ganska lång stund från det att en spelare tar emot startkommandot från Squeezebox Server till det att du hör musiken börja spelas upp. Det här kan inträffa när digitala utgångar används (beroende på den anslutna utrustningen) eller med programvarubaserade spelare på vissa plattformar. För att undvika problemet kan du ange fördröjningen här. Då kan den här spelaren startas motsvarande antal sekunder i förväg, så att ljudet från alla de synkroniserade spelarna börjar spelas upp samtidigt. Obs! det här läggs till eventuell Ljudfördröjning för spelare (se nedan). + CS Přehrávači může trvat nezanedbatelnou dobu, než spustí přehrávání (než začnete poslouchat hudbu) po zpracování příkazu ke startu od Logitech Media Server. To může nastat v případě, když se používají digitální výstupy (v závislosti na připojením zařízení) nebo u softwarových přehrávačů na určitých platformách. V těchto případech lze nastavit zde toto zpoždění tak, aby Logitech Media Server věděl, o kolik dříve musí spustit tento přehrávač, aby hudba ze všech synchronizovaných přehrávačů začala ve stejnou dobu. Poznámka: toto se přičítá k případnému "Zpoždění audia přehrávače" (níže). + DA Det kan vare lidt fra du klikker på startknappen i Logitech Media Server til afspilningen begynder (før du kan høre noget). Det kan forekomme når de digitale udgange bruges (afhængigt af hvad der er tilsluttet) eller i forbindelse med softwareafspillere på nogle platforme. I så fald kan du indstille en forsinkelse her sådan at Logitech Media Server ved hvor meget tidligere afspilleren skal startes sådan at lyden på alle de synkroniserede afspillere startes på samme tid. Bemærk: Denne indstilling er i tillæg til en permanent indstilling af Lydforsinkelse for afspiller (nedenfor). + DE Es kann eine gewisse Zeit dauern, bis ein Player die Wiedergabe beginnt (bis Sie die Musik hören), nachdem der von Logitech Media Server empfangene Startbefehl verarbeitet wurde. Dies kann bei der Nutzung digitaler Ausgänge (abhängig vom angeschlossenen Gerät) oder bei bestimmten Software-Playern unter bestimmten Plattformen vorkommen. Sie können dann diese Verzögerung hier festlegen, damit Logitech Media Server weiß, wie bald dieser Player gestartet werden soll, damit die Wiedergabe aus allen synchronisierten Playern gleichzeitig gestartet wird. Hinweis: Diese Verzögerung gilt zusätzlich zu 'Audioverzögerung des Players' (siehe unten). + EN A player can take a noticeable time to start playing (before you begin to hear the audio) after it processes the start command from Logitech Media Server. This can be the case when using digital outputs (depending upon the connected equipment) or with software players on some platforms. In these cases, this delay can be set here so that Logitech Media Server knows how much in advance to start this player so that the audio from all the synchronized players starts at the same time. Note: this is in addition to any ongoing "Player Audio Delay" (below). + ES Un reproductor puede tardar en iniciar la reproducción (antes de que el usuario oiga el audio) después de procesar el comando de inicio enviado por Logitech Media Server. Éste puede ser el caso al utilizar salidas digitales (según el equipo conectado) o al utilizar ciertos reproductores por software en algunas plataformas. En estos casos, es posible especificar el retraso aquí para que Logitech Media Server sepa con cuánta antelación debe iniciar este reproductor para que el audio de todos los reproductores sincronizados se inicie al mismo tiempo. Nota: este valor es una adición a cualquier configuración de "Retraso de audio de reproductor" (abajo). + FI Saattaa kulua huomattava aika, ennen kuin soitin aloittaa toiston (ennen kuin ääni alkaa kuulua), sen jälkeen, kun Logitech Media Server on antanut aloittamiskomennon. Näin saattaa käydä, jos käytetään digitaalilähtöjä (riippuen yhdistetyistä laitteista). Joissakin käyttöjärjestelmissä esiintyy myös ongelmia soitinohjelmistojen kanssa. Tällaisessa tapauksessa viive voidaan määrittää tässä, jotta Logitech Media Server tietää, kuinka paljon etukäteen soitin pitää käynnistää, jotta ääni alkaa kuulua samanaikaisesti kaikista synkronoiduista soittimista. Huomaa: tämä viive on lisäys soittimen äänen normaaliin viiveeseen (alla). + FR Il est possible qu'une platine mette un certain temps à démarrer (avant d'entendre le morceau lu) après avoir reçu la commande de démarrage du serveur. Tel peut être le cas avec des sorties numériques (en fonction de l'équipement connecté) ou avec des lecteurs logiciels sur certaines plates-formes. Dans de tels cas, il est possible de régler le délai pour que le Logitech Media Server connaisse le délai en fonction duquel il doit démarrer cette platine en avance afin que l'audio de toutes les platines synchronisées démarre en même temps. Remarque: cette valeur est ajoutée à celle définie pour Délai audio de la platine (ci-dessous). + IT L'avvio della riproduzione di un lettore può richiedere un intervallo considerevole (prima che venga emesso l'audio) dopo l'elaborazione del comando di avvio in Logitech Media Server. Un caso del genere può verificarsi quando si utilizzano ingressi digitali (a seconda dell'apparecchiatura collegata) o con lettori software di alcune piattaforme. In questi casi il ritardo qui impostato consente di definire con quanto anticipo Logitech Media Server deve avviare il lettore per consentire l'inizio simultaneo della riproduzione in tutti i lettori sincronizzati. Nota: questo ritardo si aggiunge a quello impostato in "Ritardo audio lettore" (sotto). + NL Nadat een muzieksysteem de startopdracht van Logitech Media Server heeft verwerkt, kan het een tijdje duren voordat het systeem begint met afspelen (voordat je de audio hoort). Dit kan het geval zijn bij gebruik van digitale uitgangen (afhankelijk van de aangesloten apparatuur) of bij softwarespelers op sommige platforms. Deze vertraging kan dan hier worden ingesteld, zodat Logitech Media Server weet hoever van tevoren dit systeem moet worden gestart om de audio uit alle gesynchroniseerde systemen tegelijk te laten beginnen. N.B. Deze optie kan ook ingesteld worden terwijl Audiovertraging muzieksysteem (hieronder) actief is. + NO Det kan ta noe tid før spilleren begynner avspillingen (dvs. før du hører lyden) etter at den har prosessert startkommandoen fra Logitech Media Server. Dette kan skje når du bruker digitale utganger (avhengig av utstyret som er koplet til), eller med spillerprogrammer på enkelte plattformer. Hvis dette skjer, kan du legge inn denne forsinkelsen her, slik at Logitech Media Server vet hvor mye tidligere den må starte denne spilleren for å synkronisere lyden fra alle synkroniserte spillere. Merk: dette kommer i tillegg til eventuell «Lydforsinkelse for spiller» (nedenfor). + PL Rozpoczęcie odtwarzania (zanim usłyszysz dźwięk) po przetworzeniu przez odtwarzacz polecenia uruchomienia z programu Logitech Media Server może być zauważalnie opóźnione. Może to mieć miejsce w przypadku korzystania z wyjść cyfrowych (w zależności od podłączonych urządzeń) lub odtwarzaczy programowych na niektórych platformach. W takich przypadkach opóźnienie to można ustawić tutaj, aby program Logitech Media Server uruchomił odtwarzacz odpowiednio wcześniej w celu jednoczesnego uruchomienia wszystkich zsynchronizowanych odtwarzaczy. Uwaga: opcja ta stanowi dodatek dla ustawienia „Opóźnienie dźwięku odtwarzacza” (poniżej). + RU После обработки команды запуска Logitech Media Server плеер может начать воспроизведение лишь через некоторое время (до того, как появится звук). Обычно это происходит при работе с цифровыми выходами (в зависимости от подключенного оборудования) или с программными плеерами на некоторых платформах. В этих случаях можно настроить длительность задержки таким образом, чтобы Logitech Media Server запускал данный плеер заблаговременно и звук со всех синхронизованных плееров появлялся в одно и то же время. Примечание: этот параметр дополняет любое из текущих значений "Задержка звука плеера" (см. ниже). + SV Det kan ta en ganska lång stund från det att en spelare tar emot startkommandot från Logitech Media Server till det att du hör musiken börja spelas upp. Det här kan inträffa när digitala utgångar används (beroende på den anslutna utrustningen) eller med programvarubaserade spelare på vissa plattformar. För att undvika problemet kan du ange fördröjningen här. Då kan den här spelaren startas motsvarande antal sekunder i förväg, så att ljudet från alla de synkroniserade spelarna börjar spelas upp samtidigt. Obs! det här läggs till eventuell Ljudfördröjning för spelare (se nedan). SETUP_MAINTAINSYNC CS Udržovat synchronizaci @@ -4977,19 +4978,19 @@ SETUP_MAINTAINSYNC SV Upprätthåll synkronisering SETUP_MAINTAINSYNC_DESC - CS I když přehrávače začnou přehrávat stopu v dokonalé synchronizaci, mohou se za určitou dobu rozejít (obvykle během několika minut). Rozdíl o více než 30 ms (milisekund) již bude znatelný, pokud posloucháte současně výstup z několika přehrávačů. Squeezebox Server tento problém řeší nepřetržitým sledováním, kolik každý přehrávač odehrál a prováděním případných malých úprav. Tuto funkci můžete zapnout nebo vypnout. - DA Selv hvis flere afspillere er perfekt synkroniseret når afspilningen begynder, kan der opstå afvigelser i løbet af kort tid (som regel efter et par minutter). Forskelle på mere end 30 millisekunder er hørbare hvis du kan høre flere afspillere på samme tid. Squeezebox Server håndterer dette ved kontinuerligt at registrere hvor meget hver afspiller har spillet, og i givet fald foretage småjusteringer. Du kan slå denne funktion til og fra. - DE Auch wenn mehrere Player die Wiedergabe eines Titels gleichzeitig starten, können sie nach einer gewissen Zeit (i.d.R. nach ein paar Minuten) voneinander abweichen. Eine Differenz von mehr als 30 ms ist wahrnehmbar, wenn die Ausgabe mehrerer Player gleichzeitig gehört werden kann. Squeezebox Server prüft ständig, wie viel ein Player wiedergegeben hat und nimmt bei Bedarf Änderungen vor. Sie können dieses Verhalten aktivieren bzw. deaktivieren. - EN Even when several players start playing a track in perfect synchronization, they can drift apart over time (usually after a few minutes). A difference of more than about 30ms (milliseconds) will be noticeable if you can hear the output from multiple players simultaneously. Squeezebox Server deals with this by continuously tracking how much each player has played and making small adjustments as necessary. You can turn this behaviour on or off. - ES Aunque varios reproductores empiecen a reproducir una pista perfectamente sincronizados, pueden perder la sincronización al cabo de un tiempo (a menudo es cuestión de minutos). Si hay una diferencia de más de 30 ms (milisegundos) es perceptible cuando hay salida de música a través de varios reproductores simultáneamente. Squeezebox Server intenta remediarlo mediante el seguimiento continuo de cada reproductor y la realización de los ajustes necesarios. Esta función se puede activar o desactivar. - FI Vaikka useat soittimet aloittaisivatkin kappaleen soiton täysin synkronoidusti, ajan myötä (yleensä muutaman minuutin kuluttua) niiden välille syntyy eroja. Yli 30 millisekunnin ero on havaittava, jos kuulet musiikin useista lähteistä samanaikaisesti. Squeezebox Server pyrkii korjaamaan virheen seuraamalla jatkuvasti sitä, kuinka pitkään kukin soitin on soittanut, ja tekemällä pieniä säätöjä tarpeen mukaan. Voit valita, pidätkö toiminnon käytössä. - FR Même lorsque plusieurs platines commencent à lire un morceau en parfaite synchronisation, il est possible qu'elles se désynchronisent au fil du temps (après quelques minutes, en général). Une différence de plus de 30ms sera perceptible si vous pouvez entendre le son en provenance de ces platines. Le Squeezebox Server effectue le suivi des morceaux lus par chaque platine et effectue les ajustements nécessaires. Vous pouvez activer ou désactiver ce comportement. - IT Anche se un brano viene inizialmente riprodotto con più lettori in perfetta sincronia, è possibile che nell'arco di alcuni minuti la riproduzione non sia più sincronizzata. Se si ha la possibilità di ascoltare un brano con più lettori contemporaneamente, sarà percepibile una differenza superiore a 30 ms (millisecondi). Squeezebox Server risolve questo problema tenendo costantemente traccia della durata di brano riprodotta e apportando le eventuali regolazioni necessarie. È possibile attivare o disattivare questa funzione. - NL Zelfs wanneer verschillende muzieksystemen een nummer vanaf het begin perfect gesynchroniseerd afspelen, kunnen ze op een gegeven moment van elkaar afwijken (meestal na een paar minuten). Een verschil van meer dan 30 milliseconden is merkbaar als je de uitvoer van meerdere systemen tegelijk kunt horen. Squeezebox Server lost dit op door voortdurend bij te houden hoeveel elk systeem heeft afgespeeld en waar nodig kleine aanpassingen te maken. Je kunt dit gedrag in- of uitschakelen. - NO Selv når flere spillere spiller samme spor og er perfekt synkronisert, kan de gli fra hverandre over tid (vanligvis etter noen få minutter). Hvis forskjellen mellom to avspillinger er på mer enn rundt 30 millisekunder, vil du kunne merke det hvis du hører lyden fra flere spillere samtidig. Squeezebox Server håndterer dette ved å spore hvor mye hver spiller til enhver tid har spilt av, og ved å gjøre små endringer etter behov. Du kan slå denne justeringen av og på. - PL Nawet jeżeli kilka odtwarzaczy rozpocznie odtwarzanie utworu dokładnie w tym samym momencie, po pewnym czasie (zwykle po kilku minutach) nie będą już zsynchronizowane. Różnica większa niż 30 ms (milisekund) będzie zauważana w przypadku słuchania dźwięku z kilku odtwarzaczy jednocześnie. Program Squeezebox Server rozwiązuje ten problem przez stałe śledzenie, jaka część utworu została odtworzona przez dany odtwarzacz i wprowadzanie niewielkich zmian w razie potrzeby. Funkcję tę można włączyć lub wyłączyć. - RU Даже если несколько плееров начинают воспроизводить дорожку абсолютно синхронно, со временем (обычно через несколько минут) могут появиться расхождения. Расхождения более 30 мс будут заметны, если одновременно слушать музыку из нескольких плееров. Squeezebox Server решает эту проблему, отслеживая время работы каждого плеера и корректируя ход воспроизведения. Эту функцию можно включать и отключать. - SV Även om när flera spelare är perfekt synkroniserade när en låt börjar spelas upp, kan de komma i otakt senare (vanligtvis efter ett par minuter). Det går att höra tidsskillnader på över 30 millisekunder från flera spelare samtidigt. I Squeezebox Server hanteras det här problemet med att speltiden för varje spelare spåras, så att justeringar kan göras vid behov. Du kan aktivera eller avaktivera den här funktionen. + CS I když přehrávače začnou přehrávat stopu v dokonalé synchronizaci, mohou se za určitou dobu rozejít (obvykle během několika minut). Rozdíl o více než 30 ms (milisekund) již bude znatelný, pokud posloucháte současně výstup z několika přehrávačů. Logitech Media Server tento problém řeší nepřetržitým sledováním, kolik každý přehrávač odehrál a prováděním případných malých úprav. Tuto funkci můžete zapnout nebo vypnout. + DA Selv hvis flere afspillere er perfekt synkroniseret når afspilningen begynder, kan der opstå afvigelser i løbet af kort tid (som regel efter et par minutter). Forskelle på mere end 30 millisekunder er hørbare hvis du kan høre flere afspillere på samme tid. Logitech Media Server håndterer dette ved kontinuerligt at registrere hvor meget hver afspiller har spillet, og i givet fald foretage småjusteringer. Du kan slå denne funktion til og fra. + DE Auch wenn mehrere Player die Wiedergabe eines Titels gleichzeitig starten, können sie nach einer gewissen Zeit (i.d.R. nach ein paar Minuten) voneinander abweichen. Eine Differenz von mehr als 30 ms ist wahrnehmbar, wenn die Ausgabe mehrerer Player gleichzeitig gehört werden kann. Logitech Media Server prüft ständig, wie viel ein Player wiedergegeben hat und nimmt bei Bedarf Änderungen vor. Sie können dieses Verhalten aktivieren bzw. deaktivieren. + EN Even when several players start playing a track in perfect synchronization, they can drift apart over time (usually after a few minutes). A difference of more than about 30ms (milliseconds) will be noticeable if you can hear the output from multiple players simultaneously. Logitech Media Server deals with this by continuously tracking how much each player has played and making small adjustments as necessary. You can turn this behaviour on or off. + ES Aunque varios reproductores empiecen a reproducir una pista perfectamente sincronizados, pueden perder la sincronización al cabo de un tiempo (a menudo es cuestión de minutos). Si hay una diferencia de más de 30 ms (milisegundos) es perceptible cuando hay salida de música a través de varios reproductores simultáneamente. Logitech Media Server intenta remediarlo mediante el seguimiento continuo de cada reproductor y la realización de los ajustes necesarios. Esta función se puede activar o desactivar. + FI Vaikka useat soittimet aloittaisivatkin kappaleen soiton täysin synkronoidusti, ajan myötä (yleensä muutaman minuutin kuluttua) niiden välille syntyy eroja. Yli 30 millisekunnin ero on havaittava, jos kuulet musiikin useista lähteistä samanaikaisesti. Logitech Media Server pyrkii korjaamaan virheen seuraamalla jatkuvasti sitä, kuinka pitkään kukin soitin on soittanut, ja tekemällä pieniä säätöjä tarpeen mukaan. Voit valita, pidätkö toiminnon käytössä. + FR Même lorsque plusieurs platines commencent à lire un morceau en parfaite synchronisation, il est possible qu'elles se désynchronisent au fil du temps (après quelques minutes, en général). Une différence de plus de 30ms sera perceptible si vous pouvez entendre le son en provenance de ces platines. Le Logitech Media Server effectue le suivi des morceaux lus par chaque platine et effectue les ajustements nécessaires. Vous pouvez activer ou désactiver ce comportement. + IT Anche se un brano viene inizialmente riprodotto con più lettori in perfetta sincronia, è possibile che nell'arco di alcuni minuti la riproduzione non sia più sincronizzata. Se si ha la possibilità di ascoltare un brano con più lettori contemporaneamente, sarà percepibile una differenza superiore a 30 ms (millisecondi). Logitech Media Server risolve questo problema tenendo costantemente traccia della durata di brano riprodotta e apportando le eventuali regolazioni necessarie. È possibile attivare o disattivare questa funzione. + NL Zelfs wanneer verschillende muzieksystemen een nummer vanaf het begin perfect gesynchroniseerd afspelen, kunnen ze op een gegeven moment van elkaar afwijken (meestal na een paar minuten). Een verschil van meer dan 30 milliseconden is merkbaar als je de uitvoer van meerdere systemen tegelijk kunt horen. Logitech Media Server lost dit op door voortdurend bij te houden hoeveel elk systeem heeft afgespeeld en waar nodig kleine aanpassingen te maken. Je kunt dit gedrag in- of uitschakelen. + NO Selv når flere spillere spiller samme spor og er perfekt synkronisert, kan de gli fra hverandre over tid (vanligvis etter noen få minutter). Hvis forskjellen mellom to avspillinger er på mer enn rundt 30 millisekunder, vil du kunne merke det hvis du hører lyden fra flere spillere samtidig. Logitech Media Server håndterer dette ved å spore hvor mye hver spiller til enhver tid har spilt av, og ved å gjøre små endringer etter behov. Du kan slå denne justeringen av og på. + PL Nawet jeżeli kilka odtwarzaczy rozpocznie odtwarzanie utworu dokładnie w tym samym momencie, po pewnym czasie (zwykle po kilku minutach) nie będą już zsynchronizowane. Różnica większa niż 30 ms (milisekund) będzie zauważana w przypadku słuchania dźwięku z kilku odtwarzaczy jednocześnie. Program Logitech Media Server rozwiązuje ten problem przez stałe śledzenie, jaka część utworu została odtworzona przez dany odtwarzacz i wprowadzanie niewielkich zmian w razie potrzeby. Funkcję tę można włączyć lub wyłączyć. + RU Даже если несколько плееров начинают воспроизводить дорожку абсолютно синхронно, со временем (обычно через несколько минут) могут появиться расхождения. Расхождения более 30 мс будут заметны, если одновременно слушать музыку из нескольких плееров. Logitech Media Server решает эту проблему, отслеживая время работы каждого плеера и корректируя ход воспроизведения. Эту функцию можно включать и отключать. + SV Även om när flera spelare är perfekt synkroniserade när en låt börjar spelas upp, kan de komma i otakt senare (vanligtvis efter ett par minuter). Det går att höra tidsskillnader på över 30 millisekunder från flera spelare samtidigt. I Logitech Media Server hanteras det här problemet med att speltiden för varje spelare spåras, så att justeringar kan göras vid behov. Du kan aktivera eller avaktivera den här funktionen. SETUP_MAINTAINSYNC_ON CS Udržovat synchronizaci během přehrávání @@ -5037,19 +5038,19 @@ SETUP_PLAYDELAY SV Ljudfördröjning för spelare (ms) SETUP_PLAYDELAY_DESC - CS Může být výrazný rozdíl mezi tím, kolik přehraného času ze stopy oznamuje přehrávač do Squeezebox Server a jaký čas byl skutečně přehrán. To může nastat v případě použití digitálních výstupů (v závislosti na připojeném zařízení) nebo u softwarových přehrávačů na určitých platformách. V těchto případech lze toto zpoždění nastavit zde, takže Squeezebox Server je může při úpravě synchronizace vzít v úvahu. - DA Der kan være en mærkbar forskel mellem hvor meget af et nummer en afspiller meddeler Squeezebox Server at den har afspillet, og hvor meget hørbar lyd som er udsendt. Det kan forekomme når de digitale udgange bruges (afhængigt af hvad der er tilsluttet) eller i forbindelse med softwareafspillere på nogle platforme. I sådanne tilfælde kan der her angives en forsinkelse således at Squeezebox Server kan medtage denne værdi når synkroniseringen justeres. - DE Es kann ein wahrnehmbarer Unterschied zwischen der abgelaufenen Zeit, die der Player an Squeezebox Server meldet, und der tatsächlichen Wiedergabezeit auftreten. Dies kann bei der Nutzung digitaler Ausgänge (abhängig vom angeschlossenen Gerät) oder bei bestimmten Software-Playern unter bestimmten Plattformen vorkommen. In diesen Fällen können Sie hier die Verzögerung einstellen, damit diese von Squeezebox Server beim Anpassen der Synchronisation einbezogen wird. - EN There can be a noticeable difference between how much of a track that the player reports it has played to Squeezebox Server and how much audio has been heard. This can be the case when using digital outputs (depending upon the connected equipment) or with software players on some platforms. In these cases, this delay can be set here so that Squeezebox Server can take it into account when adjusting synchronization. - ES Puede haber una diferencia obvia entre la parte de una pista que el reproductor notifica como reproducida en Squeezebox Server y la cantidad de audio escuchada realmente. Éste puede ser el caso al utilizar salidas digitales (según el equipo conectado) o al utilizar ciertos reproductores por software en algunas plataformas. En estos casos, se puede especificar el retraso aquí, para que Squeezebox Server lo tenga en cuenta al ajustar la sincronización. - FI Saattaa olla huomattavia eroja sen välillä, kuinka suuren osan kappaleesta soitin ilmoittaa soittaneensa Squeezebox Serverille, ja sen, kuinka suuri osa kappaleesta on kuunneltu. Näin saattaa käydä, jos käytetään digitaalilähtöjä (riippuen yhdistetyistä laitteista). Joissakin käyttöjärjestelmissä esiintyy myös ongelmia soitinohjelmistojen kanssa. Tällaisessa tapauksessa viive voidaan määrittää tässä kohdassa, niin että Squeezebox Server voi ottaa sen huomioon synkronointia säätäessään. - FR Il peut y avoir une différence entre la durée de lecture d'un morceau écoulée indiquée par la platine et la quantité du morceau qui a effectivement été lue. Tel peut être le cas avec des sorties numériques (en fonction de l'équipement connecté) ou avec des lecteurs logiciels sur certaines plates-formes. Dans de tels cas, ce délai peut être défini ici de manière à ce que le Squeezebox Server le prenne en compte lors des ajustements de synchronisation. - IT Potrebbe sussistere una differenza notevole tra l'audio segnalato come riprodotto in Squeezebox Server con il lettore e quello effettivamente ascoltato. Un caso del genere può verificarsi quando si utilizzano ingressi digitali (a seconda dell'apparecchiatura collegata) o con lettori software di alcune piattaforme. In questo caso è possibile impostare qui un ritardo che Squeezebox Server terrà in considerazione durante la regolazione della sincronizzazione. - NL Er kan een merkbaar verschil zijn tussen hoeveel van een door het muzieksysteem gerapporteerd nummer naar Squeezebox Server is afgespeeld en hoeveel audio is gehoord. Dit kan het geval zijn bij gebruik van digitale uitgangen (afhankelijk van de aangesloten apparatuur) of bij softwaresystemen op sommige platforms. Deze vertraging kan dan hier worden ingesteld, zodat Squeezebox Server er rekening mee kan houden bij het aanpassen van de synchronisatie. - NO Det kan være markant forskjell på hvor mye av et spor som har blitt spilt av ifølge Squeezebox Server, og hvor mye lyd som faktisk har kommet ut. Dette kan skje når du bruker digitale utganger (avhengig av utstyret som er koplet til), eller med spillerprogrammer på enkelte plattformer. Hvis dette skjer, kan du legge inn denne forsinkelsen her, slik at Squeezebox Server tar den med i beregningen når den justerer synkroniseringen. - PL Różnica między czasem odtworzenia utworu przesłanym przez odtwarzacz do programu Squeezebox Server, a odtworzonym dźwiękiem może być znaczna. Może to mieć miejsce w przypadku korzystania z wyjść cyfrowych (w zależności od podłączonych urządzeń) lub odtwarzaczy programowych na niektórych platformach. W takich przypadkach opóźnienie to można ustawić tutaj, aby program Squeezebox Server uwzględniał je podczas dostosowywania synchronizacji. - RU Существует значительная разница между отчетом плеера о воспроизведенной части дорожки Squeezebox Server и фактической продолжительностью прослушанного аудио. Это бывает при использовании цифровых выходов (в зависимости от подключенного оборудования) или программных плееров на некоторых платформах. Для таких случаев здесь можно задать величину задержки, учитываемую Squeezebox Server при настройке синхронизации. - SV Det kan vara en märkbar skillnad mellan hur mycket ett spår som spelaren rapporterar till Squeezebox Server att den har spelat upp och hur mycket av spåret som lyssnaren faktiskt hört. Det här kan inträffa när digitala utgångar används (beroende på den anslutna utrustningen) eller med programvarubaserade spelare på vissa plattformar. Här kan du ange fördröjningen så att den kan tas med i beräkningen när synkroniseringen justeras i Squeezebox Server. + CS Může být výrazný rozdíl mezi tím, kolik přehraného času ze stopy oznamuje přehrávač do Logitech Media Server a jaký čas byl skutečně přehrán. To může nastat v případě použití digitálních výstupů (v závislosti na připojeném zařízení) nebo u softwarových přehrávačů na určitých platformách. V těchto případech lze toto zpoždění nastavit zde, takže Logitech Media Server je může při úpravě synchronizace vzít v úvahu. + DA Der kan være en mærkbar forskel mellem hvor meget af et nummer en afspiller meddeler Logitech Media Server at den har afspillet, og hvor meget hørbar lyd som er udsendt. Det kan forekomme når de digitale udgange bruges (afhængigt af hvad der er tilsluttet) eller i forbindelse med softwareafspillere på nogle platforme. I sådanne tilfælde kan der her angives en forsinkelse således at Logitech Media Server kan medtage denne værdi når synkroniseringen justeres. + DE Es kann ein wahrnehmbarer Unterschied zwischen der abgelaufenen Zeit, die der Player an Logitech Media Server meldet, und der tatsächlichen Wiedergabezeit auftreten. Dies kann bei der Nutzung digitaler Ausgänge (abhängig vom angeschlossenen Gerät) oder bei bestimmten Software-Playern unter bestimmten Plattformen vorkommen. In diesen Fällen können Sie hier die Verzögerung einstellen, damit diese von Logitech Media Server beim Anpassen der Synchronisation einbezogen wird. + EN There can be a noticeable difference between how much of a track that the player reports it has played to Logitech Media Server and how much audio has been heard. This can be the case when using digital outputs (depending upon the connected equipment) or with software players on some platforms. In these cases, this delay can be set here so that Logitech Media Server can take it into account when adjusting synchronization. + ES Puede haber una diferencia obvia entre la parte de una pista que el reproductor notifica como reproducida en Logitech Media Server y la cantidad de audio escuchada realmente. Éste puede ser el caso al utilizar salidas digitales (según el equipo conectado) o al utilizar ciertos reproductores por software en algunas plataformas. En estos casos, se puede especificar el retraso aquí, para que Logitech Media Server lo tenga en cuenta al ajustar la sincronización. + FI Saattaa olla huomattavia eroja sen välillä, kuinka suuren osan kappaleesta soitin ilmoittaa soittaneensa Logitech Media Serverille, ja sen, kuinka suuri osa kappaleesta on kuunneltu. Näin saattaa käydä, jos käytetään digitaalilähtöjä (riippuen yhdistetyistä laitteista). Joissakin käyttöjärjestelmissä esiintyy myös ongelmia soitinohjelmistojen kanssa. Tällaisessa tapauksessa viive voidaan määrittää tässä kohdassa, niin että Logitech Media Server voi ottaa sen huomioon synkronointia säätäessään. + FR Il peut y avoir une différence entre la durée de lecture d'un morceau écoulée indiquée par la platine et la quantité du morceau qui a effectivement été lue. Tel peut être le cas avec des sorties numériques (en fonction de l'équipement connecté) ou avec des lecteurs logiciels sur certaines plates-formes. Dans de tels cas, ce délai peut être défini ici de manière à ce que le Logitech Media Server le prenne en compte lors des ajustements de synchronisation. + IT Potrebbe sussistere una differenza notevole tra l'audio segnalato come riprodotto in Logitech Media Server con il lettore e quello effettivamente ascoltato. Un caso del genere può verificarsi quando si utilizzano ingressi digitali (a seconda dell'apparecchiatura collegata) o con lettori software di alcune piattaforme. In questo caso è possibile impostare qui un ritardo che Logitech Media Server terrà in considerazione durante la regolazione della sincronizzazione. + NL Er kan een merkbaar verschil zijn tussen hoeveel van een door het muzieksysteem gerapporteerd nummer naar Logitech Media Server is afgespeeld en hoeveel audio is gehoord. Dit kan het geval zijn bij gebruik van digitale uitgangen (afhankelijk van de aangesloten apparatuur) of bij softwaresystemen op sommige platforms. Deze vertraging kan dan hier worden ingesteld, zodat Logitech Media Server er rekening mee kan houden bij het aanpassen van de synchronisatie. + NO Det kan være markant forskjell på hvor mye av et spor som har blitt spilt av ifølge Logitech Media Server, og hvor mye lyd som faktisk har kommet ut. Dette kan skje når du bruker digitale utganger (avhengig av utstyret som er koplet til), eller med spillerprogrammer på enkelte plattformer. Hvis dette skjer, kan du legge inn denne forsinkelsen her, slik at Logitech Media Server tar den med i beregningen når den justerer synkroniseringen. + PL Różnica między czasem odtworzenia utworu przesłanym przez odtwarzacz do programu Logitech Media Server, a odtworzonym dźwiękiem może być znaczna. Może to mieć miejsce w przypadku korzystania z wyjść cyfrowych (w zależności od podłączonych urządzeń) lub odtwarzaczy programowych na niektórych platformach. W takich przypadkach opóźnienie to można ustawić tutaj, aby program Logitech Media Server uwzględniał je podczas dostosowywania synchronizacji. + RU Существует значительная разница между отчетом плеера о воспроизведенной части дорожки Logitech Media Server и фактической продолжительностью прослушанного аудио. Это бывает при использовании цифровых выходов (в зависимости от подключенного оборудования) или программных плееров на некоторых платформах. Для таких случаев здесь можно задать величину задержки, учитываемую Logitech Media Server при настройке синхронизации. + SV Det kan vara en märkbar skillnad mellan hur mycket ett spår som spelaren rapporterar till Logitech Media Server att den har spelat upp och hur mycket av spåret som lyssnaren faktiskt hört. Det här kan inträffa när digitala utgångar används (beroende på den anslutna utrustningen) eller med programvarubaserade spelare på vissa plattformar. Här kan du ange fördröjningen så att den kan tas med i beräkningen när synkroniseringen justeras i Logitech Media Server. SETUP_MINSYNCADJUST CS Nastavení minimální synchronizace (ms) @@ -5067,19 +5068,19 @@ SETUP_MINSYNCADJUST SV Minsta justering vid synkronisering (ms) SETUP_MINSYNCADJUST_DESC - CS Pokud Squeezebox Server zjistí, že dva synchronizované přehrávače jsou poněkud mimo vzájemnou synchronizaci, provede malou úpravu, obvykle na přehrávači, který je pozadu. Můžete konfigurovat minimální velikost těchto úprav pro tento přehrávač. Čím větší je tento interval, tím méně často budou prováděny tyto úpravy, ale tím více bude přehrávačům povoleno se rozejít. - DA Når Squeezebox Server registrerer at to synkroniserede afspillere ikke er helt synkroniseret, foretages der en mindre justering, normalt af den afspiller som er bagud. Du kan indstille hvor meget en afspiller højst må justeres. Jo større interval, jo sjældnere foretages justeringerne, og jo mere kan afspillerne miste deres synkronisering. - DE Wenn Squeezebox Server erkennt, dass die Synchronisation zweier Player leicht verschoben ist, wird i.d.R. am langsameren Player eine geringfügige Anpassung vorgenommen. Sie können die minimale Anpassung für diesen Player konfigurieren. Je größer dieses Intervall ist, desto seltener werden Anpassungen vorgenommen aber desto häufiger können Abweichungen vorkommen. - EN When Squeezebox Server detects that two synchronized players have gotten a little bit out of synchronization with each other, it makes a small adjustment, usually to the player that has gotten behind. You can configure the minimum size of such adjustments for this player. The larger this interval, the less frequent will be the adjustments but the more the players will be allowed to drift apart. - ES Cuando Squeezebox Server detecta una leve falta de sincronización entre dos reproductores sincronizados, realiza un pequeño ajuste, por lo general en el reproductor atrasado. Puede configurar el tamaño mínimo de los ajustes para este reproductor. Cuanto más largo sea el intervalo, menos frecuente será la realización de ajustes y mayor será la desincronización posible entre los reproductores. - FI Jos Squeezebox Server havaitsee, että kaksi synkronoitua soitinta on joutunut hieman epätahtiin toistensa kanssa, se tekee pienen säädön, yleensä soittimeen, joka on jäänyt jälkeen. Voit määrittää tällaisen säädön vähimmäiskoon tälle soittimelle. Mitä suurempi intervalli on, sitä harvemmin säätöjä tehdään, mutta sitä useammin soittimet myös joutuvat epätahtiin. - FR Lorsque le Squeezebox Server détecte que deux platines se sont désynchronisées, il effectue des ajustements, généralement sur la platine qui a pris du retard. Vous pouvez configurer la taille minimale de ces ajustements pour cette platine. Plus l'intervalle est important, plus les ajustements seront espacés. Les retards autorisés pour les platines seront ainsi plus importants. - IT Quando Squeezebox Server rileva che due lettori non sono più perfettamente sincronizzati, nella maggior parte dei casi apporta una lieve regolazione al lettore più lento. È possibile configurare le dimensioni minime di tali regolazioni nel lettore corrente. Intervalli maggiori riducono la frequenza delle regolazioni e comportano una maggiore differenza di sincronizzazione. - NL Wanneer Squeezebox Server detecteert dat twee muzieksystemen niet langer helemaal synchroon lopen, wordt er een kleine aanpassing gemaakt, meestal op het systeem dat achterloopt. Je kunt de minimumlengte van dergelijke aanpassingen voor dit systeem configureren. Hoe groter het interval, des te minder vaak er aanpassingen worden gemaakt en hoe groter de afwijking tussen de twee systemen wordt. - NO Når Squeezebox Server finner ut at to synkroniserte spillere ikke er helt i synk, utfører den en liten justering, vanligvis hos spilleren som er i bakleksa. Du kan konfigurere minstestørrelsen på slike justeringer for denne spilleren. Jo større intervallet er, jo mindre hyppige blir justeringene, men jo mer kan spillerne komme i utakt. - PL Gdy program Squeezebox Server wykryje, że dwa zsynchronizowane odtwarzacze są nieznacznie rozsynchronizowane, dokona niewielkich zmian, zwykle dotyczących odtwarzacza, w którym występuje opóźnienie. Możliwe jest skonfigurowanie minimalnego dostosowania dla tego odtwarzacza. Im większy jest interwał, tym rzadziej nastąpi zmiana, ale więcej odtwarzaczy nie będzie zsynchronizowanych. - RU Когда Squeezebox Server обнаруживает некоторое отклонение в синхронизации двух плееров, проводится небольшая регулировка, обычно по отношению к отставшему плееру. Можно настроить минимальный размер регулировки данного плеера. Чем больше заданный интервал, тем реже выполняется регулировка, но тем больше размер возможного отклонения синхронизованных плееров. - SV Om två synkroniserade spelare börjar komma i otakt åtgärdas detta av Squeezebox Server, oftast genom att spelaren som hamnat efter justeras. Du kan ändra den undre gränsen för vilka skillnader som justeras för den här spelaren. Ju högre tal du anger, desto mindre ofta görs justeringar, men då kommer också spelarna att tillåtas komma mer i otakt. + CS Pokud Logitech Media Server zjistí, že dva synchronizované přehrávače jsou poněkud mimo vzájemnou synchronizaci, provede malou úpravu, obvykle na přehrávači, který je pozadu. Můžete konfigurovat minimální velikost těchto úprav pro tento přehrávač. Čím větší je tento interval, tím méně často budou prováděny tyto úpravy, ale tím více bude přehrávačům povoleno se rozejít. + DA Når Logitech Media Server registrerer at to synkroniserede afspillere ikke er helt synkroniseret, foretages der en mindre justering, normalt af den afspiller som er bagud. Du kan indstille hvor meget en afspiller højst må justeres. Jo større interval, jo sjældnere foretages justeringerne, og jo mere kan afspillerne miste deres synkronisering. + DE Wenn Logitech Media Server erkennt, dass die Synchronisation zweier Player leicht verschoben ist, wird i.d.R. am langsameren Player eine geringfügige Anpassung vorgenommen. Sie können die minimale Anpassung für diesen Player konfigurieren. Je größer dieses Intervall ist, desto seltener werden Anpassungen vorgenommen aber desto häufiger können Abweichungen vorkommen. + EN When Logitech Media Server detects that two synchronized players have gotten a little bit out of synchronization with each other, it makes a small adjustment, usually to the player that has gotten behind. You can configure the minimum size of such adjustments for this player. The larger this interval, the less frequent will be the adjustments but the more the players will be allowed to drift apart. + ES Cuando Logitech Media Server detecta una leve falta de sincronización entre dos reproductores sincronizados, realiza un pequeño ajuste, por lo general en el reproductor atrasado. Puede configurar el tamaño mínimo de los ajustes para este reproductor. Cuanto más largo sea el intervalo, menos frecuente será la realización de ajustes y mayor será la desincronización posible entre los reproductores. + FI Jos Logitech Media Server havaitsee, että kaksi synkronoitua soitinta on joutunut hieman epätahtiin toistensa kanssa, se tekee pienen säädön, yleensä soittimeen, joka on jäänyt jälkeen. Voit määrittää tällaisen säädön vähimmäiskoon tälle soittimelle. Mitä suurempi intervalli on, sitä harvemmin säätöjä tehdään, mutta sitä useammin soittimet myös joutuvat epätahtiin. + FR Lorsque le Logitech Media Server détecte que deux platines se sont désynchronisées, il effectue des ajustements, généralement sur la platine qui a pris du retard. Vous pouvez configurer la taille minimale de ces ajustements pour cette platine. Plus l'intervalle est important, plus les ajustements seront espacés. Les retards autorisés pour les platines seront ainsi plus importants. + IT Quando Logitech Media Server rileva che due lettori non sono più perfettamente sincronizzati, nella maggior parte dei casi apporta una lieve regolazione al lettore più lento. È possibile configurare le dimensioni minime di tali regolazioni nel lettore corrente. Intervalli maggiori riducono la frequenza delle regolazioni e comportano una maggiore differenza di sincronizzazione. + NL Wanneer Logitech Media Server detecteert dat twee muzieksystemen niet langer helemaal synchroon lopen, wordt er een kleine aanpassing gemaakt, meestal op het systeem dat achterloopt. Je kunt de minimumlengte van dergelijke aanpassingen voor dit systeem configureren. Hoe groter het interval, des te minder vaak er aanpassingen worden gemaakt en hoe groter de afwijking tussen de twee systemen wordt. + NO Når Logitech Media Server finner ut at to synkroniserte spillere ikke er helt i synk, utfører den en liten justering, vanligvis hos spilleren som er i bakleksa. Du kan konfigurere minstestørrelsen på slike justeringer for denne spilleren. Jo større intervallet er, jo mindre hyppige blir justeringene, men jo mer kan spillerne komme i utakt. + PL Gdy program Logitech Media Server wykryje, że dwa zsynchronizowane odtwarzacze są nieznacznie rozsynchronizowane, dokona niewielkich zmian, zwykle dotyczących odtwarzacza, w którym występuje opóźnienie. Możliwe jest skonfigurowanie minimalnego dostosowania dla tego odtwarzacza. Im większy jest interwał, tym rzadziej nastąpi zmiana, ale więcej odtwarzaczy nie będzie zsynchronizowanych. + RU Когда Logitech Media Server обнаруживает некоторое отклонение в синхронизации двух плееров, проводится небольшая регулировка, обычно по отношению к отставшему плееру. Можно настроить минимальный размер регулировки данного плеера. Чем больше заданный интервал, тем реже выполняется регулировка, но тем больше размер возможного отклонения синхронизованных плееров. + SV Om två synkroniserade spelare börjar komma i otakt åtgärdas detta av Logitech Media Server, oftast genom att spelaren som hamnat efter justeras. Du kan ändra den undre gränsen för vilka skillnader som justeras för den här spelaren. Ju högre tal du anger, desto mindre ofta görs justeringar, men då kommer också spelarna att tillåtas komma mer i otakt. SETUP_PACKETLATENCY CS Zpoždění síťových paketů (ms) @@ -5097,19 +5098,19 @@ SETUP_PACKETLATENCY SV Svarstid för nätverkspaket (ms) SETUP_PACKETLATENCY_DESC - CS Squeezebox Server automaticky měří zpoždění sítě mezi sebou a přehrávačem. To je důležité při udržování synchronizace. Občas mohou být tato měření příliš rozporná a nelze je použít a v tomto případě zde můžete zadat obvyklou hodnotu. - DA Squeezebox Server måler automatisk netværksforsinkelsen mellem sig selv og afspilleren. Det er vigtigt når synkroniseringen skal opretholdes. Det sker at disse mål er for inkonsistente til at være praktisk anvendelige, og i så fald kan du angive en gennemsnitsværdi her. - DE Squeezebox Server misst automatisch die Netzwerk-Wartezeit zwischen der Anwendung und dem Player. Dies ist zum Beibehalten der Synchronisation wichtig. Wenn diese Messungen zu inkonsistent sind, empfehlen wir, hier einen typischen Wert einzugeben. - EN Squeezebox Server automatically measures the network latency between it and the player. This is important when maintaining synchronization. Occasionally these measurements can be too inconsistent to be useful, in which case you can specify a typical value here. - ES Squeezebox Server mide automáticamente la latencia de red entre el dispositivo y el reproductor. Esto es importante al mantener la sincronización. En ocasiones, puede que estas mediciones no sean lo suficientemente coherentes para resultar útiles; en ese caso puede especificar un valor típico aquí. - FI Squeezebox Server mittaa automaattisesti verkkoviiveen sen ja soittimen välillä. Tämä on tärkeää synkronoinnin ylläpitämistä varten. Toisinaan mittaukset saattava olla liian ristiriitaisia, jotta niistä olisi hyötyä. Tällaisessa tapauksessa voit määrittää tyypillisen arvon. - FR Le Squeezebox Server mesure automatiquement la latence du réseau entre le serveur et la platine. Ces données sont importantes pour conserver la synchronisation entre les deux. Il arrive que ces mesures soient incohérentes, auquel cas vous devrez spécifier une valeur ici. - IT Squeezebox Server calcola automaticamente la latenza di rete rispetto al lettore. Questo dato è fondamentale per mantenere la sincronizzazione. In alcuni casi questi calcoli producono risultati troppo disomogenei per poter essere utilizzati. Pertanto è possibile specificare un valore indicativo in questo punto. - NL Squeezebox Server meet automatisch de netwerkvertraging tussen zichzelf en het muzieksysteem. Dit is belangrijk voor het handhaven van synchronisatie. Af en toe zijn deze metingen te inconsistent om gebruikt te kunnen worden. In dat geval kun je hier een standaardwaarde opgeven. - NO Squeezebox Server måler automatisk nettverksforsinkelsen mellom seg selv og spilleren. Dette er viktig for å opprettholde synkronisering. Disse målingene kan iblant være for variable til at de kan brukes. Da kan du i stedet angi en typisk verdi her. - PL Program Squeezebox Server automatycznie mierzy opóźnienie sieci między nim a odtwarzaczem. Jest to ważne w celu zachowania synchronizacji. Czasami te pomiary mogą być bardzo niespójne, a przez to nieprzydatne. W takim przypadku można określić typową wartość w tym miejscu. - RU Squeezebox Server автоматически измеряет задержку в сети между ним и плеером. Это важно для сохранения синхронизации. Иногда эти измерения могут слишком отличаться друг от друга, чтобы выявить какую-то закономерность: в этом случае можно ввести типичное значение в данное поле. - SV Squeezebox Server mäter automatiskt nätverksfördröjningen mellan sig själv och spelaren. Det här är viktigt när du vill upprätthålla synkronisering. Ibland ger mätningarna så spridda resultat att de inte är användbara. I så fall anger du ett typvärde här. + CS Logitech Media Server automaticky měří zpoždění sítě mezi sebou a přehrávačem. To je důležité při udržování synchronizace. Občas mohou být tato měření příliš rozporná a nelze je použít a v tomto případě zde můžete zadat obvyklou hodnotu. + DA Logitech Media Server måler automatisk netværksforsinkelsen mellem sig selv og afspilleren. Det er vigtigt når synkroniseringen skal opretholdes. Det sker at disse mål er for inkonsistente til at være praktisk anvendelige, og i så fald kan du angive en gennemsnitsværdi her. + DE Logitech Media Server misst automatisch die Netzwerk-Wartezeit zwischen der Anwendung und dem Player. Dies ist zum Beibehalten der Synchronisation wichtig. Wenn diese Messungen zu inkonsistent sind, empfehlen wir, hier einen typischen Wert einzugeben. + EN Logitech Media Server automatically measures the network latency between it and the player. This is important when maintaining synchronization. Occasionally these measurements can be too inconsistent to be useful, in which case you can specify a typical value here. + ES Logitech Media Server mide automáticamente la latencia de red entre el dispositivo y el reproductor. Esto es importante al mantener la sincronización. En ocasiones, puede que estas mediciones no sean lo suficientemente coherentes para resultar útiles; en ese caso puede especificar un valor típico aquí. + FI Logitech Media Server mittaa automaattisesti verkkoviiveen sen ja soittimen välillä. Tämä on tärkeää synkronoinnin ylläpitämistä varten. Toisinaan mittaukset saattava olla liian ristiriitaisia, jotta niistä olisi hyötyä. Tällaisessa tapauksessa voit määrittää tyypillisen arvon. + FR Le Logitech Media Server mesure automatiquement la latence du réseau entre le serveur et la platine. Ces données sont importantes pour conserver la synchronisation entre les deux. Il arrive que ces mesures soient incohérentes, auquel cas vous devrez spécifier une valeur ici. + IT Logitech Media Server calcola automaticamente la latenza di rete rispetto al lettore. Questo dato è fondamentale per mantenere la sincronizzazione. In alcuni casi questi calcoli producono risultati troppo disomogenei per poter essere utilizzati. Pertanto è possibile specificare un valore indicativo in questo punto. + NL Logitech Media Server meet automatisch de netwerkvertraging tussen zichzelf en het muzieksysteem. Dit is belangrijk voor het handhaven van synchronisatie. Af en toe zijn deze metingen te inconsistent om gebruikt te kunnen worden. In dat geval kun je hier een standaardwaarde opgeven. + NO Logitech Media Server måler automatisk nettverksforsinkelsen mellom seg selv og spilleren. Dette er viktig for å opprettholde synkronisering. Disse målingene kan iblant være for variable til at de kan brukes. Da kan du i stedet angi en typisk verdi her. + PL Program Logitech Media Server automatycznie mierzy opóźnienie sieci między nim a odtwarzaczem. Jest to ważne w celu zachowania synchronizacji. Czasami te pomiary mogą być bardzo niespójne, a przez to nieprzydatne. W takim przypadku można określić typową wartość w tym miejscu. + RU Logitech Media Server автоматически измеряет задержку в сети между ним и плеером. Это важно для сохранения синхронизации. Иногда эти измерения могут слишком отличаться друг от друга, чтобы выявить какую-то закономерность: в этом случае можно ввести типичное значение в данное поле. + SV Logitech Media Server mäter automatiskt nätverksfördröjningen mellan sig själv och spelaren. Det här är viktigt när du vill upprätthålla synkronisering. Ibland ger mätningarna så spridda resultat att de inte är användbara. I så fall anger du ett typvärde här. SETUP_NOUPNP CS Klient UPnP @@ -5128,20 +5129,20 @@ SETUP_NOUPNP SV UPnP-klient SETUP_NOUPNP_DESC - CS Má Squeezebox Server hledat na vaší síti další servery médií UPnP? - DA Skal Squeezebox Server søge efter andre UPnP-medieservere på dit netværk? - DE Soll Squeezebox Server nach weiteren UPnP-Medienservern in Ihrem Netzwerk suchen? - EN Should Squeezebox Server look for other UPnP media servers on your network? - ES ¿Debe Squeezebox Server buscar otros servidores de medios UPnP en la red? - FI Haluatko, että Squeezebox Server etsii muita UPnP-mediapalvelimia verkosta? - FR Le Squeezebox Server doit-il rechercher d'autres serveurs UPnP sur le réseau? - HE האם ברצונך ש-Squeezebox Server יחפש אחר שרתי מדיה אחרים מסוג UPnP ברשת שלך? + CS Má Logitech Media Server hledat na vaší síti další servery médií UPnP? + DA Skal Logitech Media Server søge efter andre UPnP-medieservere på dit netværk? + DE Soll Logitech Media Server nach weiteren UPnP-Medienservern in Ihrem Netzwerk suchen? + EN Should Logitech Media Server look for other UPnP media servers on your network? + ES ¿Debe Logitech Media Server buscar otros servidores de medios UPnP en la red? + FI Haluatko, että Logitech Media Server etsii muita UPnP-mediapalvelimia verkosta? + FR Le Logitech Media Server doit-il rechercher d'autres serveurs UPnP sur le réseau? + HE האם ברצונך ש-Logitech Media Server יחפש אחר שרתי מדיה אחרים מסוג UPnP ברשת שלך? IT Cercare altri server multimediali UPnP nella rete? - NL Moet Squeezebox Server naar andere UPnP-mediaservers op je netwerk zoeken? - NO Vil du at Squeezebox Server skal se etter andre UPnP-medieservere i nettverket? - PL Czy program Squeezebox Server ma wyszukać inne serwery multimediów UPnP w sieci? + NL Moet Logitech Media Server naar andere UPnP-mediaservers op je netwerk zoeken? + NO Vil du at Logitech Media Server skal se etter andre UPnP-medieservere i nettverket? + PL Czy program Logitech Media Server ma wyszukać inne serwery multimediów UPnP w sieci? RU Выполнить поиск других медиа-серверов UPnP в вашей сети? - SV Ska Squeezebox Server söka efter andra UPnP-medieservrar på nätverket? + SV Ska Logitech Media Server söka efter andra UPnP-medieservrar på nätverket? SETUP_UPNP_ENABLE CS Aktivováno, hledat další servery médií UPnP. @@ -5170,7 +5171,7 @@ SETUP_UPNP_DISABLE HE מושבת, אל תחפש אחר שרתי מדיה אחרים מסוג UPnP. IT Disattivato. Non cercare altri server multimediali UPnP. NL Uitgeschakeld, niet naar andere UPnP-mediaservers zoeken. - NO Av. Squeezebox Server vil ikke se etter andre UPnP-medieservere. + NO Av. Logitech Media Server vil ikke se etter andre UPnP-medieservere. PL Wyłączone, nie wyszukuj innych serwerów multimediów UPnP. RU Отключено, не выполнять поиск других медиа-серверов UPnP. SV Aktiverad. Sök inte efter andra UPnP-medieservrar. @@ -5194,40 +5195,40 @@ SETUP_MAXBITRATE ZH_CN 限制比特率 SETUP_MAXBITRATE_DESC - CS Squeezebox Server může automaticky konvertovat vaše hudební soubory do WAV/AIFF nebo MP3 průběžně a snížit tak přenosovou rychlost (bitrate) dat přenášených datovým proudem do vašeho přehrávače. To je užitečné, pokud připojujete přehrávač ke Squeezebox Serveru přes Internet, nebo pokud máte problémy s přerušováním bezdrátové sítě. Můžete si zvolit maximální přenosovou rychlost (bitrate), jakou bude Squeezebox Server posílat datový proud do vašeho přehrávače. Skladby MP3 kódované na nižší přenosovou rychlost (bitrate), než je maximální přenosová rychlost, nebudou konvertovány. Pokud zvolíte Bez omezení, Squeezebox Server bude posílat datový proud vašich MP3 souborů bez konverze a vaše souboru jiných typů jako nekomprimované audio PCM. - DA Squeezebox Server kan automatisk konvertere musikfilerne til wav/aiff eller mp3 med en lavere bithastighed sådan at der ikke sendes så mange data til afspilleren. Det kan være praktisk hvis du etablerer forbindelse til afspilleren over internettet eller midlertidigt har problemer med et trådløst netværk. Du kan vælge den maksimale bithastighed som Squeezebox Server kan sende til afspilleren. Numre der er kodet som mp3 med en lavere bithastighed end den maksimale, bliver ikke konverteret. Hvis du vælger Ingen begrænsning, vil serveren streame dine mp3-filer uden konvertering og andre filtyper i ukomprimeret PCM-format. - DE Squeezebox Server kann WAV/AIFF- oder MP3-Dateien automatisch während der Wiedergabe in eine geringere Bitrate umwandeln. Das ist hilfreich, wenn Sie den Player übers Internet mit dem Server verbinden oder Probleme mit dem kabellosen Netzwerk haben. Sie können die maximale Bitrate definieren, mit der Squeezebox Server an den Player übertragen soll. MP3-Titel, die mit einer kleineren Bitrate als der maximalen Bitrate kodiert wurden, werden nicht umgewandelt. Wenn Sie 'Keine Beschränkung' wählen, überträgt Squeezebox Server die MP3-Dateien ohne Umwandlung und andere Dateiarten als unkomprimiertes PCM-Audio. - EN Squeezebox Server can automatically convert your music files to WAV/AIFF or MP3 on-the-fly to lower the bitrate of the data streamed to your player. This is useful if you are connecting your player to the server across the Internet or are having intermittent problems using a wireless network. You can choose the maximum bitrate that Squeezebox Server will stream to your player. MP3 songs encoded at a bitrate lower than the maximum bitrate won't be converted. If you choose No Limit, the server will stream your MP3 files without conversion and your other file types as uncompressed PCM audio. - ES Squeezebox Server puede convertir automáticamente los archivos de música a WAV/AIFF o MP3 al instante para reducir la velocidad de bits de los datos enviados por secuencias al reproductor. Resulta útil si se conecta el reproductor al servidor a través de Internet o si se producen problemas intermitentes con una red inalámbrica. Se puede elegir la velocidad de bits máxima que Squeezebox Server usará para el envío por secuencias al reproductor. No se convertirán las canciones MP3 codificadas a una velocidad de bits inferior a la velocidad de bits máxima. Si elige Sin límite, el servidor enviará por secuencias los archivos MP3 sin conversión y los demás tipos de archivo como audio PCM sin comprimir. - FI Squeezebox Server voi muuntaa musiikkitiedostot automaattisesti WAV/AIFF- tai MP3-tiedostoiksi lennosta. Tämä alentaa soittimeen virtautettujen tiedostojen bittinopeutta. Tämä on hyödyllistä, jos yhdistät soittimesi palvelimeen internetin välityksellä tai jos langattoman verkon kanssa on ajoittaisia ongelmia. Voit valita enimmäisbittinopeuden, jolla Squeezebox Server virtauttaa tiedostoja soittimeen. Enimmäisbittinopeutta hitaammalla bittinopeudella koodattuja MP3-tiedostoja ei muunneta. Jos valitset Ei rajoitusta, palvelin virtauttaa MP3-tiedostot muuntamattomina. Muut tiedostotyypit virtautetaan pakkamaattomina PCM-tiedostoina. - FR Le Squeezebox Server peut convertir automatiquement et à la volée vos fichiers de musique en WAV/AIFF ou MP3 afin de limiter le débit binaire envoyé à votre platine. Ce réglage est utile lorsque vous vous connectez au serveur par Internet ou via un réseau sans fil défectueux. Vous pouvez spécifier le débit maximal envoyé par le Squeezebox Server à votre platine. Les fichiers MP3 encodés à un débit inférieur à celui maximal ne seront pas transcodés. Si vous choisissez Pas de limite, le serveur enverra les fichiers MP3 sans transcodage et les autres types de fichiers au format PCM audio non compressé. - HE Squeezebox Server יכול להמיר קובצי מוסיקה לתבנית WAV/AIFF או MP3 באופן אוטומטי במהלך השמעת שירים כדי להוריד את קצב הסיביות של הנתונים המוזרמים לנגן. הגדרה זו שימושית אם אתה מחבר את הנגן ל-Squeezebox Server דרך האינטרנט או נתקל בבעיות של קיטועים בשימוש ברשת אלחוטית. באפשרותך לבחור את קצב הסיביות המרבי שבו Squeezebox Server יפעיל זרימות לנגן. שירים בתבנית MP3 שקודדו בקצב נתונים נמוך מזה המצוין להלן, לא יומרו. אם תבחר את האפשרות 'ללא הגבלה', Squeezebox Server יפעיל זרימות של קובצי MP3 מבלי להמירם ויפעיל את יתר סוגי הקבצים כשמע PCM לא דחוס. - IT In Squeezebox Server è possibile eseguire rapidamente la conversione automatica dei file musicali WAV/AIFF o MP3 in modo da ridurre il bitrate dei dati inviati al lettore. Questa operazione può essere utile se si collega il lettore a un server tramite Internet o se si verificano interruzioni saltuarie con una rete senza fili. È possibile impostare il bitrate massimo con cui inviare lo stream audio al lettore. I brani MP3 codificati a un bitrate inferiore a quello massimo non vengono convertiti. Se si sceglie Nessun limite, il server trasferisce i file MP3 senza convertirli e gli altri tipi di file come audio PCM non compresso. - JA Squeezebox Serverは、自動的にあなたの音楽ファイルをWAV/AIFFまたはMP3に変換します。ビットレートの最大値を設定することができます。「制限なし」を選択しますと、元のファイル通りのビットレートで再生されます。 - NL Squeezebox Server kan je muziekbestanden direct automatisch naar WAV/AIFF of MP3 converteren om gegevens met een lagere bitsnelheid naar je muzieksysteem te streamen. Dit is handig als je systeem via het internet met Squeezebox Server verbonden is, of als je af en toe problemen hebt met een draadloos netwerk. Je kunt kiezen met welke bitsnelheid Squeezebox Server maximaal naar je systeem zal streamen. MP3-liedjes die gecodeerd zijn met een lagere bitsnelheid dan de maximale bitsnelheid, worden niet geconverteerd. Als je 'Geen limiet' kiest, streamt Squeezebox Server MP3-bestanden zonder conversie en andere bestandstypen als niet-gecomprimeerde PCM-audio. - NO Squeezebox Server kan automatisk konvertere musikkfilene til wav/aiff eller mp3 under avspilling, for å begrense bithastigheten på datastrømmen til spilleren. Dette kan være nyttig hvis du kopler spilleren til serveren over Internett, eller hvis du har periodevise problemer med et trådløst nettverk. Du kan angi maksimal bithastighet for strømmingen til spilleren fra Squeezebox Server. Mp3-filer som er kodet med en lavere bithastighet enn maksimumhastigheten, blir ikke konvertert. Hvis du velger Ubegrenset, strømmer serveren mp3-filer uten konvertering, og andre filtyper som ukomprimert pcm-lyd. - PL Program Squeezebox Server może automatycznie przekonwertować w locie pliki WAV/AIFF lub MP3 na niższą szybkość transmisji bitów danych przesyłanych strumieniowo do odtwarzacza. Jest to przydatne w przypadku łączenia odtwarzacza z programem Squeezebox Server przez Internet lub tymczasowych problemów z siecią bezprzewodową. Możliwe jest także wybranie maksymalnej szybkości transmisji bitów danych przesyłanych strumieniowo przez program Squeezebox Server do odtwarzacza. Utwory w formacie MP3 zakodowane z szybkością transmisji bitów niższą niż podana poniżej nie zostaną przekonwertowane. Wybranie opcji Bez ograniczeń spowoduje, że program Squeezebox Server będzie strumieniowo przesyłał pliki MP3 bez konwersji, a pliki innych typów jako nieskompresowany dźwięk PCM. - RU Squeezebox Server может автоматически преобразовывать музыкальные файлы в формат WAV/AIFF или MP3 в режиме реального времени, чтобы уменьшить скорость передачи данных на плеер. Это удобно при подключении плеера к Squeezebox Server через Интернет или при неустойчивой работе беспроводной сети. Можно задать максимальную скорость передачи со Squeezebox Server на плеер. MP3-файлы со скоростью передачи ниже указанного значения преобразованы не будут. Если выбрать параметр "Без ограничений", Squeezebox Server будет передавать MP3-файлы без преобразования, а другие типы файлов — в виде PCM-аудио без сжатия. - SV Squeezebox Server kan automatiskt konvertera dina musikfiler till WAV/AIFF eller mp3 när de spelas upp. På så sätt minskas datamängden som överförs till spelaren. Det kan vara användbart om du ansluter spelaren till servern via Internet eller om du har tillfälliga problem med anslutningen till ett trådlöst nätverk. Du kan ange en maximal bithastighet för data som Squeezebox Server överför till spelaren. Mp3-låtar som kodats med lägre bithastigheter än den maximala bithastigheten konverteras inte. Om du väljer Ingen gräns överförs mp3-filer utan konvertering och andra filtyper som okomprimerat PCM-ljud. - ZH_CN Squeezebox Server可以将您的音乐文件自动并即时转换成WAV/AIFF或MP3格式,以降低流出到播放机的比特率。如果您的播放机与Squeezebox Server的联系经过互联网或您的无线网络有堵塞的问题存在,这个功能将会提供很好的帮助。您可以选择Squeezebox Server流出到播放机的最大比特率。如果MP3歌曲原有比特率低于如下则不被转换。如果您选择不限制比特率,Squeezebox Server将不会对您的MP3文件流出到播放机前进行任何转换。其他文件类型也会以未压缩的PCM音像格式流出到播放机。 + CS Logitech Media Server může automaticky konvertovat vaše hudební soubory do WAV/AIFF nebo MP3 průběžně a snížit tak přenosovou rychlost (bitrate) dat přenášených datovým proudem do vašeho přehrávače. To je užitečné, pokud připojujete přehrávač ke Logitech Media Serveru přes Internet, nebo pokud máte problémy s přerušováním bezdrátové sítě. Můžete si zvolit maximální přenosovou rychlost (bitrate), jakou bude Logitech Media Server posílat datový proud do vašeho přehrávače. Skladby MP3 kódované na nižší přenosovou rychlost (bitrate), než je maximální přenosová rychlost, nebudou konvertovány. Pokud zvolíte Bez omezení, Logitech Media Server bude posílat datový proud vašich MP3 souborů bez konverze a vaše souboru jiných typů jako nekomprimované audio PCM. + DA Logitech Media Server kan automatisk konvertere musikfilerne til wav/aiff eller mp3 med en lavere bithastighed sådan at der ikke sendes så mange data til afspilleren. Det kan være praktisk hvis du etablerer forbindelse til afspilleren over internettet eller midlertidigt har problemer med et trådløst netværk. Du kan vælge den maksimale bithastighed som Logitech Media Server kan sende til afspilleren. Numre der er kodet som mp3 med en lavere bithastighed end den maksimale, bliver ikke konverteret. Hvis du vælger Ingen begrænsning, vil serveren streame dine mp3-filer uden konvertering og andre filtyper i ukomprimeret PCM-format. + DE Logitech Media Server kann WAV/AIFF- oder MP3-Dateien automatisch während der Wiedergabe in eine geringere Bitrate umwandeln. Das ist hilfreich, wenn Sie den Player übers Internet mit dem Server verbinden oder Probleme mit dem kabellosen Netzwerk haben. Sie können die maximale Bitrate definieren, mit der Logitech Media Server an den Player übertragen soll. MP3-Titel, die mit einer kleineren Bitrate als der maximalen Bitrate kodiert wurden, werden nicht umgewandelt. Wenn Sie 'Keine Beschränkung' wählen, überträgt Logitech Media Server die MP3-Dateien ohne Umwandlung und andere Dateiarten als unkomprimiertes PCM-Audio. + EN Logitech Media Server can automatically convert your music files to WAV/AIFF or MP3 on-the-fly to lower the bitrate of the data streamed to your player. This is useful if you are connecting your player to the server across the Internet or are having intermittent problems using a wireless network. You can choose the maximum bitrate that Logitech Media Server will stream to your player. MP3 songs encoded at a bitrate lower than the maximum bitrate won't be converted. If you choose No Limit, the server will stream your MP3 files without conversion and your other file types as uncompressed PCM audio. + ES Logitech Media Server puede convertir automáticamente los archivos de música a WAV/AIFF o MP3 al instante para reducir la velocidad de bits de los datos enviados por secuencias al reproductor. Resulta útil si se conecta el reproductor al servidor a través de Internet o si se producen problemas intermitentes con una red inalámbrica. Se puede elegir la velocidad de bits máxima que Logitech Media Server usará para el envío por secuencias al reproductor. No se convertirán las canciones MP3 codificadas a una velocidad de bits inferior a la velocidad de bits máxima. Si elige Sin límite, el servidor enviará por secuencias los archivos MP3 sin conversión y los demás tipos de archivo como audio PCM sin comprimir. + FI Logitech Media Server voi muuntaa musiikkitiedostot automaattisesti WAV/AIFF- tai MP3-tiedostoiksi lennosta. Tämä alentaa soittimeen virtautettujen tiedostojen bittinopeutta. Tämä on hyödyllistä, jos yhdistät soittimesi palvelimeen internetin välityksellä tai jos langattoman verkon kanssa on ajoittaisia ongelmia. Voit valita enimmäisbittinopeuden, jolla Logitech Media Server virtauttaa tiedostoja soittimeen. Enimmäisbittinopeutta hitaammalla bittinopeudella koodattuja MP3-tiedostoja ei muunneta. Jos valitset Ei rajoitusta, palvelin virtauttaa MP3-tiedostot muuntamattomina. Muut tiedostotyypit virtautetaan pakkamaattomina PCM-tiedostoina. + FR Le Logitech Media Server peut convertir automatiquement et à la volée vos fichiers de musique en WAV/AIFF ou MP3 afin de limiter le débit binaire envoyé à votre platine. Ce réglage est utile lorsque vous vous connectez au serveur par Internet ou via un réseau sans fil défectueux. Vous pouvez spécifier le débit maximal envoyé par le Logitech Media Server à votre platine. Les fichiers MP3 encodés à un débit inférieur à celui maximal ne seront pas transcodés. Si vous choisissez Pas de limite, le serveur enverra les fichiers MP3 sans transcodage et les autres types de fichiers au format PCM audio non compressé. + HE Logitech Media Server יכול להמיר קובצי מוסיקה לתבנית WAV/AIFF או MP3 באופן אוטומטי במהלך השמעת שירים כדי להוריד את קצב הסיביות של הנתונים המוזרמים לנגן. הגדרה זו שימושית אם אתה מחבר את הנגן ל-Logitech Media Server דרך האינטרנט או נתקל בבעיות של קיטועים בשימוש ברשת אלחוטית. באפשרותך לבחור את קצב הסיביות המרבי שבו Logitech Media Server יפעיל זרימות לנגן. שירים בתבנית MP3 שקודדו בקצב נתונים נמוך מזה המצוין להלן, לא יומרו. אם תבחר את האפשרות 'ללא הגבלה', Logitech Media Server יפעיל זרימות של קובצי MP3 מבלי להמירם ויפעיל את יתר סוגי הקבצים כשמע PCM לא דחוס. + IT In Logitech Media Server è possibile eseguire rapidamente la conversione automatica dei file musicali WAV/AIFF o MP3 in modo da ridurre il bitrate dei dati inviati al lettore. Questa operazione può essere utile se si collega il lettore a un server tramite Internet o se si verificano interruzioni saltuarie con una rete senza fili. È possibile impostare il bitrate massimo con cui inviare lo stream audio al lettore. I brani MP3 codificati a un bitrate inferiore a quello massimo non vengono convertiti. Se si sceglie Nessun limite, il server trasferisce i file MP3 senza convertirli e gli altri tipi di file come audio PCM non compresso. + JA Logitech Media Serverは、自動的にあなたの音楽ファイルをWAV/AIFFまたはMP3に変換します。ビットレートの最大値を設定することができます。「制限なし」を選択しますと、元のファイル通りのビットレートで再生されます。 + NL Logitech Media Server kan je muziekbestanden direct automatisch naar WAV/AIFF of MP3 converteren om gegevens met een lagere bitsnelheid naar je muzieksysteem te streamen. Dit is handig als je systeem via het internet met Logitech Media Server verbonden is, of als je af en toe problemen hebt met een draadloos netwerk. Je kunt kiezen met welke bitsnelheid Logitech Media Server maximaal naar je systeem zal streamen. MP3-liedjes die gecodeerd zijn met een lagere bitsnelheid dan de maximale bitsnelheid, worden niet geconverteerd. Als je 'Geen limiet' kiest, streamt Logitech Media Server MP3-bestanden zonder conversie en andere bestandstypen als niet-gecomprimeerde PCM-audio. + NO Logitech Media Server kan automatisk konvertere musikkfilene til wav/aiff eller mp3 under avspilling, for å begrense bithastigheten på datastrømmen til spilleren. Dette kan være nyttig hvis du kopler spilleren til serveren over Internett, eller hvis du har periodevise problemer med et trådløst nettverk. Du kan angi maksimal bithastighet for strømmingen til spilleren fra Logitech Media Server. Mp3-filer som er kodet med en lavere bithastighet enn maksimumhastigheten, blir ikke konvertert. Hvis du velger Ubegrenset, strømmer serveren mp3-filer uten konvertering, og andre filtyper som ukomprimert pcm-lyd. + PL Program Logitech Media Server może automatycznie przekonwertować w locie pliki WAV/AIFF lub MP3 na niższą szybkość transmisji bitów danych przesyłanych strumieniowo do odtwarzacza. Jest to przydatne w przypadku łączenia odtwarzacza z programem Logitech Media Server przez Internet lub tymczasowych problemów z siecią bezprzewodową. Możliwe jest także wybranie maksymalnej szybkości transmisji bitów danych przesyłanych strumieniowo przez program Logitech Media Server do odtwarzacza. Utwory w formacie MP3 zakodowane z szybkością transmisji bitów niższą niż podana poniżej nie zostaną przekonwertowane. Wybranie opcji Bez ograniczeń spowoduje, że program Logitech Media Server będzie strumieniowo przesyłał pliki MP3 bez konwersji, a pliki innych typów jako nieskompresowany dźwięk PCM. + RU Logitech Media Server может автоматически преобразовывать музыкальные файлы в формат WAV/AIFF или MP3 в режиме реального времени, чтобы уменьшить скорость передачи данных на плеер. Это удобно при подключении плеера к Logitech Media Server через Интернет или при неустойчивой работе беспроводной сети. Можно задать максимальную скорость передачи со Logitech Media Server на плеер. MP3-файлы со скоростью передачи ниже указанного значения преобразованы не будут. Если выбрать параметр "Без ограничений", Logitech Media Server будет передавать MP3-файлы без преобразования, а другие типы файлов — в виде PCM-аудио без сжатия. + SV Logitech Media Server kan automatiskt konvertera dina musikfiler till WAV/AIFF eller mp3 när de spelas upp. På så sätt minskas datamängden som överförs till spelaren. Det kan vara användbart om du ansluter spelaren till servern via Internet eller om du har tillfälliga problem med anslutningen till ett trådlöst nätverk. Du kan ange en maximal bithastighet för data som Logitech Media Server överför till spelaren. Mp3-låtar som kodats med lägre bithastigheter än den maximala bithastigheten konverteras inte. Om du väljer Ingen gräns överförs mp3-filer utan konvertering och andra filtyper som okomprimerat PCM-ljud. + ZH_CN Logitech Media Server可以将您的音乐文件自动并即时转换成WAV/AIFF或MP3格式,以降低流出到播放机的比特率。如果您的播放机与Logitech Media Server的联系经过互联网或您的无线网络有堵塞的问题存在,这个功能将会提供很好的帮助。您可以选择Logitech Media Server流出到播放机的最大比特率。如果MP3歌曲原有比特率低于如下则不被转换。如果您选择不限制比特率,Logitech Media Server将不会对您的MP3文件流出到播放机前进行任何转换。其他文件类型也会以未压缩的PCM音像格式流出到播放机。 SETUP_MP3BITRATE_DESC - CS Squeezebox Server může automaticky konvertovat vaše hudební soubory do MP3 průběžně a tak přehrávat i jiné formáty než MP3. Může rovněž provést rekompresi vašich souborů MP3 pro snížení přenosové rychlosti (bitrate) dat přenášených v proudu do vašeho přehrávače. To je užitečné, pokud připojujete přehrávač k serveru přes Internet, nebo pokud máte problémy s přerušováním bezdrátové sítě. Můžete si zvolit maximální přenosovou rychlost (bitrate), jakou bude Squeezebox Server posílat datový proud do vašeho přehrávače. Skladby MP3 kódované na nižší přenosovou rychlost (bitrate), než je maximální přenosová rychlost, nebudou konvertovány. - DA Squeezebox Server kan løbende konvertere lydfilerne til mp3 sådan at du kan spille lydfiler i andre formater. Squeezebox Server kan også genkomprimere mp3-filerne til en lavere bithastighed sådan at der ikke sendes så mange data til afspilleren. Det kan være praktisk hvis du etablerer forbindelse til afspilleren over internettet eller midlertidigt har problemer med et trådløst netværk. Numre der er kodet som mp3 med en lavere bithastighed end den maksimale, bliver ikke konverteret. - DE Squeezebox Server kann zur Wiedergabe anderer Dateiformate Musikdateien automatisch in MP3 umwandeln sowie MP3-Dateien während der Wiedergabe in eine geringere Bitrate umwandeln. Das ist hilfreich, wenn Sie den Player übers Internet mit dem Server verbinden oder Probleme mit dem kabellosen Netzwerk haben. Sie können die maximale Bitrate definieren, mit der Squeezebox Server an den Player übertragen soll. MP3-Titel, die mit einer kleineren Bitrate als der maximalen Bitrate kodiert wurden, werden nicht umgewandelt. - EN Squeezebox Server can automatically convert your music files to MP3 on-the-fly to play back other formats than MP3. It can also recompress your MP3 files to lower the bitrate of the data streamed to your player. This is useful if you are connecting your player to the server across the Internet or are having intermittent problems using a wireless network. You can choose the maximum bitrate that Squeezebox Server will stream to your player. MP3 songs encoded at a bitrate lower than the maximum bitrate won't be converted. - ES Squeezebox Server puede convertir automáticamente los archivos de música a MP3 al instante para reproducir otros formatos que no sean MP3. También puede recomprimir los archivos MP3 para reducir la velocidad de bits de los datos enviados por secuencias al reproductor. Resulta útil si se conecta el reproductor al servidor a través de Internet o si se producen problemas intermitentes con una red inalámbrica. Se puede elegir la velocidad de bits máxima que Squeezebox Server usará para el envío por secuencias al reproductor. No se convertirán las canciones MP3 codificadas a una velocidad de bits inferior a la velocidad de bits máxima. - FI Squeezebox Server voi muuntaa musiikkitiedostot automaattisesti MP3-tiedostoiksi lennosta. Tämä mahdollistaa muiden kuin MP3-muotoisten tiedostojen käytön soittimessa. Squeezebox Server voi myös uudelleenpakata MP3-tiedostot soittimeen virtautettujen tiedostojen bittinopeuden laskemiseksi. Tämä on hyödyllistä, jos yhdistät soittimesi palvelimeen internetin välityksellä tai jos langattoman verkon kanssa on ajoittain ongelmia. Voit valita enimmäisbittinopeuden, jolla Squeezebox Server virtauttaa tiedostoja soittimeen. Enimmäisbittinopeutta hitaammalla bittinopeudella koodattuja MP3-tiedostoja ei muunneta. - FR Le Squeezebox Server peut encoder automatiquement et à la volée vos fichiers de musique non-MP3 au format MP3. Il peut également ré-encoder vos fichiers MP3 existants afin de réduire le débit binaire envoyé à votre platine. Ce réglage est utile lorsque vous vous connectez au serveur par Internet ou via un réseau sans fil défectueux. Vous pouvez spécifier le débit maximal envoyé par le Squeezebox Server à votre platine. Les fichiers MP3 encodés à un débit inférieur à celui maximal ne seront pas transcodés. - HE Squeezebox Server יכול להמיר את קובצי המוסיקה שלך באופן אוטומטי ל-MP3 במהלך השמעה של תבניות שאינן MP3. Squeezebox Server גם יכול לדחוס את קובצי ה-MP3 כדי לצמצם את קצב הסיביות של הנתונים המוזרמים לנגן. הגדרה זו שימושית אם אתה מחבר את הנגן ל-Squeezebox Server דרך האינטרנט או נתקל בבעיות של קיטועים בשימוש ברשת אלחוטית. באפשרותך לבחור את קצב הסיביות המרבי שבו Squeezebox Server יפעיל זרימות לנגן. שירים בתבנית MP3 שקודדו בקצב נתונים נמוך מזה המצוין להלן, לא יומרו. - IT Squeezebox Server consente di convertire automaticamente i file musicali in MP3 in modo rapido per riprodurre formati diversi da MP3. Consente inoltre di ricomprimere i file MP3 per ridurre il bitrate dei dati inviati al lettore. Questa funzione risulta utile se si connette il lettore a un server tramite Internet o se si verificano occasionali interruzioni con una rete senza fili. È possibile scegliere il bitrate massimo con cui inviare lo stream audio al lettore tramite Squeezebox Server. I brani MP3 codificati a un bitrate inferiore a quello massimo non vengono convertiti. - JA Squeezebox Serverは、自動的にあなたの音楽ファイルをMP3に変換します。MP3からさらに下のビットレートへの変換もできます。 - NL Squeezebox Server kan je muziekbestanden direct automatisch naar MP3 converteren om andere formaten dan MP3 af te spelen. Squeezebox Server kan je MP3-bestanden ook opnieuw comprimeren om gegevens met een lagere bitsnelheid naar je muzieksysteem te streamen. Dit is handig als het systeem via het internet met Squeezebox Server verbonden is, of als je af en toe problemen hebt met een draadloos netwerk. Je kunt kiezen met welke bitsnelheid Squeezebox Server maximaal naar je systeem zal streamen. MP3-liedjes die gecodeerd zijn met een lagere bitsnelheid dan de maximale bitsnelheid, worden niet geconverteerd. - NO Squeezebox Server kan automatisk konvertere musikkfiler til mp3 under avspilling, slik at du kan spille av andre formater enn mp3. Squeezebox Server kan også komprimere mp3-filene dine, for å senke bithastigheten for data som strømmes til spilleren. Dette kan være nyttig hvis du kopler spilleren til serveren over Internett, eller hvis du har periodevise problemer med et trådløst nettverk. Du kan angi maksimal bithastighet for strømmingen til spilleren fra Squeezebox Server. Mp3-filer som er kodet med en bithastighet som er lavere enn maksimumshastigheten, blir ikke konvertert. - PL Program Squeezebox Server może automatycznie przekonwertować w locie pliki muzyczne na format MP3 w celu odtworzenia formatów innych niż MP3. Program Squeezebox Server może także ponownie skompresować pliki MP3 na niższą szybkość transmisji bitów danych przesyłanych strumieniowo do odtwarzacza. Jest to przydatne w przypadku łączenia odtwarzacza z programem Squeezebox Server przez Internet lub tymczasowych problemów z siecią bezprzewodową. Możliwe jest także wybranie maksymalnej szybkości transmisji bitów danych przesyłanych strumieniowo przez program Squeezebox Server do odtwarzacza. Utwory w formacie MP3 zakodowane z szybkością transmisji bitów niższą niż podana poniżej nie zostaną przekonwertowane. - RU Squeezebox Server может автоматически преобразовывать в формат MP3 музыкальные файлы других форматов в режиме реального времени и воспроизводить их. Squeezebox Server может также повторно сжимать MP3-файлы, чтобы снизить скорость передачи данных на плеер. Это удобно при подключении плеера к Squeezebox Server через Интернет или при неустойчивой работе беспроводной сети. Можно задать максимальную скорость передачи со Squeezebox Server на плеер. MP3-файлы со скоростью передачи ниже указанного значения преобразованы не будут. - SV Squeezebox Server kan automatiskt konvertera dina musikfiler till mp3 samtidigt som de spelas upp. På så sätt kan du lyssna på musikfiler i andra format. Squeezebox Server kan också komprimera om mp3-filerna till en lägre bithastighet, vilket minskar mängden data som skickas till spelaren. Det kan vara användbart om du ansluter spelaren till servern via Internet eller om du har tillfälliga problem med anslutningen till ett trådlöst nätverk. Du kan ange en maximal bithastighet för data som Squeezebox Server överför till spelaren. Mp3-låtar som kodats med lägre bithastigheter än den maximala bithastigheten konverteras inte. - ZH_CN Squeezebox Server可以将您的非MP3音乐文件自动并即时转换成MP3格式。Squeezebox Server也可以把MP3文件重新压缩以降低流出到播放机的比特率。如果您的播放机与Squeezebox Server的联系横跨互联网或您的无线网络有堵塞的问题存在,这个功能将会提供很好的帮助。您可以选择Squeezebox Server流出到播放机的最大比特率。如果MP3歌曲原有比特率低于如下则不被转换。 + CS Logitech Media Server může automaticky konvertovat vaše hudební soubory do MP3 průběžně a tak přehrávat i jiné formáty než MP3. Může rovněž provést rekompresi vašich souborů MP3 pro snížení přenosové rychlosti (bitrate) dat přenášených v proudu do vašeho přehrávače. To je užitečné, pokud připojujete přehrávač k serveru přes Internet, nebo pokud máte problémy s přerušováním bezdrátové sítě. Můžete si zvolit maximální přenosovou rychlost (bitrate), jakou bude Logitech Media Server posílat datový proud do vašeho přehrávače. Skladby MP3 kódované na nižší přenosovou rychlost (bitrate), než je maximální přenosová rychlost, nebudou konvertovány. + DA Logitech Media Server kan løbende konvertere lydfilerne til mp3 sådan at du kan spille lydfiler i andre formater. Logitech Media Server kan også genkomprimere mp3-filerne til en lavere bithastighed sådan at der ikke sendes så mange data til afspilleren. Det kan være praktisk hvis du etablerer forbindelse til afspilleren over internettet eller midlertidigt har problemer med et trådløst netværk. Numre der er kodet som mp3 med en lavere bithastighed end den maksimale, bliver ikke konverteret. + DE Logitech Media Server kann zur Wiedergabe anderer Dateiformate Musikdateien automatisch in MP3 umwandeln sowie MP3-Dateien während der Wiedergabe in eine geringere Bitrate umwandeln. Das ist hilfreich, wenn Sie den Player übers Internet mit dem Server verbinden oder Probleme mit dem kabellosen Netzwerk haben. Sie können die maximale Bitrate definieren, mit der Logitech Media Server an den Player übertragen soll. MP3-Titel, die mit einer kleineren Bitrate als der maximalen Bitrate kodiert wurden, werden nicht umgewandelt. + EN Logitech Media Server can automatically convert your music files to MP3 on-the-fly to play back other formats than MP3. It can also recompress your MP3 files to lower the bitrate of the data streamed to your player. This is useful if you are connecting your player to the server across the Internet or are having intermittent problems using a wireless network. You can choose the maximum bitrate that Logitech Media Server will stream to your player. MP3 songs encoded at a bitrate lower than the maximum bitrate won't be converted. + ES Logitech Media Server puede convertir automáticamente los archivos de música a MP3 al instante para reproducir otros formatos que no sean MP3. También puede recomprimir los archivos MP3 para reducir la velocidad de bits de los datos enviados por secuencias al reproductor. Resulta útil si se conecta el reproductor al servidor a través de Internet o si se producen problemas intermitentes con una red inalámbrica. Se puede elegir la velocidad de bits máxima que Logitech Media Server usará para el envío por secuencias al reproductor. No se convertirán las canciones MP3 codificadas a una velocidad de bits inferior a la velocidad de bits máxima. + FI Logitech Media Server voi muuntaa musiikkitiedostot automaattisesti MP3-tiedostoiksi lennosta. Tämä mahdollistaa muiden kuin MP3-muotoisten tiedostojen käytön soittimessa. Logitech Media Server voi myös uudelleenpakata MP3-tiedostot soittimeen virtautettujen tiedostojen bittinopeuden laskemiseksi. Tämä on hyödyllistä, jos yhdistät soittimesi palvelimeen internetin välityksellä tai jos langattoman verkon kanssa on ajoittain ongelmia. Voit valita enimmäisbittinopeuden, jolla Logitech Media Server virtauttaa tiedostoja soittimeen. Enimmäisbittinopeutta hitaammalla bittinopeudella koodattuja MP3-tiedostoja ei muunneta. + FR Le Logitech Media Server peut encoder automatiquement et à la volée vos fichiers de musique non-MP3 au format MP3. Il peut également ré-encoder vos fichiers MP3 existants afin de réduire le débit binaire envoyé à votre platine. Ce réglage est utile lorsque vous vous connectez au serveur par Internet ou via un réseau sans fil défectueux. Vous pouvez spécifier le débit maximal envoyé par le Logitech Media Server à votre platine. Les fichiers MP3 encodés à un débit inférieur à celui maximal ne seront pas transcodés. + HE Logitech Media Server יכול להמיר את קובצי המוסיקה שלך באופן אוטומטי ל-MP3 במהלך השמעה של תבניות שאינן MP3. Logitech Media Server גם יכול לדחוס את קובצי ה-MP3 כדי לצמצם את קצב הסיביות של הנתונים המוזרמים לנגן. הגדרה זו שימושית אם אתה מחבר את הנגן ל-Logitech Media Server דרך האינטרנט או נתקל בבעיות של קיטועים בשימוש ברשת אלחוטית. באפשרותך לבחור את קצב הסיביות המרבי שבו Logitech Media Server יפעיל זרימות לנגן. שירים בתבנית MP3 שקודדו בקצב נתונים נמוך מזה המצוין להלן, לא יומרו. + IT Logitech Media Server consente di convertire automaticamente i file musicali in MP3 in modo rapido per riprodurre formati diversi da MP3. Consente inoltre di ricomprimere i file MP3 per ridurre il bitrate dei dati inviati al lettore. Questa funzione risulta utile se si connette il lettore a un server tramite Internet o se si verificano occasionali interruzioni con una rete senza fili. È possibile scegliere il bitrate massimo con cui inviare lo stream audio al lettore tramite Logitech Media Server. I brani MP3 codificati a un bitrate inferiore a quello massimo non vengono convertiti. + JA Logitech Media Serverは、自動的にあなたの音楽ファイルをMP3に変換します。MP3からさらに下のビットレートへの変換もできます。 + NL Logitech Media Server kan je muziekbestanden direct automatisch naar MP3 converteren om andere formaten dan MP3 af te spelen. Logitech Media Server kan je MP3-bestanden ook opnieuw comprimeren om gegevens met een lagere bitsnelheid naar je muzieksysteem te streamen. Dit is handig als het systeem via het internet met Logitech Media Server verbonden is, of als je af en toe problemen hebt met een draadloos netwerk. Je kunt kiezen met welke bitsnelheid Logitech Media Server maximaal naar je systeem zal streamen. MP3-liedjes die gecodeerd zijn met een lagere bitsnelheid dan de maximale bitsnelheid, worden niet geconverteerd. + NO Logitech Media Server kan automatisk konvertere musikkfiler til mp3 under avspilling, slik at du kan spille av andre formater enn mp3. Logitech Media Server kan også komprimere mp3-filene dine, for å senke bithastigheten for data som strømmes til spilleren. Dette kan være nyttig hvis du kopler spilleren til serveren over Internett, eller hvis du har periodevise problemer med et trådløst nettverk. Du kan angi maksimal bithastighet for strømmingen til spilleren fra Logitech Media Server. Mp3-filer som er kodet med en bithastighet som er lavere enn maksimumshastigheten, blir ikke konvertert. + PL Program Logitech Media Server może automatycznie przekonwertować w locie pliki muzyczne na format MP3 w celu odtworzenia formatów innych niż MP3. Program Logitech Media Server może także ponownie skompresować pliki MP3 na niższą szybkość transmisji bitów danych przesyłanych strumieniowo do odtwarzacza. Jest to przydatne w przypadku łączenia odtwarzacza z programem Logitech Media Server przez Internet lub tymczasowych problemów z siecią bezprzewodową. Możliwe jest także wybranie maksymalnej szybkości transmisji bitów danych przesyłanych strumieniowo przez program Logitech Media Server do odtwarzacza. Utwory w formacie MP3 zakodowane z szybkością transmisji bitów niższą niż podana poniżej nie zostaną przekonwertowane. + RU Logitech Media Server может автоматически преобразовывать в формат MP3 музыкальные файлы других форматов в режиме реального времени и воспроизводить их. Logitech Media Server может также повторно сжимать MP3-файлы, чтобы снизить скорость передачи данных на плеер. Это удобно при подключении плеера к Logitech Media Server через Интернет или при неустойчивой работе беспроводной сети. Можно задать максимальную скорость передачи со Logitech Media Server на плеер. MP3-файлы со скоростью передачи ниже указанного значения преобразованы не будут. + SV Logitech Media Server kan automatiskt konvertera dina musikfiler till mp3 samtidigt som de spelas upp. På så sätt kan du lyssna på musikfiler i andra format. Logitech Media Server kan också komprimera om mp3-filerna till en lägre bithastighet, vilket minskar mängden data som skickas till spelaren. Det kan vara användbart om du ansluter spelaren till servern via Internet eller om du har tillfälliga problem med anslutningen till ett trådlöst nätverk. Du kan ange en maximal bithastighet för data som Logitech Media Server överför till spelaren. Mp3-låtar som kodats med lägre bithastigheter än den maximala bithastigheten konverteras inte. + ZH_CN Logitech Media Server可以将您的非MP3音乐文件自动并即时转换成MP3格式。Logitech Media Server也可以把MP3文件重新压缩以降低流出到播放机的比特率。如果您的播放机与Logitech Media Server的联系横跨互联网或您的无线网络有堵塞的问题存在,这个功能将会提供很好的帮助。您可以选择Logitech Media Server流出到播放机的最大比特率。如果MP3歌曲原有比特率低于如下则不被转换。 CONVERTED_TO CS Zkonvertováno do @@ -5248,22 +5249,22 @@ CONVERTED_TO ZH_CN 已转换成 SETUP_LAME_NOT_FOUND - CS (Poznámka: Zřejmě nemáte nainstalovaný LAME. Squeezebox Server potřebuje nainstalovaný kodér LAME MP3 ve vašem systému, aby mohl převádět hudbu do MP3. Více o LAME najdete zde.) - DA Bemærk: LAME-codecet er tilsyneladende ikke installeret. Squeezebox Server skal bruge LAME til at konvertere lydfiler til mp3-format. Du kan læse mere om LAME her). - DE Hinweis: LAME scheint nicht installiert zu sein. Squeezebox Server benötigt den MP3-Kodierer LAME zum Durchführen der MP3-Konvertierung. Weitere Informationen über LAME finden Sie hier. - EN (Note: You do not appear to have LAME installed. Squeezebox Server will need the LAME MP3 encoder installed on your system to do conversion to MP3. You can find out more about LAME here.) - ES Nota: Parece que LAME no está instalado. Squeezebox Server necesita que el codificador MP3 LAME esté instalado en el sistema para la conversión a MP3. Encontrará más información sobre LAME aquí. - FI (Huomaa: LAME ei ole asennettuna. Squeezebox Server vaatii, että LAME MP3 -kooderi on asennettuna tietokoneeseen, jotta muunnos MP3:een voidaan suorittaa. Lisätietoa LAME-kooderista on täällä.) - FR Remarque: LAME ne semble pas être installé. Le Squeezebox Server nécessite l'installation de LAME pour effectuer la conversion au format MP3. Cliquez ici pour en savoir plus sur LAME. - HE (שים לב: נראה שאין ברשותך LAME מותקן. לביצוע המרות ל-MP3,‏ Squeezebox Server זקוק למקודד LAME MP3 מותקן. באפשרותך למצוא מידע נוסף אודות LAME כאן.) - IT Nota: LAME non è installato. Per eseguire la conversione al formato MP3 in Squeezebox Server, è necessario che il codificatore MP3 LAME sia installato. Ulteriori informazioni su LAME sono disponibili qui. - JA (注意: LAMEがインストールされていないようです。MP3に変換するためにはSqueezebox ServerはLAMEをインストールする必要があります。LAMEについてはここをクリックして下さい。) - NL (Let op: Het lijkt erop dat LAME niet geïnstalleerd is. Squeezebox Server heeft het MP3-codeerprogramma LAME nodig voor conversie naar MP3. Je kunt hier meer informatie over LAME vinden.) - NO (Merk: Det ser ikke ut til at LAME er installert. Squeezebox Server trenger mp3-koderen LAME for å konvertere til mp3. Du kan lese mer om LAME her.) - PL (Uwaga: Koder LAME nie jest zainstalowany. Program Squeezebox Server wymaga zainstalowania w systemie kodera LAME MP3 w celu przeprowadzenia konwersji do formatu MP3. Więcej informacji na temat kodera LAME można znaleźć tutaj.) - RU (Примечание. Кодировщик LAME не установлен. Чтобы Squeezebox Server мог выполнить преобразование в MP3, в системе должен быть установлен кодировщик LAME MP3. Дополнительные сведения о кодировщике LAME см. здесь.) - SV (Obs! Det verkar inte som om du har installerat LAME. Mp3-kodaren LAME krävs för att Squeezebox Server ska kunna konvertera filer till mp3-format. Mer information om LAME finns påhere.) - ZH_CN (注意: 您似乎没有在此计算机内安装LAME。Squeezebox Server需要用到您计算机的LAME MP3编码器进行MP3格式转换。您能从这里查阅更多有关LAME的资料。) + CS (Poznámka: Zřejmě nemáte nainstalovaný LAME. Logitech Media Server potřebuje nainstalovaný kodér LAME MP3 ve vašem systému, aby mohl převádět hudbu do MP3. Více o LAME najdete zde.) + DA Bemærk: LAME-codecet er tilsyneladende ikke installeret. Logitech Media Server skal bruge LAME til at konvertere lydfiler til mp3-format. Du kan læse mere om LAME her). + DE Hinweis: LAME scheint nicht installiert zu sein. Logitech Media Server benötigt den MP3-Kodierer LAME zum Durchführen der MP3-Konvertierung. Weitere Informationen über LAME finden Sie hier. + EN (Note: You do not appear to have LAME installed. Logitech Media Server will need the LAME MP3 encoder installed on your system to do conversion to MP3. You can find out more about LAME here.) + ES Nota: Parece que LAME no está instalado. Logitech Media Server necesita que el codificador MP3 LAME esté instalado en el sistema para la conversión a MP3. Encontrará más información sobre LAME aquí. + FI (Huomaa: LAME ei ole asennettuna. Logitech Media Server vaatii, että LAME MP3 -kooderi on asennettuna tietokoneeseen, jotta muunnos MP3:een voidaan suorittaa. Lisätietoa LAME-kooderista on täällä.) + FR Remarque: LAME ne semble pas être installé. Le Logitech Media Server nécessite l'installation de LAME pour effectuer la conversion au format MP3. Cliquez ici pour en savoir plus sur LAME. + HE (שים לב: נראה שאין ברשותך LAME מותקן. לביצוע המרות ל-MP3,‏ Logitech Media Server זקוק למקודד LAME MP3 מותקן. באפשרותך למצוא מידע נוסף אודות LAME כאן.) + IT Nota: LAME non è installato. Per eseguire la conversione al formato MP3 in Logitech Media Server, è necessario che il codificatore MP3 LAME sia installato. Ulteriori informazioni su LAME sono disponibili qui. + JA (注意: LAMEがインストールされていないようです。MP3に変換するためにはLogitech Media ServerはLAMEをインストールする必要があります。LAMEについてはここをクリックして下さい。) + NL (Let op: Het lijkt erop dat LAME niet geïnstalleerd is. Logitech Media Server heeft het MP3-codeerprogramma LAME nodig voor conversie naar MP3. Je kunt hier meer informatie over LAME vinden.) + NO (Merk: Det ser ikke ut til at LAME er installert. Logitech Media Server trenger mp3-koderen LAME for å konvertere til mp3. Du kan lese mer om LAME her.) + PL (Uwaga: Koder LAME nie jest zainstalowany. Program Logitech Media Server wymaga zainstalowania w systemie kodera LAME MP3 w celu przeprowadzenia konwersji do formatu MP3. Więcej informacji na temat kodera LAME można znaleźć tutaj.) + RU (Примечание. Кодировщик LAME не установлен. Чтобы Logitech Media Server мог выполнить преобразование в MP3, в системе должен быть установлен кодировщик LAME MP3. Дополнительные сведения о кодировщике LAME см. здесь.) + SV (Obs! Det verkar inte som om du har installerat LAME. Mp3-kodaren LAME krävs för att Logitech Media Server ska kunna konvertera filer till mp3-format. Mer information om LAME finns påhere.) + ZH_CN (注意: 您似乎没有在此计算机内安装LAME。Logitech Media Server需要用到您计算机的LAME MP3编码器进行MP3格式转换。您能从这里查阅更多有关LAME的资料。) SETUP_LAME_FOUND CS Kodér LAME je na vašem systému zřejmě správně instalován. @@ -5335,21 +5336,21 @@ SETUP_LAMEQUALITY ZH_CN LAME质量水平 SETUP_LAMEQUALITY_DESC - CS Kodér LAME MP3 lze použít pro konverzi vaší hudby do formátu MP3 vhodného pro datový proud. Můžete upravit nastavení kvality pro LAME v rozsahu od 0 do 9. 9 je výchozí nastavení, které zní velmi dobře při vysokých přenosových rychlostech a spotřebovává nejméně výpočetního výkonu. 0 je nejvyšší kvalita, ale může zpomalovat váš počítač. Některé počítače, na nichž běží Squeezebox Server, nemusí být schopny při vyšším nastavení kvality provádět konverzi dostatečně rychle. - DA LAME mp3-indkoderen kan bruges til at konvertere dine musikfiler til mp3-format sådan at de kan streames. Du kan indstille lydkvaliteten i LAME mellem 1 og 9. 9 er standardindstillingen og giver en god lydkvalitet med en høj bithastighed, og den kræver de færreste systemresurser. 0 er den højeste kvalitet, men det kan få computeren til at køre langsomt. Nogle computere med Squeezebox Server kan muligvis ikke konvertere hurtigt nok med en højere kvalitetsindstilling. - DE Sie können den MP3-Kodierer LAME zum Konvertieren von Musikdateien in MP3 verwenden, damit diese übertragen werden können. Die LAME-Qualität ist ein Wert zwischen 0 und 9, wobei 9 die Standardeinstellung ist, die sehr gut bei hohen Bitraten klingt und die geringste Rechenleistung benötigt. 0 ist die höchste Qualitätsstufe, die jedoch zu Leistungseinbußen führen kann. Manche Rechner mit Squeezebox Server können die Konvertierung auf höheren Qualitätsstufen eventuell nicht schnell genug durchführen. - EN The LAME MP3 encoder may be used to convert your music to MP3 format for streaming. You can adjust the quality setting for LAME in the range 0 to 9. 9 is the default setting, which sounds very good at high bit rates and and uses the least amount of computing power. 0 is the highest quality, but may slow your computer down. Some computers running Squeezebox Server may not be able to convert fast enough with higher quality settings. - ES Se puede usar el codificador LAME MP3 para convertir música al formato MP3 para envío por secuencias. La configuración de calidad de LAME se puede ajustar entre 0 y 9. 9 es la opción predeterminada, que ofrece muy buen sonido a velocidades de bits altas y que usa la menor cantidad de recursos del equipo. 0 es la calidad mas alta, pero puede afectar al rendimiento del equipo. Es posible que algunos equipos que ejecuten Squeezebox Server no sean capaces de convertir con la suficiente rapidez con niveles de calidad superiores. - FI LAME-MP3-kooderilla musiikkitiedostot voidaan muuntaa MP3-muotoon virtauttamista varten. Laatu voidaan valita LAME-kooderissa asteikolla 0-9. Oletusarvo on 9. Oletuslaatu kuulostaa hyvältä korkeilla bittinopeuksilla ja vaatii pienimmän tietojenkäsittelytehon. Korkein arvo on 0, mutta se saattaa hidastaa tietokoneen toimintaa. Jotkin tietokoneet, joissa on käytössä Squeezebox Server, eivät välttämättä pysty muuntamaan tiedostomuotoa riittävän nopeasti korkeilla laatuasetuksilla. - FR Vous pouvez convertir vos fichiers audio au format MP3 pour la diffusion à distance à l'aide de LAME. Vous pouvez ajuster le niveau de qualité de LAME de 0 à 9. La valeur par défaut est 9, qui permet d'obtenir de bons résultats avec des taux d'encodage élevés et économise les ressources système au maximum. La valeur 0 permet un niveau de qualité optimal mais risque de ralentir l'ordinateur. Les ordinateurs les moins performants exécutant le Squeezebox Server risquent de ne pas pouvoir utiliser les réglages de qualité optimale. - HE ניתן להשתמש במקודד LAME MP3 להמרת מוסיקה לתבנית MP3 לצורך הפעלה בזרימה. באפשרותך לכוונן את הגדרת האיכות עבור LAME בטווח שבין 0-9‏. הגדרת ברירת המחדל היא 9, לשמע מצוין בקצבי סיביות גבוהים ולשימוש המועט ביותר בהספק מיחשוב. 0 היא ההגדרה הגבוהה ביותר, אך עלולה להאט את מחשבך. ייתכן שמחשבים מסוימים שפועל בהם Squeezebox Server לא יוכלו לבצע המרות במהירות מספקת עם הגדרות האיכות הגבוהות יותר. - IT Il codificatore LAME MP3 può essere utilizzato per convertire i file musicali nel formato MP3 per lo streaming. È possibile impostare il livello di qualità su un valore compreso tra 0 e 9. L'impostazione predefinita è 9; consente di ottenere un suono di ottima qualità a una velocità in bit elevata con il minimo utilizzo delle risorse del processore. 0 rappresenta il livello massimo di qualità ma può determinare rallentamenti del computer. In alcuni computer in cui si esegue Squeezebox Server la conversione potrebbe non risultare sufficientemente rapida se sono impostati i livelli di qualità più elevati. - NL Met behulp van het MP3-codeerprogramma LAME kun je muziek voor streaming naar MP3-formaat converteren. Je kunt de kwaliteit voor LAME instellen op een waarde tussen 0 en 9. 9 is de standaardinstelling die heel goed klinkt bij hoge bitsnelheden en de minste rekenkracht gebruikt. 0 is de hoogste kwaliteit, maar kan je computer langzamer maken. Sommige computers waarop Squeezebox Server draait, zijn misschien niet krachtig genoeg om met hogere kwaliteitsinstellingen te kunnen converteren. - NO Med mp3-koderen LAME kan musikkfiler konverteres til mp3-format og strømmes. Du kan justere kvaliteten for LAME fra 0 til 9. 9 er standardinnstilling. Dette gir svært god lyd ved høy bithastighet, og bruker minst kapasitet. 0 er høyeste kvalitet, men den kan føre til at datamaskinen går tregere. Enkelte datamaskiner som kjører Squeezebox Server kan ha problemer med å konvertere filer raskt nok hvis kvalitetsinnstillingen er for høy. - PL W celu przekonwertowania muzyki na format MP3 i przesyłania strumieniowego można użyć kodera LAME MP3. Jakość kodera LAME można ustawić w zakresie od 0 do 9. Wartość 9 to ustawienie domyślne zapewniające dobre brzmienie przy wysokiej szybkości transmisji bitów i wykorzystujące niewielką wydajność obliczeniową. Wartość 0 zapewnia najwyższą jakość, ale może spowolnić komputer. Niektóre komputery z programem Squeezebox Server mogą nie umożliwiać wystarczająco szybkiej konwersji przy ustawieniu wyższej jakości. - RU С помощью кодировщика LAME MP3 можно преобразовать музыку в формат MP3 для потоковой передачи. Можно настроить качество для LAME, выбрав значение от 0 до 9. 9 — это значение по умолчанию, которое обеспечивает очень хорошее звучание при высоких скоростях передачи и требует минимальных вычислительных ресурсов. 0 — это значение обеспечивает высокое качество, но может замедлить работу компьютера. Некоторые компьютеры, на которых выполняется Squeezebox Server, могут недостаточно быстро преобразовывать музыку при высоких значениях настройки качества. - SV Mp3-omkodaren LAME kan användas för konvertering av musik till mp3-format innan den strömmas. Du kan ändra kvalitetsinställningen för LAME inom intervallet 0–9. Standardinställningen är 9, vilket ger bra ljud vid höga bithastigheter och kräver minsta möjliga datorkraft. Värdet 0 ger högsta möjliga kvalitet, men kan göra att datorn arbetar långsamt. Vissa datorer där Squeezebox Server körs kanske inte klarar att konvertera tillräckligt snabbt vid högre kvalitetsinställningar. - ZH_CN LAME MP3编码器可将您的音乐转换成MP3格式流出。您能在0至9的设置范围内调节LAME MP3编码器的输出质量。缺省值为5的设置以高比特率编码的音效会相當的好,同时计算量也較小。0是最高质量,但其高计算量可能对计算机的性能表现造成负面影响。有一些运行Squeezebox Server的计算机也许不足以迅速的应付更加优质的LAME设置。 + CS Kodér LAME MP3 lze použít pro konverzi vaší hudby do formátu MP3 vhodného pro datový proud. Můžete upravit nastavení kvality pro LAME v rozsahu od 0 do 9. 9 je výchozí nastavení, které zní velmi dobře při vysokých přenosových rychlostech a spotřebovává nejméně výpočetního výkonu. 0 je nejvyšší kvalita, ale může zpomalovat váš počítač. Některé počítače, na nichž běží Logitech Media Server, nemusí být schopny při vyšším nastavení kvality provádět konverzi dostatečně rychle. + DA LAME mp3-indkoderen kan bruges til at konvertere dine musikfiler til mp3-format sådan at de kan streames. Du kan indstille lydkvaliteten i LAME mellem 1 og 9. 9 er standardindstillingen og giver en god lydkvalitet med en høj bithastighed, og den kræver de færreste systemresurser. 0 er den højeste kvalitet, men det kan få computeren til at køre langsomt. Nogle computere med Logitech Media Server kan muligvis ikke konvertere hurtigt nok med en højere kvalitetsindstilling. + DE Sie können den MP3-Kodierer LAME zum Konvertieren von Musikdateien in MP3 verwenden, damit diese übertragen werden können. Die LAME-Qualität ist ein Wert zwischen 0 und 9, wobei 9 die Standardeinstellung ist, die sehr gut bei hohen Bitraten klingt und die geringste Rechenleistung benötigt. 0 ist die höchste Qualitätsstufe, die jedoch zu Leistungseinbußen führen kann. Manche Rechner mit Logitech Media Server können die Konvertierung auf höheren Qualitätsstufen eventuell nicht schnell genug durchführen. + EN The LAME MP3 encoder may be used to convert your music to MP3 format for streaming. You can adjust the quality setting for LAME in the range 0 to 9. 9 is the default setting, which sounds very good at high bit rates and and uses the least amount of computing power. 0 is the highest quality, but may slow your computer down. Some computers running Logitech Media Server may not be able to convert fast enough with higher quality settings. + ES Se puede usar el codificador LAME MP3 para convertir música al formato MP3 para envío por secuencias. La configuración de calidad de LAME se puede ajustar entre 0 y 9. 9 es la opción predeterminada, que ofrece muy buen sonido a velocidades de bits altas y que usa la menor cantidad de recursos del equipo. 0 es la calidad mas alta, pero puede afectar al rendimiento del equipo. Es posible que algunos equipos que ejecuten Logitech Media Server no sean capaces de convertir con la suficiente rapidez con niveles de calidad superiores. + FI LAME-MP3-kooderilla musiikkitiedostot voidaan muuntaa MP3-muotoon virtauttamista varten. Laatu voidaan valita LAME-kooderissa asteikolla 0-9. Oletusarvo on 9. Oletuslaatu kuulostaa hyvältä korkeilla bittinopeuksilla ja vaatii pienimmän tietojenkäsittelytehon. Korkein arvo on 0, mutta se saattaa hidastaa tietokoneen toimintaa. Jotkin tietokoneet, joissa on käytössä Logitech Media Server, eivät välttämättä pysty muuntamaan tiedostomuotoa riittävän nopeasti korkeilla laatuasetuksilla. + FR Vous pouvez convertir vos fichiers audio au format MP3 pour la diffusion à distance à l'aide de LAME. Vous pouvez ajuster le niveau de qualité de LAME de 0 à 9. La valeur par défaut est 9, qui permet d'obtenir de bons résultats avec des taux d'encodage élevés et économise les ressources système au maximum. La valeur 0 permet un niveau de qualité optimal mais risque de ralentir l'ordinateur. Les ordinateurs les moins performants exécutant le Logitech Media Server risquent de ne pas pouvoir utiliser les réglages de qualité optimale. + HE ניתן להשתמש במקודד LAME MP3 להמרת מוסיקה לתבנית MP3 לצורך הפעלה בזרימה. באפשרותך לכוונן את הגדרת האיכות עבור LAME בטווח שבין 0-9‏. הגדרת ברירת המחדל היא 9, לשמע מצוין בקצבי סיביות גבוהים ולשימוש המועט ביותר בהספק מיחשוב. 0 היא ההגדרה הגבוהה ביותר, אך עלולה להאט את מחשבך. ייתכן שמחשבים מסוימים שפועל בהם Logitech Media Server לא יוכלו לבצע המרות במהירות מספקת עם הגדרות האיכות הגבוהות יותר. + IT Il codificatore LAME MP3 può essere utilizzato per convertire i file musicali nel formato MP3 per lo streaming. È possibile impostare il livello di qualità su un valore compreso tra 0 e 9. L'impostazione predefinita è 9; consente di ottenere un suono di ottima qualità a una velocità in bit elevata con il minimo utilizzo delle risorse del processore. 0 rappresenta il livello massimo di qualità ma può determinare rallentamenti del computer. In alcuni computer in cui si esegue Logitech Media Server la conversione potrebbe non risultare sufficientemente rapida se sono impostati i livelli di qualità più elevati. + NL Met behulp van het MP3-codeerprogramma LAME kun je muziek voor streaming naar MP3-formaat converteren. Je kunt de kwaliteit voor LAME instellen op een waarde tussen 0 en 9. 9 is de standaardinstelling die heel goed klinkt bij hoge bitsnelheden en de minste rekenkracht gebruikt. 0 is de hoogste kwaliteit, maar kan je computer langzamer maken. Sommige computers waarop Logitech Media Server draait, zijn misschien niet krachtig genoeg om met hogere kwaliteitsinstellingen te kunnen converteren. + NO Med mp3-koderen LAME kan musikkfiler konverteres til mp3-format og strømmes. Du kan justere kvaliteten for LAME fra 0 til 9. 9 er standardinnstilling. Dette gir svært god lyd ved høy bithastighet, og bruker minst kapasitet. 0 er høyeste kvalitet, men den kan føre til at datamaskinen går tregere. Enkelte datamaskiner som kjører Logitech Media Server kan ha problemer med å konvertere filer raskt nok hvis kvalitetsinnstillingen er for høy. + PL W celu przekonwertowania muzyki na format MP3 i przesyłania strumieniowego można użyć kodera LAME MP3. Jakość kodera LAME można ustawić w zakresie od 0 do 9. Wartość 9 to ustawienie domyślne zapewniające dobre brzmienie przy wysokiej szybkości transmisji bitów i wykorzystujące niewielką wydajność obliczeniową. Wartość 0 zapewnia najwyższą jakość, ale może spowolnić komputer. Niektóre komputery z programem Logitech Media Server mogą nie umożliwiać wystarczająco szybkiej konwersji przy ustawieniu wyższej jakości. + RU С помощью кодировщика LAME MP3 можно преобразовать музыку в формат MP3 для потоковой передачи. Можно настроить качество для LAME, выбрав значение от 0 до 9. 9 — это значение по умолчанию, которое обеспечивает очень хорошее звучание при высоких скоростях передачи и требует минимальных вычислительных ресурсов. 0 — это значение обеспечивает высокое качество, но может замедлить работу компьютера. Некоторые компьютеры, на которых выполняется Logitech Media Server, могут недостаточно быстро преобразовывать музыку при высоких значениях настройки качества. + SV Mp3-omkodaren LAME kan användas för konvertering av musik till mp3-format innan den strömmas. Du kan ändra kvalitetsinställningen för LAME inom intervallet 0–9. Standardinställningen är 9, vilket ger bra ljud vid höga bithastigheter och kräver minsta möjliga datorkraft. Värdet 0 ger högsta möjliga kvalitet, men kan göra att datorn arbetar långsamt. Vissa datorer där Logitech Media Server körs kanske inte klarar att konvertera tillräckligt snabbt vid högre kvalitetsinställningar. + ZH_CN LAME MP3编码器可将您的音乐转换成MP3格式流出。您能在0至9的设置范围内调节LAME MP3编码器的输出质量。缺省值为5的设置以高比特率编码的音效会相當的好,同时计算量也較小。0是最高质量,但其高计算量可能对计算机的性能表现造成负面影响。有一些运行Logitech Media Server的计算机也许不足以迅速的应付更加优质的LAME设置。 SETUP_MP3SILENCEPRELUDE CS Čas spuštění audio @@ -5554,20 +5555,20 @@ SETUP_MP3STREAMINGMETHOD SV Mp3-strömningsmetod SETUP_MP3STREAMINGMETHOD_DESC - CS Při přehrávání MP3 Internet proudu, může být přehrávání datových proudů provedeno jedním ze dvou způsobů. při Direct Streaming přehrávač provede přímé spojení se serverem přehrávání audio proudů a tím mírně sníží zatížení Squeeze Center a umožní přehrávání proudu i po ztrátě spojení Squeeze Center. Proxy Streaming způsobí, že Squeezebox Server zajistí spojení a přehraje audio prostřdnictvím přehrávače. Direct Streaming je výchozí nastavení, ale jestliže budete mít potíže s s MP3 proudy, zkuste změnit nastavení na Proxy Streaming. Pamatujte na to, že pokud jsou s MP3 proudem synchronizovány dva a více přehrávačů, použije se vždy Proxy Streaming k omezení použití širokopásmového přenosu. - DA Når der afspilles en mp3-stream fra internettet, kan det gøres på to måder. Ved direkte streaming etableres der en direkte forbindelse mellem afspilleren og serveren der streames fra. Det reducerer belastningen af Squeezebox Server en smule og afspilningen fortsætter selvom forbindelsen til Squeezebox Server bliver afbrudt. Ved streaming via en proxy vil Squeezebox Server håndtere forbindelsen og sende lyden videre til afspilleren. Direkte streaming er standardmetoden, men hvis du har problemer med mp3-streams, kan du ændre indstillingen til Streaming via proxy. Bemærk at hvis to eller flere afspillere er synkroniseret til en mp3-stream, bliver proxymetoden altid anvendt for at begrænse brugen af båndbredde. - DE Zur Wiedergabe eines MP3-Internet-Streams kann das Streaming auf zwei verschiedene Arten durchgeführt werden. Beim direkten Streaming erstellt der Player eine direkte Verbindung mit dem Audio-Streaming-Server, wodurch die Belastung von Squeezebox Server verringert wird und der Stream auch fortgesetzt werden kann, wenn die Verbindung zu Squeezebox Server unterbrochen wird. Beim Streaming über einen Proxy-Server verwaltet Squeezebox Server die Verbindung und leitet die Musik an den Player weiter. Standardmäßig wird das direkte Streaming verwendet, aber wenn Probleme mit MP3-Streams auftreten, können Sie die andere Methode versuchen. Hinweis: Wenn zwei oder mehre Player synchron auf einem MP3-Stream zugreifen, wird immer das Streaming über einen Proxy-Server verwendet, um die Bandbreitennutzung zu reduzieren. - EN When playing an MP3 Internet stream, the streaming can be done in one of two ways. Direct Streaming causes the player to make a direct connection to the audio streaming server, reducing the load on Squeezebox Server slightly and allowing the stream to continue playing if the Squeezebox Server connection is lost. Proxied Streaming causes Squeezebox Server to handle the connection, passing the audio through to the player. Direct Streaming is the default, but if you experience problems with MP3 streams, try changing this setting to Proxied Streaming. Note that if two or more players are synchronized to an MP3 stream, proxied streaming is always used to reduce bandwidth usage. - ES Al reproducir secuencias MP3 de Internet, el envío por secuencias puede realizarse de dos maneras. Secuencias directas hace que el reproductor establezca una conexión directa con el servidor de secuencias de audio. Esto reduce ligeramente la carga en Squeezebox Server y permite que las secuencias se sigan reproduciendo si se pierde la conexión con Squeezebox Server. Secuencias por proxy hace que Squeezebox Server gestione la conexión y que el audio pase a través del reproductor. Secuencias directas es la opción predeterminada pero, si tiene problemas con secuencias MP3, cambie a Secuencias por proxy. Tenga en cuenta que si hay dos o más reproductores sincronizados con una secuencia MP3, se usa siempre Secuencias por proxy para reducir el uso de ancho de banda. - FI Kun toistetaan MP3 internet -virtaa, virtautus voidaan suorittaa kahdella tavalla. Jos valitaan suora virtautus, soitin muodostaa suoran yhteyden äänen virtautuspalvelimeen. Tämä vähentää Squeezebox Serverin kuormitusta lievästi. Virran toistoa voidaan myös jatkaa, jos Squeezebox Serverin yhteys katkeaa. Jos valitaan virtautus välityspalvelimen kautta, Squeezebox Server huolehtii yhteydestä ja välittää äänen soittimeen. Oletus on suora virtautus, mutta jos MP3-virtojen kanssa esiintyy ongelmia, kokeile vaihtaa välityspalvelimen kautta virtautukseen. Huomaa, että jos vähintään kaksi palvelinta on synkronoitu MP3-virtaan, käytetään aina välityspalvelimen kautta virtautusta, koska se vähentää kaistanleveyden käyttöä. - FR Il existe deux manières de diffuser un flux MP3 sur Internet. La diffusion directe permet à la platine de se connecter directement au serveur de diffusion audio, réduisant ainsi la charge sur le Squeezebox Server et permettant de poursuivre la lecture du flux en cas de perte de la connexion. La diffusion par proxy permet au Squeezebox Server de gérer la connexion et de transmettre le flux audio vers la platine. La diffusion directe est l'option sélectionnée par défaut. Si vous rencontrez des problèmes lors de la lecture des flux MP3, sélectionnez l'option de diffusion par proxy. Notez que si plusieurs platines sont synchronisées pour utiliser un flux MP3, c'est la diffusion proxy qui est utilisée afin de réduire l'utilisation de bande passante. - HE בעת הפעלה של זרימת אינטרנט בתבנית MP3, ניתן להפעיל את הזרימה באחת משתי דרכים. זרימה ישירה גורמת לנגן ליצור חיבור ישיר לשרת הזרימה של השמע, לצמצום קל של העומס על Squeezebox Server וכדי לאפשר לזרימה להימשך במקרה של אובדן החיבור של Squeezebox Server. זרימה ב-Proxy גורמת ל-Squeezebox Server לטפל בחיבור, להעברת השמע לנגן. זרימה ישירה היא ברירת המחדל, אך אם אתה נתקל בבעיות עם זרימות של MP3, נסה לשנות את ההגדרה לזרימה ב-Proxy. שים לב שאם לפחות שני נגנים מסונכרנים לזרימה מסוג MP3, תמיד נעשה שימוש בזרימה ב-Proxy לצמצום השימוש ברוחב הפס. - IT Quando si riproduce uno stream Internet MP3 si possono utilizzare due metodi. Con il metodo dello streaming diretto il riproduttore si collega direttamente al server di streaming audio. Ciò consente di ridurre leggermente il carico di Squeezebox Server e di proseguire la riproduzione dello stream anche nel caso in cui la connessione con Squeezebox Server venga persa. Con il metodo dello streaming tramite proxy la gestione della connessione viene effettuata da Squeezebox Server, il quale passa l'audio al riproduttore. Lo streaming diretto è il metodo predefinito. Se tuttavia si riscontrassero problemi con gli stream MP3, provare a utilizzare il metodo dello streaming tramite proxy. Si noti che se due o più lettori sono sincronizzati su uno stream MP3, viene sempre utilizzato il metodo dello streaming tramite proxy per ridurre l'utilizzo della banda. - NL Het afspelen van een mp3-internetstream kan op twee manieren. Directe streaming: het muzieksysteem maakt een directe verbinding met de server die de audio streamt. Je Squeezebox Server wordt hierdoor minder belast en de stream speelt door als de verbinding tussen het muzieksysteem en de Squeezebox Server wordt verbroken. Proxystreaming: de Squeezebox Server zorgt voor de verbinding en geeft de audiostream door aan het muzieksysteem. Directe streaming is de standaard, maar als dit problemen oplevert, kun je proxystreaming proberen. Let op: Als je twee of meer muzieksystemen synchroniseert op een mp3-stream, wordt proxystreaming automatisch ingesteld om zo de gebruikte bandbreedte te minimaliseren. - NO Avspilling av mp3-strømmer fra Internett kan gjøres på to måter: Hvis du bruker direktestrøm oppretter spilleren en direkte forbindelse til serveren som sender lydstrømmen. Det gir litt mindre belastning på Squeezebox Server-maskinen, og strømmen kan spilles av selv om forbindelsen til denne blir brutt. Det er også mulig å sende datastrømmen gjennom Squeezebox Server, som da opptrer som en proxy. Dette kalles proxystrømming. Direktestrømming er standard, men hvis du får problemer med mp3-strømmer, kan du prøve å endre innstillingen til proxystrømming i stedet. Merk: hvis to eller flere spillere er synkronisert med en mp3-strøm, brukes proxystrømming alltid, for å redusere båndbreddebruken. - PL Podczas odtwarzania internetowego strumienia MP3 przesyłanie strumieniowe wykonywane jest na dwa sposoby. Bezpośrednie przesyłanie strumieniowe powoduje połączenie z serwerem strumieniowego przesyłania dźwięku, co nieznacznie zmniejsza obciążenie programu Squeezebox Server i umożliwia kontynuację odtwarzania strumienia, jeżeli połączenie z programem Squeezebox Server zostanie utracone. Przesyłanie strumieniowe z wykorzystaniem serwera proxy powoduje, że program Squeezebox Server obsługuje połączenie, przekazując dźwięk do odtwarzacza. Bezpośrednie przesyłanie strumieniowe to metoda domyślna, ale w przypadku problemów ze strumieniami MP3 należy zmienić ustawienie na Przesyłanie strumieniowe przez serwer proxy. Należy pamiętać, że jeżeli ze strumieniem MP3 zsynchronizowane są co najmniej dwa odtwarzacze, zawsze używane jest przesyłanie strumieniowe przez serwer proxy w celu ograniczenia użycia przepustowości. - RU Поддерживается два способа потоковой передачи МР3 из Интернета. При прямой передаче плеер напрямую подключается к серверу потокового аудио, что несколько уменьшает нагрузку на Squeezebox Server и позволяет продолжать воспроизведение потока в случае разрыва подключения к Squeezebox Server. При передаче через прокси Squeezebox Server обслуживает подключение, передавая аудиоданные плееру. По умолчанию задана прямая потоковая передача, но если возникают проблемы с потоком МР3, можно попробовать переключиться на опосредованную передачу. Помните: если два и более плееров настраиваются на один поток МР3, всегда применяется опосредованная передача для сужения полосы пропускания. - SV När du spelar upp en mp3-ström från internet kan det ske på två olika sätt. Direktströmning innebär att spelaren ansluts direkt till servern som strömmen kommer ifrån, vilket minskar belastningen på Squeezebox Server något och gör det möjligt att fortsätta spela även om anslutningen till Squeezebox Server skulle brytas. Proxyströmmning innebär att Squeezebox Server ansluts till servern och sedan vidarebefordrar ljudet till spelaren. Direktströmning är standard. Om du har problem med mp3-strömmar kan du prova att ändra inställningen till Proxyströmning. Observera att proxyströmning alltid används när flera spelare synkroniseras för att spela upp samma mp3-ström, eftersom detta sparar bandbredd. + CS Při přehrávání MP3 Internet proudu, může být přehrávání datových proudů provedeno jedním ze dvou způsobů. při Direct Streaming přehrávač provede přímé spojení se serverem přehrávání audio proudů a tím mírně sníží zatížení Squeeze Center a umožní přehrávání proudu i po ztrátě spojení Squeeze Center. Proxy Streaming způsobí, že Logitech Media Server zajistí spojení a přehraje audio prostřdnictvím přehrávače. Direct Streaming je výchozí nastavení, ale jestliže budete mít potíže s s MP3 proudy, zkuste změnit nastavení na Proxy Streaming. Pamatujte na to, že pokud jsou s MP3 proudem synchronizovány dva a více přehrávačů, použije se vždy Proxy Streaming k omezení použití širokopásmového přenosu. + DA Når der afspilles en mp3-stream fra internettet, kan det gøres på to måder. Ved direkte streaming etableres der en direkte forbindelse mellem afspilleren og serveren der streames fra. Det reducerer belastningen af Logitech Media Server en smule og afspilningen fortsætter selvom forbindelsen til Logitech Media Server bliver afbrudt. Ved streaming via en proxy vil Logitech Media Server håndtere forbindelsen og sende lyden videre til afspilleren. Direkte streaming er standardmetoden, men hvis du har problemer med mp3-streams, kan du ændre indstillingen til Streaming via proxy. Bemærk at hvis to eller flere afspillere er synkroniseret til en mp3-stream, bliver proxymetoden altid anvendt for at begrænse brugen af båndbredde. + DE Zur Wiedergabe eines MP3-Internet-Streams kann das Streaming auf zwei verschiedene Arten durchgeführt werden. Beim direkten Streaming erstellt der Player eine direkte Verbindung mit dem Audio-Streaming-Server, wodurch die Belastung von Logitech Media Server verringert wird und der Stream auch fortgesetzt werden kann, wenn die Verbindung zu Logitech Media Server unterbrochen wird. Beim Streaming über einen Proxy-Server verwaltet Logitech Media Server die Verbindung und leitet die Musik an den Player weiter. Standardmäßig wird das direkte Streaming verwendet, aber wenn Probleme mit MP3-Streams auftreten, können Sie die andere Methode versuchen. Hinweis: Wenn zwei oder mehre Player synchron auf einem MP3-Stream zugreifen, wird immer das Streaming über einen Proxy-Server verwendet, um die Bandbreitennutzung zu reduzieren. + EN When playing an MP3 Internet stream, the streaming can be done in one of two ways. Direct Streaming causes the player to make a direct connection to the audio streaming server, reducing the load on Logitech Media Server slightly and allowing the stream to continue playing if the Logitech Media Server connection is lost. Proxied Streaming causes Logitech Media Server to handle the connection, passing the audio through to the player. Direct Streaming is the default, but if you experience problems with MP3 streams, try changing this setting to Proxied Streaming. Note that if two or more players are synchronized to an MP3 stream, proxied streaming is always used to reduce bandwidth usage. + ES Al reproducir secuencias MP3 de Internet, el envío por secuencias puede realizarse de dos maneras. Secuencias directas hace que el reproductor establezca una conexión directa con el servidor de secuencias de audio. Esto reduce ligeramente la carga en Logitech Media Server y permite que las secuencias se sigan reproduciendo si se pierde la conexión con Logitech Media Server. Secuencias por proxy hace que Logitech Media Server gestione la conexión y que el audio pase a través del reproductor. Secuencias directas es la opción predeterminada pero, si tiene problemas con secuencias MP3, cambie a Secuencias por proxy. Tenga en cuenta que si hay dos o más reproductores sincronizados con una secuencia MP3, se usa siempre Secuencias por proxy para reducir el uso de ancho de banda. + FI Kun toistetaan MP3 internet -virtaa, virtautus voidaan suorittaa kahdella tavalla. Jos valitaan suora virtautus, soitin muodostaa suoran yhteyden äänen virtautuspalvelimeen. Tämä vähentää Logitech Media Serverin kuormitusta lievästi. Virran toistoa voidaan myös jatkaa, jos Logitech Media Serverin yhteys katkeaa. Jos valitaan virtautus välityspalvelimen kautta, Logitech Media Server huolehtii yhteydestä ja välittää äänen soittimeen. Oletus on suora virtautus, mutta jos MP3-virtojen kanssa esiintyy ongelmia, kokeile vaihtaa välityspalvelimen kautta virtautukseen. Huomaa, että jos vähintään kaksi palvelinta on synkronoitu MP3-virtaan, käytetään aina välityspalvelimen kautta virtautusta, koska se vähentää kaistanleveyden käyttöä. + FR Il existe deux manières de diffuser un flux MP3 sur Internet. La diffusion directe permet à la platine de se connecter directement au serveur de diffusion audio, réduisant ainsi la charge sur le Logitech Media Server et permettant de poursuivre la lecture du flux en cas de perte de la connexion. La diffusion par proxy permet au Logitech Media Server de gérer la connexion et de transmettre le flux audio vers la platine. La diffusion directe est l'option sélectionnée par défaut. Si vous rencontrez des problèmes lors de la lecture des flux MP3, sélectionnez l'option de diffusion par proxy. Notez que si plusieurs platines sont synchronisées pour utiliser un flux MP3, c'est la diffusion proxy qui est utilisée afin de réduire l'utilisation de bande passante. + HE בעת הפעלה של זרימת אינטרנט בתבנית MP3, ניתן להפעיל את הזרימה באחת משתי דרכים. זרימה ישירה גורמת לנגן ליצור חיבור ישיר לשרת הזרימה של השמע, לצמצום קל של העומס על Logitech Media Server וכדי לאפשר לזרימה להימשך במקרה של אובדן החיבור של Logitech Media Server. זרימה ב-Proxy גורמת ל-Logitech Media Server לטפל בחיבור, להעברת השמע לנגן. זרימה ישירה היא ברירת המחדל, אך אם אתה נתקל בבעיות עם זרימות של MP3, נסה לשנות את ההגדרה לזרימה ב-Proxy. שים לב שאם לפחות שני נגנים מסונכרנים לזרימה מסוג MP3, תמיד נעשה שימוש בזרימה ב-Proxy לצמצום השימוש ברוחב הפס. + IT Quando si riproduce uno stream Internet MP3 si possono utilizzare due metodi. Con il metodo dello streaming diretto il riproduttore si collega direttamente al server di streaming audio. Ciò consente di ridurre leggermente il carico di Logitech Media Server e di proseguire la riproduzione dello stream anche nel caso in cui la connessione con Logitech Media Server venga persa. Con il metodo dello streaming tramite proxy la gestione della connessione viene effettuata da Logitech Media Server, il quale passa l'audio al riproduttore. Lo streaming diretto è il metodo predefinito. Se tuttavia si riscontrassero problemi con gli stream MP3, provare a utilizzare il metodo dello streaming tramite proxy. Si noti che se due o più lettori sono sincronizzati su uno stream MP3, viene sempre utilizzato il metodo dello streaming tramite proxy per ridurre l'utilizzo della banda. + NL Het afspelen van een mp3-internetstream kan op twee manieren. Directe streaming: het muzieksysteem maakt een directe verbinding met de server die de audio streamt. Je Logitech Media Server wordt hierdoor minder belast en de stream speelt door als de verbinding tussen het muzieksysteem en de Logitech Media Server wordt verbroken. Proxystreaming: de Logitech Media Server zorgt voor de verbinding en geeft de audiostream door aan het muzieksysteem. Directe streaming is de standaard, maar als dit problemen oplevert, kun je proxystreaming proberen. Let op: Als je twee of meer muzieksystemen synchroniseert op een mp3-stream, wordt proxystreaming automatisch ingesteld om zo de gebruikte bandbreedte te minimaliseren. + NO Avspilling av mp3-strømmer fra Internett kan gjøres på to måter: Hvis du bruker direktestrøm oppretter spilleren en direkte forbindelse til serveren som sender lydstrømmen. Det gir litt mindre belastning på Logitech Media Server-maskinen, og strømmen kan spilles av selv om forbindelsen til denne blir brutt. Det er også mulig å sende datastrømmen gjennom Logitech Media Server, som da opptrer som en proxy. Dette kalles proxystrømming. Direktestrømming er standard, men hvis du får problemer med mp3-strømmer, kan du prøve å endre innstillingen til proxystrømming i stedet. Merk: hvis to eller flere spillere er synkronisert med en mp3-strøm, brukes proxystrømming alltid, for å redusere båndbreddebruken. + PL Podczas odtwarzania internetowego strumienia MP3 przesyłanie strumieniowe wykonywane jest na dwa sposoby. Bezpośrednie przesyłanie strumieniowe powoduje połączenie z serwerem strumieniowego przesyłania dźwięku, co nieznacznie zmniejsza obciążenie programu Logitech Media Server i umożliwia kontynuację odtwarzania strumienia, jeżeli połączenie z programem Logitech Media Server zostanie utracone. Przesyłanie strumieniowe z wykorzystaniem serwera proxy powoduje, że program Logitech Media Server obsługuje połączenie, przekazując dźwięk do odtwarzacza. Bezpośrednie przesyłanie strumieniowe to metoda domyślna, ale w przypadku problemów ze strumieniami MP3 należy zmienić ustawienie na Przesyłanie strumieniowe przez serwer proxy. Należy pamiętać, że jeżeli ze strumieniem MP3 zsynchronizowane są co najmniej dwa odtwarzacze, zawsze używane jest przesyłanie strumieniowe przez serwer proxy w celu ograniczenia użycia przepustowości. + RU Поддерживается два способа потоковой передачи МР3 из Интернета. При прямой передаче плеер напрямую подключается к серверу потокового аудио, что несколько уменьшает нагрузку на Logitech Media Server и позволяет продолжать воспроизведение потока в случае разрыва подключения к Logitech Media Server. При передаче через прокси Logitech Media Server обслуживает подключение, передавая аудиоданные плееру. По умолчанию задана прямая потоковая передача, но если возникают проблемы с потоком МР3, можно попробовать переключиться на опосредованную передачу. Помните: если два и более плееров настраиваются на один поток МР3, всегда применяется опосредованная передача для сужения полосы пропускания. + SV När du spelar upp en mp3-ström från internet kan det ske på två olika sätt. Direktströmning innebär att spelaren ansluts direkt till servern som strömmen kommer ifrån, vilket minskar belastningen på Logitech Media Server något och gör det möjligt att fortsätta spela även om anslutningen till Logitech Media Server skulle brytas. Proxyströmmning innebär att Logitech Media Server ansluts till servern och sedan vidarebefordrar ljudet till spelaren. Direktströmning är standard. Om du har problem med mp3-strömmar kan du prova att ändra inställningen till Proxyströmning. Observera att proxyströmning alltid används när flera spelare synkroniseras för att spela upp samma mp3-ström, eftersom detta sparar bandbredd. MP3_STREAMING_DIRECT CS Přímý datový proud @@ -6097,21 +6098,21 @@ SETUP_GUESSFILEFORMATS ZH_CN 猜测标签格式 SETUP_GROUP_GUESSFILEFORMATS_DESC - CS U souborů, které nemají srozumitelné tagy, můžete nechat Squeezebox Server odhadnout tagy podle cesty a názvu souboru. Pomocí stejné proměnné jako je formát názvu (Title Format) můžete vytvořit vzor odpovídající zvyklostem pojmenování vašich souborů tak, aby aplikace mohla provést odhad, jaké by tagy měly být. Priorita je dána v pořadí uvedeném níže. Bude použit první platný soulad se vzorem. - DA Hvis filer ikke har meningsfulde mærker, kan Squeezebox Server gætte hvad mærkerne burde være, ud fra stien og filnavnene. Hvis du bruger de samme variable som i titelformatet, kan du oprette et mønster det svarer til konventionerne du bruger ved navngivning af filer, og på den måde kan programmet komme med kvalificerede gæt på hvad mærkerne burde være. Prioritetsrækkefølgen er som rækkefølgen nedenfor. Det første gyldige mønster der matcher filnavnene, bliver brugt. - DE Bei Dateien, die keine sinnvollen Tags enthalten, kann Squeezebox Server versuchen, die Informationen aus dem Pfad und Dateinamen zu gewinnen. Mit denselben Variablen wie für das Titelformat können Sie Dateinamenskonventionen definieren, damit Squeezebox Server die Tags besser erraten kann. Dies geschieht in der unten vermerkten Reihenfolge. Die erste gültige Musterübereinstimmung wird verwendet. - EN For files that do not have reasonable tags, you can have Squeezebox Server guess at tags using the path and filename. Using the same variables as Title Format, you can create a pattern to match your file naming conventions so that the application can make a good guess at what the tags should be. Priority goes in the order listed below. The first valid pattern match is used. - ES Para aquellos archivos que no tengan etiquetas razonables, se puede hacer que Squeezebox Server las suponga utilizando la ruta y el nombre de archivo. Utilizando las mismas variables que en Formato de título, se puede crear un patrón para que coincida con las convenciones de nomenclatura de tal forma que el servidor pueda hacer buenas suposiciones de lo que tendrían que ser las etiquetas. La prioridad se indica en la lista siguiente. Se usa la primera coincidencia con un patrón válido. - FI Jos tiedostoissa ei ole kunnollisia tunnisteita, voit määrittää Squeezebox Serverin arvaamaan tunnisteet polun ja tiedostonimen pohjalta. Voit luoda tiedostojen nimeämiskäytäntöjä vastaavan mallin käyttäen samoja muuttujia kuin nimen muodossa. Näin sovellus voi arvata hyvällä tarkkuudella, missä tunnisteiden pitäisi olla. Prioriteetti noudattaa alla olevaa luetteloa. Sovellus käyttää ensimmäistä kelvollista mallivastaavuutta. - FR Le Squeezebox Server peut tenter de compléter les repères ID3 manquants ou incomplets de vos fichiers musicaux à partir de leur chemin ou de leur nom de fichier. En utilisant les mêmes variables que pour le format du titre, vous pouvez spécifier des masques type afin de déterminer les repères ID3. Les masques seront testés dans l'ordre ci-dessous. Le premier masque valide est appliqué. + CS U souborů, které nemají srozumitelné tagy, můžete nechat Logitech Media Server odhadnout tagy podle cesty a názvu souboru. Pomocí stejné proměnné jako je formát názvu (Title Format) můžete vytvořit vzor odpovídající zvyklostem pojmenování vašich souborů tak, aby aplikace mohla provést odhad, jaké by tagy měly být. Priorita je dána v pořadí uvedeném níže. Bude použit první platný soulad se vzorem. + DA Hvis filer ikke har meningsfulde mærker, kan Logitech Media Server gætte hvad mærkerne burde være, ud fra stien og filnavnene. Hvis du bruger de samme variable som i titelformatet, kan du oprette et mønster det svarer til konventionerne du bruger ved navngivning af filer, og på den måde kan programmet komme med kvalificerede gæt på hvad mærkerne burde være. Prioritetsrækkefølgen er som rækkefølgen nedenfor. Det første gyldige mønster der matcher filnavnene, bliver brugt. + DE Bei Dateien, die keine sinnvollen Tags enthalten, kann Logitech Media Server versuchen, die Informationen aus dem Pfad und Dateinamen zu gewinnen. Mit denselben Variablen wie für das Titelformat können Sie Dateinamenskonventionen definieren, damit Logitech Media Server die Tags besser erraten kann. Dies geschieht in der unten vermerkten Reihenfolge. Die erste gültige Musterübereinstimmung wird verwendet. + EN For files that do not have reasonable tags, you can have Logitech Media Server guess at tags using the path and filename. Using the same variables as Title Format, you can create a pattern to match your file naming conventions so that the application can make a good guess at what the tags should be. Priority goes in the order listed below. The first valid pattern match is used. + ES Para aquellos archivos que no tengan etiquetas razonables, se puede hacer que Logitech Media Server las suponga utilizando la ruta y el nombre de archivo. Utilizando las mismas variables que en Formato de título, se puede crear un patrón para que coincida con las convenciones de nomenclatura de tal forma que el servidor pueda hacer buenas suposiciones de lo que tendrían que ser las etiquetas. La prioridad se indica en la lista siguiente. Se usa la primera coincidencia con un patrón válido. + FI Jos tiedostoissa ei ole kunnollisia tunnisteita, voit määrittää Logitech Media Serverin arvaamaan tunnisteet polun ja tiedostonimen pohjalta. Voit luoda tiedostojen nimeämiskäytäntöjä vastaavan mallin käyttäen samoja muuttujia kuin nimen muodossa. Näin sovellus voi arvata hyvällä tarkkuudella, missä tunnisteiden pitäisi olla. Prioriteetti noudattaa alla olevaa luetteloa. Sovellus käyttää ensimmäistä kelvollista mallivastaavuutta. + FR Le Logitech Media Server peut tenter de compléter les repères ID3 manquants ou incomplets de vos fichiers musicaux à partir de leur chemin ou de leur nom de fichier. En utilisant les mêmes variables que pour le format du titre, vous pouvez spécifier des masques type afin de déterminer les repères ID3. Les masques seront testés dans l'ordre ci-dessous. Le premier masque valide est appliqué. HE עבור קבצים שלא כוללים תגים הגיוניים, באפשרותך להורות לשרת לנחש תגים באמצעות הנתיב ושם הקובץ. באמצעות משתנים אלה עבור תבנית השם, באפשרותך ליצור תבנית שתתאים למוסכמות מתן השמות לקבצים שבהן אתה משתמש כך שיהיה באפשרות השרת לבצע ניחוש מוצלח עבור התגים. העדיפות מתקיימת לפי הסדר המפורט להלן. נעשה שימוש בהתאמה הראשונה של תבנית חוקית. - IT In caso di file non provvisti di tag appropriati, è possibile impostare Squeezebox Server in modo che individui i tag corretti in base al percorso e al nome file. Utilizzando le stesse variabili adottate per il formato titolo, è possibile creare un modello con le stesse convenzioni di denominazione del file in modo da facilitare il rilevamento dei tag appropriati tramite il server. Di seguito è indicato l'ordine di priorità adottato. Viene utilizzato il primo modello corrispondente. + IT In caso di file non provvisti di tag appropriati, è possibile impostare Logitech Media Server in modo che individui i tag corretti in base al percorso e al nome file. Utilizzando le stesse variabili adottate per il formato titolo, è possibile creare un modello con le stesse convenzioni di denominazione del file in modo da facilitare il rilevamento dei tag appropriati tramite il server. Di seguito è indicato l'ordine di priorità adottato. Viene utilizzato il primo modello corrispondente. JA 正しいタグが含まれていないファイルに関しては、サーバーが推測するよう指定できます。どのようなパターンで推測するか指定してください。 - NL Je kunt Squeezebox Server naar tags laten raden met behulp van pad en bestandsnaam voor bestanden die geen goede taginformatie hebben. Je kunt dezelfde variabelen als bij 'Titelformaat' gebruiken om een patroon te maken dat correspondeert met de gebruikte bestandsnaamconventie, zodat Squeezebox Server kan raden wat de tags moeten zijn. De prioriteitsvolgorde staat hieronder. Het eerste correcte patroon wordt gebruikt. - NO Hvis du har filer som ikke har forståelige etiketter, kan Squeezebox Server gjette på etiketter ved å bruke informasjon om bane og filnavn. Ved å bruke noen av de samme variablene som i Tittelformat, kan du lage et mønster som passer måten du navngir filer på, slik at programmet lettere kan gjette hva etikettene skal være. Programmet prioriterer som oppgitt nedenfor. Det første gyldige treffet på mønster brukes. - PL W przypadku plików, które nie mają odpowiednich znaczników program Squeezebox Server może odgadnąć tagi na podstawie ścieżki i nazwy pliku. Używając tej samej zmiennej co opcja Format tytułu, można utworzyć wzór odpowiedni do utworzenia konwencji nazywania plików, co ułatwi aplikacji utworzenie właściwego znacznika. Priorytety mają kolejność podaną poniżej. Stosowany jest pierwszy pasujący wzór. - RU Squeezebox Server может угадывать теги на основе пути и имени файла для тех файлов, у которых нет корректных тегов. С помощью переменных, аналогичных формату названия, можно создать шаблон, отвечающий условиям именования файлов, чтобы приложению было легче угадывать возможные теги. Приоритет присваивается в нижеследующем порядке. Используется первое допустимое совпадение шаблона. - SV För filer som inte har taggats korrekt kan du låta Squeezebox Server gissa taggarna med hjälp av sökväg och filnamn. Om du använder samma variabler som i titelformatet kan du skapa ett mönster som överensstämmer med hur man brukar namnge filer, så kan programmet gissa vad taggarna borde vara. Prioriteringsordningen är densamma som i listan nedan. Det första giltiga mönstret används. + NL Je kunt Logitech Media Server naar tags laten raden met behulp van pad en bestandsnaam voor bestanden die geen goede taginformatie hebben. Je kunt dezelfde variabelen als bij 'Titelformaat' gebruiken om een patroon te maken dat correspondeert met de gebruikte bestandsnaamconventie, zodat Logitech Media Server kan raden wat de tags moeten zijn. De prioriteitsvolgorde staat hieronder. Het eerste correcte patroon wordt gebruikt. + NO Hvis du har filer som ikke har forståelige etiketter, kan Logitech Media Server gjette på etiketter ved å bruke informasjon om bane og filnavn. Ved å bruke noen av de samme variablene som i Tittelformat, kan du lage et mønster som passer måten du navngir filer på, slik at programmet lettere kan gjette hva etikettene skal være. Programmet prioriterer som oppgitt nedenfor. Det første gyldige treffet på mønster brukes. + PL W przypadku plików, które nie mają odpowiednich znaczników program Logitech Media Server może odgadnąć tagi na podstawie ścieżki i nazwy pliku. Używając tej samej zmiennej co opcja Format tytułu, można utworzyć wzór odpowiedni do utworzenia konwencji nazywania plików, co ułatwi aplikacji utworzenie właściwego znacznika. Priorytety mają kolejność podaną poniżej. Stosowany jest pierwszy pasujący wzór. + RU Logitech Media Server может угадывать теги на основе пути и имени файла для тех файлов, у которых нет корректных тегов. С помощью переменных, аналогичных формату названия, можно создать шаблон, отвечающий условиям именования файлов, чтобы приложению было легче угадывать возможные теги. Приоритет присваивается в нижеследующем порядке. Используется первое допустимое совпадение шаблона. + SV För filer som inte har taggats korrekt kan du låta Logitech Media Server gissa taggarna med hjälp av sökväg och filnamn. Om du använder samma variabler som i titelformatet kan du skapa ett mönster som överensstämmer med hur man brukar namnge filer, så kan programmet gissa vad taggarna borde vara. Prioriteringsordningen är densamma som i listan nedan. Det första giltiga mönstret används. ZH_CN 那些没有合理标签的文件,您可以让服务器凭着使用路径和文件名为基础进行标签猜测。您可以使用和标题格式一样的变量来建立匹配您的文件命名惯例的样式,以方便服务器对标签的猜测。优先权将取决于下列的排序。第一个被匹配的样式将被接受使用。 SETUP_IRMAP @@ -6204,25 +6205,25 @@ SETUP_LANGUAGE ZH_CN 语言 SETUP_LANGUAGE_DESC - CS Vyberte jazyk, který chcete používat na Squeezebox Server. Položky označené * byly přeloženy komunitou zákazníků Squeezebox Server. Pokud zjistíte nějaké problémy nebo budete chtít přispět, kontaktujte vývojáře na adrese forums.slimdevices.com. - DA Vælg det sprog som teksten i Squeezebox Servers brugerflade skal vises på. De sprog som er markeret med en stjerne (*), er oversat af Squeezebox Servers brugergrupper. Hvis du opdager fejl eller ønsker at bidrage, kan du kontakte udviklerne på forums.slimdevices.com. - DE Wählen Sie die Sprache für Squeezebox Server. Die mit * markierten Sprachen wurden durch die Squeezebox Server-Community bereitgestellt. Falls Probleme auftreten oder Sie Verbesserungsvorschläge haben, wenden Sie sich an die Entwickler unter forums.slimdevices.com. - EN Choose the language that you'd like to use with Squeezebox Server. Those marked with * were translated by the Squeezebox Server customer community. If you find problems or would like to contribute, contact the developers at forums.slimdevices.com. - ES Elija el idioma que desea utilizar con Squeezebox Server. Un * significa que el idioma en cuestión ha sido traducido por la comunidad de usuarios de Squeezebox Server. Si tiene alguna consulta que realizar o desea aportar su contribución, póngase en contacto con los desarrolladores a forums.slimdevices.com. - FI Valitse kieli, jota haluat käyttää Squeezebox Serverissä. Tähdellä (*) merkityt ovat Squeezebox Serverin käyttäjäyhteisön kääntämiä. Jos löydät virheitä tai haluat kantaa oman kortesi kekoon, ota yhteyttä kehittäjiin osoitteessa forums.slimdevices.com. - FR Sélectionnez la langue à utiliser pour le Squeezebox Server. Les langues marquées d'un astérisque (*) contiennent des traductions réalisées par la communauté des utilisateurs Squeezebox Server. Pour signaler un problème ou si vous souhaitez contribuer, contactez les développeurs à l'adresse suivante: forums.slimdevices.com. - IT Scegliere la lingua che si desidera utilizzare con Squeezebox Server. Le versioni nelle lingue contrassegnate con un asterisco (*) sono state tradotte da utenti di Squeezebox Server. Se si individuano dei problemi o si desidera fornire un contributo, contattare gli sviluppatori alla pagina forums.slimdevices.com. - NL Kies de taal die je met Squeezebox Server wilt gebruiken. De talen met een sterretje (*) zijn door de klantencommunity van Squeezebox Server vertaald. Wil je verbeteringen voorstellen of aan vertalingen bijdragen, stuur dan een e-mail naar forums.slimdevices.com. - NO Velg hvilket språk du vil bruke i Squeezebox Server. Språk markert med * er oversatt av Squeezebox Server-brukere. Hvis du oppdager problemer eller ønsker å hjelpe til, kan du sende en e-post til forums.slimdevices.com. - PL Wybierz język programu Squeezebox Server. Tłumaczenia na języki oznaczone * zostały wykonane przez społeczność użytkowników programu Squeezebox Server. W przypadku znalezienia problemów lub jeżeli chcesz rozpocząć współpracę, skontaktuj się z twórcami pod adresem forums.slimdevices.com. - RU Выберите язык программы Squeezebox Server. На языки, помеченные звездочкой (*), программа была переведена сообществом пользователей Squeezebox Server. Если вы найдете ошибки или захотите сотрудничать с нами, напишите по адресу forums.slimdevices.com. - SV Välj språk för Squeezebox Server. Språkversioner markerade med en asterisk (*) har översatts av Squeezebox Server-användare. Om du stöter på problem eller om du vill hjälpa till med översättningen kan du ta kontakt med programutvecklarna på forums.slimdevices.com. + CS Vyberte jazyk, který chcete používat na Logitech Media Server. Položky označené * byly přeloženy komunitou zákazníků Logitech Media Server. Pokud zjistíte nějaké problémy nebo budete chtít přispět, kontaktujte vývojáře na adrese forums.slimdevices.com. + DA Vælg det sprog som teksten i Logitech Media Servers brugerflade skal vises på. De sprog som er markeret med en stjerne (*), er oversat af Logitech Media Servers brugergrupper. Hvis du opdager fejl eller ønsker at bidrage, kan du kontakte udviklerne på forums.slimdevices.com. + DE Wählen Sie die Sprache für Logitech Media Server. Die mit * markierten Sprachen wurden durch die Logitech Media Server-Community bereitgestellt. Falls Probleme auftreten oder Sie Verbesserungsvorschläge haben, wenden Sie sich an die Entwickler unter forums.slimdevices.com. + EN Choose the language that you'd like to use with Logitech Media Server. Those marked with * were translated by the Logitech Media Server customer community. If you find problems or would like to contribute, contact the developers at forums.slimdevices.com. + ES Elija el idioma que desea utilizar con Logitech Media Server. Un * significa que el idioma en cuestión ha sido traducido por la comunidad de usuarios de Logitech Media Server. Si tiene alguna consulta que realizar o desea aportar su contribución, póngase en contacto con los desarrolladores a forums.slimdevices.com. + FI Valitse kieli, jota haluat käyttää Logitech Media Serverissä. Tähdellä (*) merkityt ovat Logitech Media Serverin käyttäjäyhteisön kääntämiä. Jos löydät virheitä tai haluat kantaa oman kortesi kekoon, ota yhteyttä kehittäjiin osoitteessa forums.slimdevices.com. + FR Sélectionnez la langue à utiliser pour le Logitech Media Server. Les langues marquées d'un astérisque (*) contiennent des traductions réalisées par la communauté des utilisateurs Logitech Media Server. Pour signaler un problème ou si vous souhaitez contribuer, contactez les développeurs à l'adresse suivante: forums.slimdevices.com. + IT Scegliere la lingua che si desidera utilizzare con Logitech Media Server. Le versioni nelle lingue contrassegnate con un asterisco (*) sono state tradotte da utenti di Logitech Media Server. Se si individuano dei problemi o si desidera fornire un contributo, contattare gli sviluppatori alla pagina forums.slimdevices.com. + NL Kies de taal die je met Logitech Media Server wilt gebruiken. De talen met een sterretje (*) zijn door de klantencommunity van Logitech Media Server vertaald. Wil je verbeteringen voorstellen of aan vertalingen bijdragen, stuur dan een e-mail naar forums.slimdevices.com. + NO Velg hvilket språk du vil bruke i Logitech Media Server. Språk markert med * er oversatt av Logitech Media Server-brukere. Hvis du oppdager problemer eller ønsker å hjelpe til, kan du sende en e-post til forums.slimdevices.com. + PL Wybierz język programu Logitech Media Server. Tłumaczenia na języki oznaczone * zostały wykonane przez społeczność użytkowników programu Logitech Media Server. W przypadku znalezienia problemów lub jeżeli chcesz rozpocząć współpracę, skontaktuj się z twórcami pod adresem forums.slimdevices.com. + RU Выберите язык программы Logitech Media Server. На языки, помеченные звездочкой (*), программа была переведена сообществом пользователей Logitech Media Server. Если вы найдете ошибки или захотите сотрудничать с нами, напишите по адресу forums.slimdevices.com. + SV Välj språk för Logitech Media Server. Språkversioner markerade med en asterisk (*) har översatts av Logitech Media Server-användare. Om du stöter på problem eller om du vill hjälpa till med översättningen kan du ta kontakt med programutvecklarna på forums.slimdevices.com. SETUP_LIBRARY_NAME CS Název hudební knihovny DA Navn på musikbibliotek DE Name der Musiksammlung - EN Music library name + EN Media library name ES Nombre de biblioteca de música FI Musiikkikirjaston nimi FR Nom de la collection musicale @@ -6237,7 +6238,7 @@ SETUP_LIBRARY_NAME_DESC CS Tak se bude jmenovat vaše hudební knihovna v menu "Moje hudba" vašeho Squeezebox. DA Dit musikbibliotek får dette navn i Squeezebox-menuen Musik. DE Das ist der Name der Squeezebox im Menü "Eigene Musik". - EN This is how your music library will be named in your Squeezebox's "My Music" menu. + EN This is how your media library will be named in your Squeezebox's "My Media" menu. ES Así es como se llamará la biblioteca de música en el menú de \"Mi música\" de Squeezebox. FI Näin musiikkikirjastosi nimetään Squeezeboxisi Oma musiikki -valikossa. FR Votre collection musicale est nommée de cette manière sous le menu "Ma musique" de la Squeezebox. @@ -6267,22 +6268,34 @@ SETUP_AUDIODIR ZH_CN 音乐文件夹 SETUP_AUDIODIR_DESC - CS Můžete zadat složku obsahující hudební soubory, kterou bude Squeezebox Server prohledávat, a přidat do své hudební knihovny. Níže zadejte cestu ke složce. Můžete toto pole ponechat prázdné, pokud importujete informace o své knihovně hudby z iTunes nebo MusicIP. - DA Du kan angive en mappe med musikfiler som Squeezebox Server vil gennemsøge og føje til musikbiblioteket. Angiv stien til mappen nedenfor. Feltet kan være tomt hvis du importerer oplysninger om musikbiblioteket fra iTunes eller MusicIP. - DE Geben Sie den Ordner ein, der die Musikdateien enthält, die von Squeezebox Server durchsucht und der Musiksammlung hinzugefügt werden sollen. Sie können dieses Feld leer lassen, wenn Sie die Musiksammlung über iTunes oder MusicIP importieren. - EN You can specify a folder containing music files that Squeezebox Server will scan and add to your music library. Enter the path to the folder below. You can leave this field blank if you are importing your music library information from iTunes or MusicIP. - ES Se puede especificar una carpeta que contenga archivos de música para que Squeezebox Server la examine y agregue a la biblioteca de música. Introduzca la ruta a ala carpeta a continuación. Se puede dejar este campo en blanco si va a importar la información de la biblioteca de música desde iTunes o MusicIP. - FI Voit määrittää kansion, jonka Squeezebox Server tarkistaa ja josta se etsii musiikkitiedostoja musiikkikirjastoon lisättäväksi. Kirjoita kansion polku alle. Voit jättää kentän tyhjäksi, jos tuot musiikkikirjastotietoja iTunes- tai MusicIP-sovelluksista. - FR Vous pouvez spécifier un dossier contenant vos fichiers musicaux afin que le Squeezebox Server l'analyse et ajoute son contenu à votre collection musicale. Spécifiez le chemin ci-dessous. Vous pouvez ignorer ce champ si vous importez les informations de votre collection musicale à partir d'iTunes ou de MusicIP. - HE באפשרותך לציין תיקייה שמכילה קובצי מוסיקה שעל Squeezebox Server לסרוק ולהוסיף לספריית המוסיקה שלך. הזן את הנתיב לתיקייה בשדה שלהלן. באפשרותך להשאיר שדה זה ריק אם אתה מייבא את מידע ספריית המוסיקה מ-iTunes או מ-MusicIP. - IT È possibile indicare una cartella contenente file musicali che Squeezebox Server analizzerà e aggiungerà alla libreria musicale. Inserire di seguito il percorso della cartella. Si può lasciare il campo vuoto se si importa la libreria musicale da iTunes o MusicIP. - JA Squeezebox Serverが検索するフォルダーを指定することができます。iTunesまたはムードロジックの情報を利用する場合はブランクで構いません。 - NL Je kunt een map met muziekbestanden opgeven zodat Squeezebox Server de map scant en aan je muziekcollectie toevoegt. Voer hieronder het pad naar de map in. Je kunt dit veld leeg laten als je je muziekcollectiegegevens uit iTunes of MusicIP importeert. - NO Du kan angi en mappe med musikkfiler som Squeezebox Server skal søke gjennom og legge til i musikkbiblioteket. Angi banen til mappen nedenfor. Du kan la dette feltet stå tomt hvis du importerer informasjon om musikkbibliotek fra iTunes eller MusicIP. - PL Możliwe jest określenie folderu zawierającego pliki muzyczne, który program Squeezebox Server przeszuka w celu dodania ich do biblioteki muzyki. Wprowadź ścieżkę do folderu poniżej. To pole można pozostawić puste w przypadku importowania informacji o bibliotece muzyki z programu iTunes lub MusicIP. - RU Можно задать папку, содержащую музыкальные файлы, которые Squeezebox Server будет сканировать и добавлять в медиатеку. Введите путь к папке ниже. Это поле можно не заполнять, если информация медиатеки импортируется из iTunes или MusicIP. + CS Můžete zadat složku obsahující hudební soubory, kterou bude Logitech Media Server prohledávat, a přidat do své hudební knihovny. Níže zadejte cestu ke složce. Můžete toto pole ponechat prázdné, pokud importujete informace o své knihovně hudby z iTunes nebo MusicIP. + DA Du kan angive en mappe med musikfiler som Logitech Media Server vil gennemsøge og føje til musikbiblioteket. Angiv stien til mappen nedenfor. Feltet kan være tomt hvis du importerer oplysninger om musikbiblioteket fra iTunes eller MusicIP. + DE Geben Sie den Ordner ein, der die Musikdateien enthält, die von Logitech Media Server durchsucht und der Musiksammlung hinzugefügt werden sollen. Sie können dieses Feld leer lassen, wenn Sie die Musiksammlung über iTunes oder MusicIP importieren. + EN You can specify a folder containing music files that Logitech Media Server will scan and add to your music library. Enter the path to the folder below. You can leave this field blank if you are importing your music library information from iTunes or MusicIP. + ES Se puede especificar una carpeta que contenga archivos de música para que Logitech Media Server la examine y agregue a la biblioteca de música. Introduzca la ruta a ala carpeta a continuación. Se puede dejar este campo en blanco si va a importar la información de la biblioteca de música desde iTunes o MusicIP. + FI Voit määrittää kansion, jonka Logitech Media Server tarkistaa ja josta se etsii musiikkitiedostoja musiikkikirjastoon lisättäväksi. Kirjoita kansion polku alle. Voit jättää kentän tyhjäksi, jos tuot musiikkikirjastotietoja iTunes- tai MusicIP-sovelluksista. + FR Vous pouvez spécifier un dossier contenant vos fichiers musicaux afin que le Logitech Media Server l'analyse et ajoute son contenu à votre collection musicale. Spécifiez le chemin ci-dessous. Vous pouvez ignorer ce champ si vous importez les informations de votre collection musicale à partir d'iTunes ou de MusicIP. + HE באפשרותך לציין תיקייה שמכילה קובצי מוסיקה שעל Logitech Media Server לסרוק ולהוסיף לספריית המוסיקה שלך. הזן את הנתיב לתיקייה בשדה שלהלן. באפשרותך להשאיר שדה זה ריק אם אתה מייבא את מידע ספריית המוסיקה מ-iTunes או מ-MusicIP. + IT È possibile indicare una cartella contenente file musicali che Logitech Media Server analizzerà e aggiungerà alla libreria musicale. Inserire di seguito il percorso della cartella. Si può lasciare il campo vuoto se si importa la libreria musicale da iTunes o MusicIP. + JA Logitech Media Serverが検索するフォルダーを指定することができます。iTunesまたはムードロジックの情報を利用する場合はブランクで構いません。 + NL Je kunt een map met muziekbestanden opgeven zodat Logitech Media Server de map scant en aan je muziekcollectie toevoegt. Voer hieronder het pad naar de map in. Je kunt dit veld leeg laten als je je muziekcollectiegegevens uit iTunes of MusicIP importeert. + NO Du kan angi en mappe med musikkfiler som Logitech Media Server skal søke gjennom og legge til i musikkbiblioteket. Angi banen til mappen nedenfor. Du kan la dette feltet stå tomt hvis du importerer informasjon om musikkbibliotek fra iTunes eller MusicIP. + PL Możliwe jest określenie folderu zawierającego pliki muzyczne, który program Logitech Media Server przeszuka w celu dodania ich do biblioteki muzyki. Wprowadź ścieżkę do folderu poniżej. To pole można pozostawić puste w przypadku importowania informacji o bibliotece muzyki z programu iTunes lub MusicIP. + RU Можно задать папку, содержащую музыкальные файлы, которые Logitech Media Server будет сканировать и добавлять в медиатеку. Введите путь к папке ниже. Это поле можно не заполнять, если информация медиатеки импортируется из iTunes или MusicIP. SV Du kan ange en mapp med de musikfiler som ska sökas igenom och läggas till i ditt musikbibliotek. Ange sökvägen till mappen nedan: Om du importerar musikbibliotek från iTunes eller MusicIP kan du lämna fältet tomt. - ZH_CN 您可以指定Squeezebox Server所扫描和用来增加您的音乐库的音乐文件夹。请在以下的资料栏内输入此文件夹的完整路径。如果您从iTunes或MusicIP导入您音乐库信息,您可以让此资料栏空白。 + ZH_CN 您可以指定Logitech Media Server所扫描和用来增加您的音乐库的音乐文件夹。请在以下的资料栏内输入此文件夹的完整路径。如果您从iTunes或MusicIP导入您音乐库信息,您可以让此资料栏空白。 + +SETUP_MEDIADIRS + EN Media Folders + +SETUP_MEDIADIRS_DESC + EN You can specify one or more folders containing media files that Logitech Media Server will scan and add to your media library. Enter the paths to the folder below. + +SETUP_MEDIADIRS_EXCLUSION_LIST + EN Folders and Media Types + +SETUP_MEDIADIRS_EXCLUSION_LIST_DESC + EN Define for every media folder what kind of media you want to use it for. SETUP_PLAYLISTDIR CS Složka seznamu skladeb @@ -6322,21 +6335,21 @@ SETUP_ARTFOLDER ZH_CN 封面图象文件夹 SETUP_ARTFOLDER_DESC - CS Můžete si zvolit ukládání všech vašich obalů alb do jedné složky s pomocí volby proměnných názvů souborů výše. Zde zadejte umístění souborů obalů alb. Bez ohledu na toto umístění bude Squeezebox Server stále hledat obaly alb na stejné cestě jako každý zvukový soubor, pokud nebude ve složce obalů alb nalezen žádný odpovídající obal alba. - DA Du kan vælge at gemme alle albumcovere i en enkelt mappe og bruge indstillingen til variable filnavne ovenfor. Her skal du angive hvor filerne med albumcoverne er placeret. Uanset hvor mappen er placeret, vil Squeezebox Server stadig se efter coverbilleder i samme mappe som de enkelte lydfiler hvis der ikke blev fundet et cover i mappen med albumcovere. - DE Mit der Option 'Variable Dateinamen' können Sie alle Plattenhüllen in einem Ordner ablegen. Geben Sie hier den Speicherort der entsprechenden Dateien ein. Unabhängig von diesem Ordner sucht Squeezebox Server die Plattenhülle im selben Pfad wie die entsprechende Audiodatei, falls keine Plattenhülle im Ordner für Plattenhüllen gefunden wird. - EN You may choose to store all your artwork in a single folder, using the variable filenames option above. Enter the location of the Artwork files here. Regardless of this location, Squeezebox Server will still look for artwork in the same path as each audio file if no matching artwork is found in the Artwork Folder. - ES Se puede optar por almacenar todas las carátulas en una única carpeta, con la opción de nombre de archivos variables anterior. Introduzca aquí la ubicación de los archivos de carátula. Independientemente de esta ubicación, Squeezebox Server seguirá buscando carátulas en la misma ruta que cada archivo de audio si no se encuentran carátulas coincidentes en la carpeta de carátulas. - FI Halutessasi voit tallentaa kaikki kansikuvat yhteen kansioon käyttäen tiedostonimien muuttujien asetusta yllä. Kirjoita kansikuvatiedostojen sijainti tähän. Tästä huolimatta Squeezebox Server etsii yhä kansikuvia samasta polusta kuin äänitiedostoja, jos se ei löydä vastaavia kansikuvia kansikuvakansiosta. - FR Vous pouvez choisir de stocker toutes les pochettes dans un dossier unique en utilisant les noms de fichier variables décrits plus haut. Spécifiez l'emplacement des fichiers de pochette ci-dessous. Si aucune pochette correspondante n'est trouvée à cet emplacement, le Squeezebox Server la cherchera à l'emplacement du fichier de musique. + CS Můžete si zvolit ukládání všech vašich obalů alb do jedné složky s pomocí volby proměnných názvů souborů výše. Zde zadejte umístění souborů obalů alb. Bez ohledu na toto umístění bude Logitech Media Server stále hledat obaly alb na stejné cestě jako každý zvukový soubor, pokud nebude ve složce obalů alb nalezen žádný odpovídající obal alba. + DA Du kan vælge at gemme alle albumcovere i en enkelt mappe og bruge indstillingen til variable filnavne ovenfor. Her skal du angive hvor filerne med albumcoverne er placeret. Uanset hvor mappen er placeret, vil Logitech Media Server stadig se efter coverbilleder i samme mappe som de enkelte lydfiler hvis der ikke blev fundet et cover i mappen med albumcovere. + DE Mit der Option 'Variable Dateinamen' können Sie alle Plattenhüllen in einem Ordner ablegen. Geben Sie hier den Speicherort der entsprechenden Dateien ein. Unabhängig von diesem Ordner sucht Logitech Media Server die Plattenhülle im selben Pfad wie die entsprechende Audiodatei, falls keine Plattenhülle im Ordner für Plattenhüllen gefunden wird. + EN You may choose to store all your artwork in a single folder, using the variable filenames option above. Enter the location of the Artwork files here. Regardless of this location, Logitech Media Server will still look for artwork in the same path as each audio file if no matching artwork is found in the Artwork Folder. + ES Se puede optar por almacenar todas las carátulas en una única carpeta, con la opción de nombre de archivos variables anterior. Introduzca aquí la ubicación de los archivos de carátula. Independientemente de esta ubicación, Logitech Media Server seguirá buscando carátulas en la misma ruta que cada archivo de audio si no se encuentran carátulas coincidentes en la carpeta de carátulas. + FI Halutessasi voit tallentaa kaikki kansikuvat yhteen kansioon käyttäen tiedostonimien muuttujien asetusta yllä. Kirjoita kansikuvatiedostojen sijainti tähän. Tästä huolimatta Logitech Media Server etsii yhä kansikuvia samasta polusta kuin äänitiedostoja, jos se ei löydä vastaavia kansikuvia kansikuvakansiosta. + FR Vous pouvez choisir de stocker toutes les pochettes dans un dossier unique en utilisant les noms de fichier variables décrits plus haut. Spécifiez l'emplacement des fichiers de pochette ci-dessous. Si aucune pochette correspondante n'est trouvée à cet emplacement, le Logitech Media Server la cherchera à l'emplacement du fichier de musique. HE באפשרותך לבחור לאחסן את כל העטיפות בתיקייה יחידה, באמצעות האפשרות לשינוי שמות קבצים שלעיל. הזן כאן את המיקום של קובצי העטיפות. ללא תלות במיקום זה, השרת עדיין יחפש עטיפות בנתיב של כל קובץ שמע אם לא נמצאו עטיפות מתאימות בתיקיית העטיפות. IT Si può scegliere di archiviare tutte le copertine in una sola cartella, usando l'opzione per i nomi di file variabili indicata sopra. Inserire qui la posizione dei file delle copertine. Se nella cartella delle copertine non viene trovata alcuna copertina corrispondente, ne viene eseguita una ricerca nello stesso percorso dei file audio . JA アートワークを1つのフォルダーにまとめて保存しても構いません。以下に入力してください。フォルダー名を指定しても、もし見つからなければ、音楽ファイルがある場所を探します。 - NL Je kunt alle hoesafbeeldingen in één map opslaan via de optie voor variabele bestandsnamen hierboven. Typ hier de locatie van de bestanden met hoesafbeeldingen. Ongeacht wat je hier invult, zal Squeezebox Server ook nog in de map met de audiobestanden kijken, als in de map met hoesafbeeldingen geen hoesje is gevonden. - NO Med alternativet for variable filnavn ovenfor, kan du velge å lagre alle albumomslag i samme mappe. Angi hvor du vil lagre albumomslagsfilene her. Uansett hvor du plasserer mappen, kommer Squeezebox Server først til å se etter albumomslag i samme bane som der hver lydfil ligger, hvis den ikke finner riktig omslag i albumomslagsmappen. - PL Wszystkie okładki można zapisać w jednym folderze, używając powyższej opcji zmiennych nazw plików. Wprowadź lokalizację plików okładek tutaj. Bez względu na tę lokalizację, jeżeli w folderze okładek nie zostanie znaleziona odpowiednia okładka, program Squeezebox Server będzie szukał okładki, używając ścieżki do pliku audio. - RU Можно хранить все обложки в единой папке, пользуясь вышеописанной функцией изменяемых имен файлов. Введите в это поле расположение файлов обложек. Независимо от данного расположения Squeezebox Server будет по-прежнему выполнять поиск обложек в папке каждого аудиофайла, если в папке обложек не обнаружится необходимых обложек. - SV Du kan välja att spara alla albumomslag i en och samma mapp med hjälp av alternativet för variabla filnamn ovan. Ange sökvägen till omslagsfilerna här. Oavsett sökvägen du anger här kommer Squeezebox Server att söka efter omslagsbilder i samma mapp som var och en av ljudfilerna om inget omslag hittas i mappen för omslagsfiler. + NL Je kunt alle hoesafbeeldingen in één map opslaan via de optie voor variabele bestandsnamen hierboven. Typ hier de locatie van de bestanden met hoesafbeeldingen. Ongeacht wat je hier invult, zal Logitech Media Server ook nog in de map met de audiobestanden kijken, als in de map met hoesafbeeldingen geen hoesje is gevonden. + NO Med alternativet for variable filnavn ovenfor, kan du velge å lagre alle albumomslag i samme mappe. Angi hvor du vil lagre albumomslagsfilene her. Uansett hvor du plasserer mappen, kommer Logitech Media Server først til å se etter albumomslag i samme bane som der hver lydfil ligger, hvis den ikke finner riktig omslag i albumomslagsmappen. + PL Wszystkie okładki można zapisać w jednym folderze, używając powyższej opcji zmiennych nazw plików. Wprowadź lokalizację plików okładek tutaj. Bez względu na tę lokalizację, jeżeli w folderze okładek nie zostanie znaleziona odpowiednia okładka, program Logitech Media Server będzie szukał okładki, używając ścieżki do pliku audio. + RU Можно хранить все обложки в единой папке, пользуясь вышеописанной функцией изменяемых имен файлов. Введите в это поле расположение файлов обложек. Независимо от данного расположения Logitech Media Server будет по-прежнему выполнять поиск обложек в папке каждого аудиофайла, если в папке обложек не обнаружится необходимых обложек. + SV Du kan välja att spara alla albumomslag i en och samma mapp med hjälp av alternativet för variabla filnamn ovan. Ange sökvägen till omslagsfilerna här. Oavsett sökvägen du anger här kommer Logitech Media Server att söka efter omslagsbilder i samma mapp som var och en av ljudfilerna om inget omslag hittas i mappen för omslagsfiler. ZH_CN 您可以利用以上的文件名变量选项,把所有的图象集中存放在一个文件夹内。请在这里输入图象文件所在地点。如果服务器未能在所指定的封面图象文件夹中找到匹配图象,便会在各个音像文件所属的文件夹中寻找匹配的图象。 SETUP_BAD_FILE @@ -6399,7 +6412,7 @@ SETUP_RESCAN CS Znovu prohledat hudební knihovnu DA Gennemsøg musikbibliotek igen DE Musiksammlung erneut durchsuchen - EN Rescan Music Library + EN Rescan Media Library ES Volver a examinar la biblioteca de música FI Tarkista musiikkikirjasto uudelleen FR Analyser la collection musicale @@ -6432,21 +6445,21 @@ SETUP_RESCAN_BUTTON ZH_CN 重新扫描 SETUP_RESCAN_DESC - CS Po klepnutí na Nové hledání Squeezebox Server prohledá vaši knihovnu hudby a přidá novou hudbu nebo aktualizuje skladby, které byly změněny. - DA Klik på Gennemsøg igen for at få Squeezebox Server til at gennemsøge dit musikbibliotek og tilføje ny musik og opdatere ændrede numre. - DE Klicken Sie auf 'Musiksammlung durchsuchen', damit Squeezebox Server die Musiksammlung erneut nach neuen oder veränderten Musikstücken durchsucht. - EN Click Rescan to have Squeezebox Server scan through your music library and add new music or update songs that have changed. - ES Haga clic en Volver a examinar para que Squeezebox Server examine la biblioteca de música y agregue música nueva o actualice canciones que hayan cambiado. - FI Valitse Tarkista uudelleen, jos haluat, että Squeezebox Server tarkistaa musiikkikirjastosi ja lisää uudet kappaleet tai päivittää kappaleet, jotka ovat muuttuneet. - FR Cliquez sur Analyser et Squeezebox Server va à nouveau analyser son contenu. - HE לחץ על 'סריקה חוזרת' כדי להורות ל-Squeezebox Server לסרוק את ספריית המוסיקה שלך ולהוסיף מוסיקה חדשה או לעדכן שירים שהשתנו. + CS Po klepnutí na Nové hledání Logitech Media Server prohledá vaši knihovnu hudby a přidá novou hudbu nebo aktualizuje skladby, které byly změněny. + DA Klik på Gennemsøg igen for at få Logitech Media Server til at gennemsøge dit musikbibliotek og tilføje ny musik og opdatere ændrede numre. + DE Klicken Sie auf 'Musiksammlung durchsuchen', damit Logitech Media Server die Musiksammlung erneut nach neuen oder veränderten Musikstücken durchsucht. + EN Click Rescan to have Logitech Media Server scan through your media library and add new media or update files that have changed. + ES Haga clic en Volver a examinar para que Logitech Media Server examine la biblioteca de música y agregue música nueva o actualice canciones que hayan cambiado. + FI Valitse Tarkista uudelleen, jos haluat, että Logitech Media Server tarkistaa musiikkikirjastosi ja lisää uudet kappaleet tai päivittää kappaleet, jotka ovat muuttuneet. + FR Cliquez sur Analyser et Logitech Media Server va à nouveau analyser son contenu. + HE לחץ על 'סריקה חוזרת' כדי להורות ל-Logitech Media Server לסרוק את ספריית המוסיקה שלך ולהוסיף מוסיקה חדשה או לעדכן שירים שהשתנו. IT Fare clic su Ripeti analisi per analizzare la libreria musicale e aggiungere nuova musica o aggiornare i brani che sono cambiati. - NL Klik op 'Opnieuw scannen' om Squeezebox Server je muziekcollectie te laten scannen en nieuwe muziek toe te voegen, of gewijzigde liedjes bij te werken. - NO Klikk på Søk på nytt for å la Squeezebox Server søke gjennom musikkbiblioteket og legge til ny musikk eller oppdatere spor som endres. - PL Kliknij przycisk Przeszukaj ponownie, aby program Squeezebox Server przeszukał bibliotekę muzyczną i dodał nową muzyką lub zaktualizował utwory, które zostały zmienione. - RU Выберите "Повторное сканирование", чтобы Squeezebox Server выполнил сканирование медиатеки и добавил новую музыку или обновил изменившиеся песни. - SV Klicka på Sök igenom igen om du vill låta Squeezebox Server söka igenom musikmappen och lägga till ny musik eller uppdatera låtar som ändrats. - ZH_CN 点击《重新扫描》将使Squeezebox Server扫瞄音乐库,把新增或已更新的音乐记录在音乐库内。在点击《重新扫描》前点击复选框将使Squeezebox Server把现有的音乐库删除然后重头扫描重建。 + NL Klik op 'Opnieuw scannen' om Logitech Media Server je muziekcollectie te laten scannen en nieuwe muziek toe te voegen, of gewijzigde liedjes bij te werken. + NO Klikk på Søk på nytt for å la Logitech Media Server søke gjennom musikkbiblioteket og legge til ny musikk eller oppdatere spor som endres. + PL Kliknij przycisk Przeszukaj ponownie, aby program Logitech Media Server przeszukał bibliotekę muzyczną i dodał nową muzyką lub zaktualizował utwory, które zostały zmienione. + RU Выберите "Повторное сканирование", чтобы Logitech Media Server выполнил сканирование медиатеки и добавил новую музыку или обновил изменившиеся песни. + SV Klicka på Sök igenom igen om du vill låta Logitech Media Server söka igenom musikmappen och lägga till ny musik eller uppdatera låtar som ändrats. + ZH_CN 点击《重新扫描》将使Logitech Media Server扫瞄音乐库,把新增或已更新的音乐记录在音乐库内。在点击《重新扫描》前点击复选框将使Logitech Media Server把现有的音乐库删除然后重头扫描重建。 SETUP_WIPEDB CS Vyčistit knihovnu a znovu vše prohledat @@ -6469,7 +6482,7 @@ SETUP_STANDARDRESCAN CS Hledat novou a změněnou hudbu DA Søg efter nye og ændrede musikfiler DE Nach neuen und veränderten Musikstücken suchen - EN Look for new and changed music + EN Look for new and changed media files ES Buscar música nueva y cambiada FI Etsi uusia ja muutettuja kappaleita FR Rechercher les morceaux ajoutés ou modifiés @@ -6515,19 +6528,19 @@ SETUP_AUTO_RESCAN SV Upptäck ändringar automatiskt SETUP_AUTO_RESCAN_DESC - CS Squeezebox Server může sledovat vaší složku s hudbou a automaticky detekovat změny. Nové a změněné soubory by se měly ve vaší knihovně objevit během několika minut. - DA Squeezebox Server kan holde øje med musikmapperne og automatisk registrere alle ændringer. Nye og ændrede filer bliver vist i biblioteket i løbet af et par minutter. - DE Squeezebox Server kann den Musikordner durchsuchen und Änderungen automatisch erkennen. Nach einigen Minuten sollten die neuen und geänderten Dateien in der Musiksammlung angezeigt werden. - EN Squeezebox Server can watch your music folder and automatically detect changes. New and changed files should appear in your library within several minutes. - ES Squeezebox Server puede examinar la carpeta de música y detectar los cambios automáticamente. Los archivos nuevos y modificados aparecen en la biblioteca tras varios minutos. - FI Squeezebox Server voi tarkastella musiikkikansiotasi ja havaita muutokset välittömästi. Uusien ja muutettujen tiedostojen pitäisi ilmestyä kirjastoosi muutaman minuutin sisällä. - FR Squeezebox Server peut surveiller vos dossiers de musique et y détecter automatiquement toute modification. Tout fichier ajouté ou modifié s'affiche dans votre collection en l'espace de quelques minutes. - IT Squeezebox Server può monitorare la cartella della musica a rilevare automaticamente le modifiche. I file nuovi o modificati appariranno nella libreria nel giro di qualche minuto. - NL Squeezebox Server kan je muziekmap in de gaten houden en automatisch wijzigingen detecteren. Nieuwe en gewijzigde bestanden moeten binnen een paar minuten in je collectie verschijnen. - NO Squeezebox Server kan holde et øye med musikkmappen, og oppdage endringer automatisk. Nye og endrede filer skal da komme opp i biblioteket innen få minutter. - PL Program Squeezebox Server może monitorować folder z muzyką i automatycznie wykrywać zmiany. Nowe i zmienione pliki powinny pojawiać się w bibliotece w ciągu kilku minut. - RU Squeezebox Server может автоматически обнаруживать изменения в вашей папке "Музыка". Новые и измененные файлы должны отобразиться в вашей медиатеке через несколько минут. - SV Squeezebox Server kan bevaka din musikmapp och automatiskt upptäcka ändringar. Nya och ändrade filer bör visas i ditt bibliotek inom några minuter. + CS Logitech Media Server může sledovat vaší složku s hudbou a automaticky detekovat změny. Nové a změněné soubory by se měly ve vaší knihovně objevit během několika minut. + DA Logitech Media Server kan holde øje med musikmapperne og automatisk registrere alle ændringer. Nye og ændrede filer bliver vist i biblioteket i løbet af et par minutter. + DE Logitech Media Server kann den Musikordner durchsuchen und Änderungen automatisch erkennen. Nach einigen Minuten sollten die neuen und geänderten Dateien in der Musiksammlung angezeigt werden. + EN Logitech Media Server can watch your media folders and automatically detect changes. New and changed files should appear in your library within several minutes. + ES Logitech Media Server puede examinar la carpeta de música y detectar los cambios automáticamente. Los archivos nuevos y modificados aparecen en la biblioteca tras varios minutos. + FI Logitech Media Server voi tarkastella musiikkikansiotasi ja havaita muutokset välittömästi. Uusien ja muutettujen tiedostojen pitäisi ilmestyä kirjastoosi muutaman minuutin sisällä. + FR Logitech Media Server peut surveiller vos dossiers de musique et y détecter automatiquement toute modification. Tout fichier ajouté ou modifié s'affiche dans votre collection en l'espace de quelques minutes. + IT Logitech Media Server può monitorare la cartella della musica a rilevare automaticamente le modifiche. I file nuovi o modificati appariranno nella libreria nel giro di qualche minuto. + NL Logitech Media Server kan je muziekmap in de gaten houden en automatisch wijzigingen detecteren. Nieuwe en gewijzigde bestanden moeten binnen een paar minuten in je collectie verschijnen. + NO Logitech Media Server kan holde et øye med musikkmappen, og oppdage endringer automatisk. Nye og endrede filer skal da komme opp i biblioteket innen få minutter. + PL Program Logitech Media Server może monitorować folder z muzyką i automatycznie wykrywać zmiany. Nowe i zmienione pliki powinny pojawiać się w bibliotece w ciągu kilku minut. + RU Logitech Media Server может автоматически обнаруживать изменения в вашей папке "Музыка". Новые и измененные файлы должны отобразиться в вашей медиатеке через несколько минут. + SV Logitech Media Server kan bevaka din musikmapp och automatiskt upptäcka ändringar. Nya och ändrade filer bör visas i ditt bibliotek inom några minuter. SETUP_AUTO_RESCAN_ENABLE CS Aktivováno, automatické sledování změn @@ -6548,7 +6561,7 @@ SETUP_AUTO_RESCAN_DISABLE CS Deaktivováno, pro novou hudbu použít ruční vyhledávání DA Deaktiveret – søg efter ny musik manuelt DE Deaktiviert, manuell nach neuer Musik suchen - EN Disabled, manually scan for new music + EN Disabled, manually scan for new media files ES Desactivado, examinar música nueva manualmente FI Poistettu käytöstä. Hae uutta musiikkia manuaalisesti. FR Désactivé, analyse manuelle des nouveaux morceaux @@ -6590,29 +6603,29 @@ SETUP_AUTO_RESCAN_STAT_INTERVAL_DESC SV För att upptäcka ändringar i fjärrnätverksresurser eller i vissa operativsystem som saknar inbyggt stöd för upptäckt av ändringar, måste filerna avsökas efter ändringar med regelbundna intervall. Välj ett tidsintervall i minuter för kontrollen. Standardvärdet är 10 minuter. RESCANNING - CS Squeezebox Server nyní znovu prohledává vaši hudební knihovnu. - DA Squeezebox Server gennemsøger nu dit musikbibliotek. - DE Squeezebox Server durchsucht Ihre Musiksammlung. - EN Squeezebox Server is now rescanning your Music Library. - ES Squeezebox Server está volviendo a examinar la biblioteca de música. - FI Squeezebox Server tarkistaa musiikkikirjastoasi uudelleen. - FR Squeezebox Server analyse maintenant la collection musicale. + CS Logitech Media Server nyní znovu prohledává vaši hudební knihovnu. + DA Logitech Media Server gennemsøger nu dit musikbibliotek. + DE Logitech Media Server durchsucht Ihre Musiksammlung. + EN Logitech Media Server is now rescanning your Media Library. + ES Logitech Media Server está volviendo a examinar la biblioteca de música. + FI Logitech Media Server tarkistaa musiikkikirjastoasi uudelleen. + FR Logitech Media Server analyse maintenant la collection musicale. HE השרת מבצע סריקה חוזרת של ספריית המוסיקה שלך. - IT Squeezebox Server sta analizzando nuovamente la libreria musicale. + IT Logitech Media Server sta analizzando nuovamente la libreria musicale. JA サーバーは音楽ライブラリーを再スキャンしています。 - NL Squeezebox Server is nu je muziekcollectie opnieuw aan het scannen. - NO Squeezebox Server søker gjennom musikkbiblioteket. - PL Program Squeezebox Server ponownie przeszukuje bibliotekę muzyki. - PT Squeezebox Server está a analisar o arquivo de músicas. - RU Squeezebox Server повторно сканирует медиатеку. - SV Squeezebox Server söker nu igenom ditt musikbibliotek igen. + NL Logitech Media Server is nu je muziekcollectie opnieuw aan het scannen. + NO Logitech Media Server søker gjennom musikkbiblioteket. + PL Program Logitech Media Server ponownie przeszukuje bibliotekę muzyki. + PT Logitech Media Server está a analisar o arquivo de músicas. + RU Logitech Media Server повторно сканирует медиатеку. + SV Logitech Media Server söker nu igenom ditt musikbibliotek igen. ZH_CN 服务器正在重新扫描您的音乐库。 RESCANNING_SHORT CS Nové prohledávání knihovny hudby... DA Gennemsøger musikbibliotek igen... DE Musiksammlung wird durchsucht ... - EN Rescanning Music Library... + EN Rescanning Media Library... ES Volviendo a examinar la biblioteca de música... FI Musiikkikirjasto tarkistetaan uudelleen... FR Analyse en cours... @@ -6644,7 +6657,7 @@ SCAN_ABORTED CS Prohledávání bylo přerušeno. Chcete-li mít plný přístup ke své knihovně hudby, musíte spustit nové prohledávání. DA Gennemsøgningen er afbrudt. Du skal foretage gennemsøgningen en gang til for at få fuld adgang til musikbiblioteket. DE Der Scan wurde abgebrochen. Beachten Sie, dass Sie die Suche wiederholen müssen, um vollständigen Zugriff auf Ihre Musiksammlung zu erhalten. - EN The scan has been aborted. Please note that you'll have to re-run a scan to get full access to your music library. + EN The scan has been aborted. Please note that you'll have to re-run a scan to get full access to your media library. ES Se ha cancelado el examen. Tenga en cuenta que para tener acceso completo a la biblioteca de música deberá volver a ejecutar un examen. FI Tarkistus keskeytettiin. Huomaa, että tarkistus täytyy suorittaa uudelleen, jotta voit käyttää musiikkikirjastoa täysin. FR L'analyse a été interrompue. Notez que vous devrez exécuter une nouvelle fois une analyse afin d'obtenir l'accès complet à votre collection musicale. @@ -6696,19 +6709,19 @@ SETUP_SKIN_DESC ZH_CN 您可以从如下的选项选择一个外壳作为网界面。 SETUP_SKIN_OK - CS Aby vaše změny začaly platit, zavřete prosím okno Squeezebox Server a znovu jej zaveďte. - DA Du skal lukke Squeezebox Server-vinduet og åbne det igen for at anvende ændringerne. - DE Schließen Sie Squeezebox Server und öffnen Sie es erneut, um die Änderungen anzuwenden. - EN To apply your changes please close the Squeezebox Server window and reload it. - ES Para aplicar los cambios, cierre la ventana de Squeezebox Server y vuelva a cargarlo. - FI Jos haluat ottaa tekemäsi muutokset käyttöön, sulje Squeezebox Server -ikkuna ja lataa se uudelleen. - FR Pour appliquer les modifications, fermez la fenêtre du Squeezebox Server et démarrez à nouveau le serveur. - IT Per applicare le modifiche, chiudere la finestra di Squeezebox Server e aprirla di nuovo. - NL Als je je wijzigingen wilt toepassen, sluit je het venster van Squeezebox Server en laad je het opnieuw. - NO Lukk Squeezebox Server-vinduet og åpne det på nytt for å ta i bruk endringene. - PL Aby zastosować zmiany, zamknij okno programu Squeezebox Server i załaduj go ponownie. - RU Закройте окно Squeezebox Server и перезапустите его, чтобы изменения вступили в силу. - SV Verkställ ändringarna genom att stänga Squeezebox Server-fönstret och öppna det igen. + CS Aby vaše změny začaly platit, zavřete prosím okno Logitech Media Server a znovu jej zaveďte. + DA Du skal lukke Logitech Media Server-vinduet og åbne det igen for at anvende ændringerne. + DE Schließen Sie Logitech Media Server und öffnen Sie es erneut, um die Änderungen anzuwenden. + EN To apply your changes please close the Logitech Media Server window and reload it. + ES Para aplicar los cambios, cierre la ventana de Logitech Media Server y vuelva a cargarlo. + FI Jos haluat ottaa tekemäsi muutokset käyttöön, sulje Logitech Media Server -ikkuna ja lataa se uudelleen. + FR Pour appliquer les modifications, fermez la fenêtre du Logitech Media Server et démarrez à nouveau le serveur. + IT Per applicare le modifiche, chiudere la finestra di Logitech Media Server e aprirla di nuovo. + NL Als je je wijzigingen wilt toepassen, sluit je het venster van Logitech Media Server en laad je het opnieuw. + NO Lukk Logitech Media Server-vinduet og åpne det på nytt for å ta i bruk endringene. + PL Aby zastosować zmiany, zamknij okno programu Logitech Media Server i załaduj go ponownie. + RU Закройте окно Logitech Media Server и перезапустите его, чтобы изменения вступили в силу. + SV Verkställ ändringarna genom att stänga Logitech Media Server-fönstret och öppna det igen. SETUP_PLUGINS CS Zásuvné moduly (pluginy) @@ -6744,20 +6757,20 @@ SETUP_REFRESHRATE ZH_CN 浏览器刷新时间 SETUP_REFRESHRATE_DESC - CS Nastavte dobu obnovení prohlížeče v sekundách. Při přehrávání skladby se Squeezebox Server obnoví před koncem skladby, pokud je hodnota menší než tato hodnota. (Výchozí nastavení je 30, minimum je 2) + CS Nastavte dobu obnovení prohlížeče v sekundách. Při přehrávání skladby se Logitech Media Server obnoví před koncem skladby, pokud je hodnota menší než tato hodnota. (Výchozí nastavení je 30, minimum je 2) DA Angiv hvor mange sekunder der skal gå mellem hver opdatering af siden i browseren. Når du hører et nummer, bliver siden opdateret når nummeret er ved at være slut hvis værdien er mindre end nummerets længde. Standard er 30, minimum er 2. - DE Legen Sie die Zeit zwischen Browser-Aktualisierungen in Sekunden fest. Während der Wiedergabe eines Titels legt Squeezebox Server die Aktualisierung zum Ende eines Titels fest, falls dieses näher als dieser Wert liegt. (Standardwert ist 30, Minimalwert 2) - EN Set the time between browser reloads in seconds. While playing a song, Squeezebox Server will set the refresh near a song end if it is less than this value. (Default is 30, minimum is 2) - ES Establezca en segundos el tiempo de espera entre las recargas del navegador. Mientras se reproduce una canción, Squeezebox Server establecerá la actualización cerca del final de una canción si es inferior a este valor. (Valor predeterminado: 30, mínimo: 2) - FI Määritä selaimen päivitysten välillä kuluva aika sekunteina. Kappaleen toiston aikana Squeezebox Server päivittää selaimen lähellä kappaleen loppua, jos jäljellä oleva aika on lyhyempi kuin tämä arvo (Oletus on 30, vähimmäisaika 2). - FR Définissez le délai entre chaque actualisation du navigateur. Lors de la lecture d'un morceau, le Squeezebox Server force l'actualisation vers la fin du morceau, si le nombre de secondes restantes est inférieur au nombre défini. La valeur par défaut est 30 et la valeur minimale 2. + DE Legen Sie die Zeit zwischen Browser-Aktualisierungen in Sekunden fest. Während der Wiedergabe eines Titels legt Logitech Media Server die Aktualisierung zum Ende eines Titels fest, falls dieses näher als dieser Wert liegt. (Standardwert ist 30, Minimalwert 2) + EN Set the time between browser reloads in seconds. While playing a song, Logitech Media Server will set the refresh near a song end if it is less than this value. (Default is 30, minimum is 2) + ES Establezca en segundos el tiempo de espera entre las recargas del navegador. Mientras se reproduce una canción, Logitech Media Server establecerá la actualización cerca del final de una canción si es inferior a este valor. (Valor predeterminado: 30, mínimo: 2) + FI Määritä selaimen päivitysten välillä kuluva aika sekunteina. Kappaleen toiston aikana Logitech Media Server päivittää selaimen lähellä kappaleen loppua, jos jäljellä oleva aika on lyhyempi kuin tämä arvo (Oletus on 30, vähimmäisaika 2). + FR Définissez le délai entre chaque actualisation du navigateur. Lors de la lecture d'un morceau, le Logitech Media Server force l'actualisation vers la fin du morceau, si le nombre de secondes restantes est inférieur au nombre défini. La valeur par défaut est 30 et la valeur minimale 2. HE הגדר את פרק הזמן בין טעינות חוזרות של הדפדפן, בשניות. במהלך השמעה של שיר, השרת יגדיר את הרענון סמוך לסוף השיר, אם הוא אינו עולה על ערך זה. (ברירת המחדל היא 30, הערך המינימלי 2) - IT Imposta l'intervallo di aggiornamento del browser in secondi. Se la durata del brano è inferiore al valore impostato, Squeezebox Server esegue l'aggiornamento verso la fine del brano. Il valore predefinito è 30, quello minimo 2. + IT Imposta l'intervallo di aggiornamento del browser in secondi. Se la durata del brano è inferiore al valore impostato, Logitech Media Server esegue l'aggiornamento verso la fine del brano. Il valore predefinito è 30, quello minimo 2. JA ブラウザーが更新する時間を秒数で入力してください。曲を再生中の場合には、曲の最後に更新します。(工場出荷時は30秒、最小は2秒) - NL Stel de tijd in seconden in waarna de browser de pagina moet vernieuwen. Squeezebox Server zal de pagina bij het einde van een liedje vernieuwen als dit minder is dan deze waarde. (Standaardwaarde is 30, minimumwaarde is 2 seconden.) - NO Angi tiden mellom hver oppdatering i nettleseren i sekunder. Når en sang spilles, foretar Squeezebox Server en oppdatering mot slutten av sangen, selv om gjenværende tid er mindre enn angitt. (Standardverdi er 30, minimumsverdi er 2) - PL Ustaw czas w sekundach do ponownego załadowania przeglądarki. Podczas odtwarzania utworu program Squeezebox Server ustawi odświeżenie pod koniec utworu, jeżeli czas będzie krótszy od tej wartości (ustawienie domyślne to 30, minimalne to 2). - RU Задайте время между перезагрузками браузера в секундах. При воспроизведении Squeezebox Server будет делать обновление в конце песни, если ее длительность меньше этого значения. (По умолчанию — 30, минимум — 2.) + NL Stel de tijd in seconden in waarna de browser de pagina moet vernieuwen. Logitech Media Server zal de pagina bij het einde van een liedje vernieuwen als dit minder is dan deze waarde. (Standaardwaarde is 30, minimumwaarde is 2 seconden.) + NO Angi tiden mellom hver oppdatering i nettleseren i sekunder. Når en sang spilles, foretar Logitech Media Server en oppdatering mot slutten av sangen, selv om gjenværende tid er mindre enn angitt. (Standardverdi er 30, minimumsverdi er 2) + PL Ustaw czas w sekundach do ponownego załadowania przeglądarki. Podczas odtwarzania utworu program Logitech Media Server ustawi odświeżenie pod koniec utworu, jeżeli czas będzie krótszy od tej wartości (ustawienie domyślne to 30, minimalne to 2). + RU Задайте время между перезагрузками браузера в секундах. При воспроизведении Logitech Media Server будет делать обновление в конце песни, если ее длительность меньше этого значения. (По умолчанию — 30, минимум — 2.) SV Ange (i sekunder) med vilka tidsintervall webbläsaren ska uppdatera sidan. Standardvärdet är 30 sekunder och minimivärdet är 2 sekunder. När en låt spelas upp sker uppdateringen mot slutet av låten om den är kortare än värdet som anges här. ZH_CN 设置浏览器刷新的间隔时间。当播放歌曲时,如果设的值少于歌曲的长度服务器将在歌曲末端附近设置刷新。(缺省为30,极小值为2) @@ -6815,19 +6828,19 @@ SETUP_DOWNLOAD_ARTWORK SV Autokomplettera albumomslag SETUP_DOWNLOAD_ARTWORK_DESC - CS Squeezebox Server se může v průběhu prohledávání knihovny pokusit o doplnění chybějících obalů alba vašich hudebních souborů. V průběhu tohoto procesu budou za účelem nalezení odpovídajícího obalu alba odeslány údaje o interpretovi a albu na server mysqueezebox.com. Upozornění: tento proces může výrazně zpomalit vyhledávání.

              Obaly alba jsou poskytovány službou Last.fm. - DA Squeezebox Server kan forsøge at hente manglende albumcovere til dine musikfiler mens dit bibliotek scannes. I denne proces sendes der oplysninger om kunstnere og album til mysqueezebox.com for at finde matchende albumcovere. Bemærk at denne proces kan gøre scanningen betydeligt langsommere.

              Albumcovere leveres af Last.fm. - DE Der Squeezebox Server kann beim Durchsuchen Ihrer Bibliothek fehlende Plattenhüllen für Ihre Musikdateien ergänzen. Bei diesem Vorgang werden Informationen zu Interpret und Album an mysqueezebox.com gesendet, um dort nach passenden Plattenhüllen zu suchen. Beachten Sie, dass dieser Prozess den Suchvorgang erheblich verlangsamen kann.

              Plattenhüllen werden von Last.fm zur Verfügung gestellt. - EN Squeezebox Server can try to complete missing artwork for your music files while it's scanning your library. This process will send artist and album information to mysqueezebox.com to discover matching cover art. Please note that this process can slow down scanning considerably.

              Artwork is provided by Last.fm. - ES Squeezebox Server puede intentar completar las carátulas que falten en los archivos de música mientras examina la biblioteca. Este proceso enviará información de álbum y artista a mysqueezebox.com para descubrir cubiertas que coincidan. Tenga en cuenta que este proceso puede ralentizar considerablemente el examen.

              Las carátulas las proporciona Last.fm. + CS Logitech Media Server se může v průběhu prohledávání knihovny pokusit o doplnění chybějících obalů alba vašich hudebních souborů. V průběhu tohoto procesu budou za účelem nalezení odpovídajícího obalu alba odeslány údaje o interpretovi a albu na server mysqueezebox.com. Upozornění: tento proces může výrazně zpomalit vyhledávání.

              Obaly alba jsou poskytovány službou Last.fm. + DA Logitech Media Server kan forsøge at hente manglende albumcovere til dine musikfiler mens dit bibliotek scannes. I denne proces sendes der oplysninger om kunstnere og album til mysqueezebox.com for at finde matchende albumcovere. Bemærk at denne proces kan gøre scanningen betydeligt langsommere.

              Albumcovere leveres af Last.fm. + DE Der Logitech Media Server kann beim Durchsuchen Ihrer Bibliothek fehlende Plattenhüllen für Ihre Musikdateien ergänzen. Bei diesem Vorgang werden Informationen zu Interpret und Album an mysqueezebox.com gesendet, um dort nach passenden Plattenhüllen zu suchen. Beachten Sie, dass dieser Prozess den Suchvorgang erheblich verlangsamen kann.

              Plattenhüllen werden von Last.fm zur Verfügung gestellt. + EN Logitech Media Server can try to complete missing artwork for your music files while it's scanning your library. This process will send artist and album information to mysqueezebox.com to discover matching cover art. Please note that this process can slow down scanning considerably.

              Artwork is provided by Last.fm. + ES Logitech Media Server puede intentar completar las carátulas que falten en los archivos de música mientras examina la biblioteca. Este proceso enviará información de álbum y artista a mysqueezebox.com para descubrir cubiertas que coincidan. Tenga en cuenta que este proceso puede ralentizar considerablemente el examen.

              Las carátulas las proporciona Last.fm. FI Squeezebox-palvelin voi yrittää viimeistellä musiikkitiedostojen puuttuvan kansitaiteen, kun kirjastoa tarkistetaan. Esittäjän ja albumin tiedot lähetetään osoitteeseen mysqueezebox.com, josta täsmäävää kansitaidetta etsitään. Ota huomioon, että tämä saattaa hidastaa tarkistusta huomattavasti.

              Kansitaiteen tarjoaa Last.fm. - FR Squeezebox Server peut essayer de rechercher les pochettes manquantes de vos fichiers musicaux pendant qu'il analyse votre bibliothèque. Pour ce faire, il envoie les informations des artistes et des albums à mysqueezebox.com pour trouver les pochettes correspondantes. Veuillez noter que ce processus peut considérablement ralentir l'analyse.

              Les pochettes sont fournies par Last.fm. - IT È possibile tentare di inserire le copertine mancanti per i file musicali mediante Squeezebox Server durante l'analisi della libreria. Tale processo prevede l'invio di informazioni su album e artisti a mysqueezebox.com per individuare le copertine corrispondenti. Il processo può rallentare notevolmente l'analisi.

              Le copertine vengono fornite da Last.fm. - NL Squeezebox Server kan ontbrekende hoesafbeeldingen voor je opzoeken tijdens het scannen van je collectie. Hierbij worden gegevens van de artiest en het album verzonden naar mysqueezebox.com om te zien of er hoesafbeeldingen beschikbaar zijn. Houd er wel rekening mee dat dit het scanproces aanzienlijk kan vertragen.

              Hoesafbeeldingen worden aangeboden door Last.fm. - NO Squeezebox Server kan forsøke å sette inn manglende omslag for musikkfilene dine under søk i biblioteket. Denne prosessen sender artist- og albuminformasjon til mysqueezebox.com for å finne fram til riktig albumomslag. Prosessen kan føre til at søket tar betraktelig lengre tid.

              Det er Last.fm som leverer albumomslag. - PL Program Squeezebox Server może spróbować uzupełnić brakujące okładki do plików muzycznych podczas przeszukiwania biblioteki. W ramach tego procesu informacje o wykonawcy i albumie zostaną przesłane do witryny mysqueezebox.com w celu wykrycia pasującej okładki. Uwaga: proces ten może znacząco spowolnić przeszukiwanie biblioteki.

              Okładki udostępnia serwis Last.fm. - RU Squeezebox Server может попробовать найти недостающие обложки для музыкальных файлов в процессе сканирования медиатеки. При этом сведения об исполнителе и альбоме будут отправляться на mysqueezebox.com, чтобы найти соответствующую обложку. Нужно учитывать, что этот процесс может значительно замедлить сканирование.

              Обложки предоставляются сайтом Last.fm. - SV Squeezebox Server kan försöka komplettera albumomslag som saknas för musikfilerna medan ditt bibliotek genomsöks. I den här processen skickas information om artisten och albumet till mysqueezebox.com för att hitta ett matchande albumomslag. Observera att den här processen kan göra att sökningen går betydligt långsammare.

              Albumomslagen tillhandahålls av Last.fm. + FR Logitech Media Server peut essayer de rechercher les pochettes manquantes de vos fichiers musicaux pendant qu'il analyse votre bibliothèque. Pour ce faire, il envoie les informations des artistes et des albums à mysqueezebox.com pour trouver les pochettes correspondantes. Veuillez noter que ce processus peut considérablement ralentir l'analyse.

              Les pochettes sont fournies par Last.fm. + IT È possibile tentare di inserire le copertine mancanti per i file musicali mediante Logitech Media Server durante l'analisi della libreria. Tale processo prevede l'invio di informazioni su album e artisti a mysqueezebox.com per individuare le copertine corrispondenti. Il processo può rallentare notevolmente l'analisi.

              Le copertine vengono fornite da Last.fm. + NL Logitech Media Server kan ontbrekende hoesafbeeldingen voor je opzoeken tijdens het scannen van je collectie. Hierbij worden gegevens van de artiest en het album verzonden naar mysqueezebox.com om te zien of er hoesafbeeldingen beschikbaar zijn. Houd er wel rekening mee dat dit het scanproces aanzienlijk kan vertragen.

              Hoesafbeeldingen worden aangeboden door Last.fm. + NO Logitech Media Server kan forsøke å sette inn manglende omslag for musikkfilene dine under søk i biblioteket. Denne prosessen sender artist- og albuminformasjon til mysqueezebox.com for å finne fram til riktig albumomslag. Prosessen kan føre til at søket tar betraktelig lengre tid.

              Det er Last.fm som leverer albumomslag. + PL Program Logitech Media Server może spróbować uzupełnić brakujące okładki do plików muzycznych podczas przeszukiwania biblioteki. W ramach tego procesu informacje o wykonawcy i albumie zostaną przesłane do witryny mysqueezebox.com w celu wykrycia pasującej okładki. Uwaga: proces ten może znacząco spowolnić przeszukiwanie biblioteki.

              Okładki udostępnia serwis Last.fm. + RU Logitech Media Server может попробовать найти недостающие обложки для музыкальных файлов в процессе сканирования медиатеки. При этом сведения об исполнителе и альбоме будут отправляться на mysqueezebox.com, чтобы найти соответствующую обложку. Нужно учитывать, что этот процесс может значительно замедлить сканирование.

              Обложки предоставляются сайтом Last.fm. + SV Logitech Media Server kan försöka komplettera albumomslag som saknas för musikfilerna medan ditt bibliotek genomsöks. I den här processen skickas information om artisten och albumet till mysqueezebox.com för att hitta ett matchande albumomslag. Observera att den här processen kan göra att sökningen går betydligt långsammare.

              Albumomslagen tillhandahålls av Last.fm. SETUP_DOWNLOAD_ARTWORK_ON CS Stáhnout obal alba (zkušebně) @@ -6916,7 +6929,7 @@ SETUP_HTTPPORT SETUP_HTTPPORT_DESC CS Můžete změnit číslo portu, který se používá pro přístup k serveru z webového prohlížeče. (Výchozí hodnota je 9000.) - DA Du kan ændre hvilket portnummer der skal bruges til at åbne Squeezebox Servers brugerflade i en webbrowser. Standard er 9000. + DA Du kan ændre hvilket portnummer der skal bruges til at åbne Logitech Media Servers brugerflade i en webbrowser. Standard er 9000. DE Sie können die Anschlussnummer ändern, die vom Browser für den Server-Zugriff verwendet wird (Standard ist 9000). EN You can change the port number that is used to access the server from a web browser. (The default is 9000.) ES Se puede cambiar el número de puerto que se usa para acceder al servidor con un navegador Web (el predeterminado es el 9000). @@ -7055,19 +7068,19 @@ SETUP_RATINGIMPLEMENTATION_DESC SV Lagring av betyg som ska användas när betygsättning visas eller lagras LOCAL_RATING_STORAGE - CS Databáze Squeezebox Server - DA Squeezebox Server-database - DE Squeezebox Server-Datenbank - EN Squeezebox Server Database - ES Base de datos de Squeezebox Server - FI Squeezebox Serverin tietokanta - FR Base de données Squeezebox Server - IT Database Squeezebox Server - NL Database van Squeezebox Server - NO Squeezebox Server-database - PL Baza danych programu Squeezebox Server - RU База данных Squeezebox Server - SV Squeezebox Server-databas + CS Databáze Logitech Media Server + DA Logitech Media Server-database + DE Logitech Media Server-Datenbank + EN Logitech Media Server Database + ES Base de datos de Logitech Media Server + FI Logitech Media Serverin tietokanta + FR Base de données Logitech Media Server + IT Database Logitech Media Server + NL Database van Logitech Media Server + NO Logitech Media Server-database + PL Baza danych programu Logitech Media Server + RU База данных Logitech Media Server + SV Logitech Media Server-databas SETUP_CHECKVERSION CS Aktualizace softwaru @@ -7089,23 +7102,23 @@ SETUP_CHECKVERSION ZH_CN 软件更新 SETUP_CHECKVERSION_DESC - CS Squeezebox Server se každý den může automaticky připojit k mysqueezebox.com a zkontrolovat, zda není k dispozici aktualizovaná verze softwaru. Pokud je, na webovém rozhraní Squeezebox Server se zobrazí zpráva. - DA Squeezebox Server kan automatisk etablere forbindelse til mysqueezebox.com hver dag og tjekke om der er udgivet en opdateret version af programmet. Hvis der er, vises en meddelelse i Squeezebox Servers webbaserede brugerflade. - DE Squeezebox Server kann automatisch jeden Tag Verbindung mit mysqueezebox.com aufnehmen und prüfen, ob eine neue Softwareversion verfügbar ist. Ist dies der Fall, wird dies in der Web-Benutzeroberfläche von Squeezebox Server gemeldet. - EN Squeezebox Server can automatically connect to mysqueezebox.com every day and check to see if an updated version of the software is available. If it is, then a message will appear in Squeezebox Server's web interface. - ES Squeezebox Server se puede conectar automáticamente a mysqueezebox.com cada día y comprobar si hay disponible una versión actualizada del software. Si la hay, aparecerá un mensaje en la interfaz Web de Squeezebox Server. - FI Squeezebox Server voi muodostaa automaattisesti yhteyden sivustoon mysqueezebox.com joka päivä ja tarkistaa, onko ohjelmistosta tarjolla päivitettyä versiota. Jos päivitetty versio on tarjolla, Squeezebox Serverin internet-liittymään tulee ilmoitus siitä. + CS Logitech Media Server se každý den může automaticky připojit k mysqueezebox.com a zkontrolovat, zda není k dispozici aktualizovaná verze softwaru. Pokud je, na webovém rozhraní Logitech Media Server se zobrazí zpráva. + DA Logitech Media Server kan automatisk etablere forbindelse til mysqueezebox.com hver dag og tjekke om der er udgivet en opdateret version af programmet. Hvis der er, vises en meddelelse i Logitech Media Servers webbaserede brugerflade. + DE Logitech Media Server kann automatisch jeden Tag Verbindung mit mysqueezebox.com aufnehmen und prüfen, ob eine neue Softwareversion verfügbar ist. Ist dies der Fall, wird dies in der Web-Benutzeroberfläche von Logitech Media Server gemeldet. + EN Logitech Media Server can automatically connect to mysqueezebox.com every day and check to see if an updated version of the software is available. If it is, then a message will appear in Logitech Media Server's web interface. + ES Logitech Media Server se puede conectar automáticamente a mysqueezebox.com cada día y comprobar si hay disponible una versión actualizada del software. Si la hay, aparecerá un mensaje en la interfaz Web de Logitech Media Server. + FI Logitech Media Server voi muodostaa automaattisesti yhteyden sivustoon mysqueezebox.com joka päivä ja tarkistaa, onko ohjelmistosta tarjolla päivitettyä versiota. Jos päivitetty versio on tarjolla, Logitech Media Serverin internet-liittymään tulee ilmoitus siitä. FR Le serveur peut se connecter tous les jours automatiquement à mysqueezebox.com pour vérifier la disponibilité d'une nouvelle version du logiciel. Le cas échéant, un message dans l'interface Web indique qu'une nouvelle version est disponible. - HE השרת יכול להתחבר באופן אוטומטי לכתובת mysqueezebox.com בכל יום ולבדוק אם קיימת גרסה מעודכנת של התוכנה. אם קיימת, תופיע הודעה בממשק האינטרנט של Squeezebox Server. - IT Squeezebox Server può collegarsi automaticamente al sito mysqueezebox.com ogni giorno e verificare se è disponibile una versione aggiornata del software. In caso affermativo, viene visualizzato un messaggio nell'interfaccia Web di Squeezebox Server. + HE השרת יכול להתחבר באופן אוטומטי לכתובת mysqueezebox.com בכל יום ולבדוק אם קיימת גרסה מעודכנת של התוכנה. אם קיימת, תופיע הודעה בממשק האינטרנט של Logitech Media Server. + IT Logitech Media Server può collegarsi automaticamente al sito mysqueezebox.com ogni giorno e verificare se è disponibile una versione aggiornata del software. In caso affermativo, viene visualizzato un messaggio nell'interfaccia Web di Logitech Media Server. JA サーバーソフトウェアは、毎日mysqueezebox.comに接続してアップデートを確認します。アップデート バージョンがある場合には、その旨メッセージが出ます。 - NL Squeezebox Server kan elke dag automatisch verbinding maken met 'mysqueezebox.com' om te kijken of er een nieuwere versie van de software beschikbaar is. Als dit zo is, verschijnt er een bericht in de webinterface van Squeezebox Server. - NO Squeezebox Server kan automatisk sjekke mysqueezebox.com hver dag etter en nyere versjon av programvaren. Hvis det finnes en ny versjon, får du beskjed i nettgrensesnittet. - PL Program Squeezebox Server może codziennie automatycznie łączyć się z witryną mysqueezebox.com w celu sprawdzenia dostępności zaktualizowanej wersji oprogramowania. Jeżeli będzie ono dostępne, w interfejsie internetowym programu Squeezebox Server zostanie wyświetlony komunikat. + NL Logitech Media Server kan elke dag automatisch verbinding maken met 'mysqueezebox.com' om te kijken of er een nieuwere versie van de software beschikbaar is. Als dit zo is, verschijnt er een bericht in de webinterface van Logitech Media Server. + NO Logitech Media Server kan automatisk sjekke mysqueezebox.com hver dag etter en nyere versjon av programvaren. Hvis det finnes en ny versjon, får du beskjed i nettgrensesnittet. + PL Program Logitech Media Server może codziennie automatycznie łączyć się z witryną mysqueezebox.com w celu sprawdzenia dostępności zaktualizowanej wersji oprogramowania. Jeżeli będzie ono dostępne, w interfejsie internetowym programu Logitech Media Server zostanie wyświetlony komunikat. PT O servidor poderá ligar-se automaticamente a mysqueezebox.com todos os dias e verificar se está disponível alguma versão nova do software. Se for o caso, aparecerá uma mensagem na interface Web do Slim. - RU Squeezebox Server может каждый день автоматически подключаться к сайту mysqueezebox.com и проверять наличие обновленных версий программы. При обнаружении новой версии в веб-интерфейсе Squeezebox Server появится соответствующее сообщение. - SV Squeezebox Server kan automatiskt kopplas upp mot mysqueezebox.com varje dag för att kontrollera om en uppdaterad version av programvaran finns tillgänglig. Om det finns uppdateringar visas ett meddelande i webbgränssnittet. - ZH_CN 服务器能够每天自动地连接到mysqueezebox.com检查是否有新的软件版本可供使用。如果新的软件版本的确存在,有关信息将出现在Squeezebox Server的网界面。 + RU Logitech Media Server может каждый день автоматически подключаться к сайту mysqueezebox.com и проверять наличие обновленных версий программы. При обнаружении новой версии в веб-интерфейсе Logitech Media Server появится соответствующее сообщение. + SV Logitech Media Server kan automatiskt kopplas upp mot mysqueezebox.com varje dag för att kontrollera om en uppdaterad version av programvaran finns tillgänglig. Om det finns uppdateringar visas ett meddelande i webbgränssnittet. + ZH_CN 服务器能够每天自动地连接到mysqueezebox.com检查是否有新的软件版本可供使用。如果新的软件版本的确存在,有关信息将出现在Logitech Media Server的网界面。 SETUP_CHECKVERSION_1 CS Automaticky kontrolovat aktualizace softwaru @@ -7161,19 +7174,19 @@ SETUP_AUTO_DOWNLOAD SV Automatisk nedladdning SETUP_AUTO_DOWNLOAD_DESC - CS Automaticky stahovat aktualizace Squeezebox Server, pokud jsou k dispozici. Po dokončení stahování budete vyzváni k instalaci aktualizace. - DA Hent automatisk opdateringer til Squeezebox Server når de udkommer. Når opdateringerne er overført til computeren, bliver du bedt om at installere dem - DE Verfügbare Updates für Squeezebox Server werden automatisch heruntergeladen. Nach dem Herunterladen werden Sie zur Installation des Updates aufgefordert. - EN Automatically download Squeezebox Server updates when they're available. You'll then be prompted to install the update as soon as the download has finished. - ES Descargar actualizaciones de Squeezebox Server automáticamente cuando estén disponibles. Se le indicará que instale la actualización en cuanto haya acabado la descarga. - FI Lataa Squeezebox Serverin päivitykset automaattisesti, kun ne ovat saatavilla. Ohjelma kehottaa asentamaan päivityksen heti, kun se on ladattu. - FR Télécharger automatiquement les mises à jour Squeezebox Server disponibles. Vous serez ensuite invité à installer la mises à jour à la fin du téléchargement. - IT Scarica automaticamente gli aggiornamenti a Squeezebox Server quando sono disponibili. Al termine del download verrà chiesto di installare l'aggiornamento. - NL Updates voor Squeezebox Server automatisch downloaden wanneer deze beschikbaar zijn. Je wordt dan gevraagd de updates te installeren zodra het downloaden voltooid is. - NO Last ned Squeezebox Server-oppdateringer automatisk når de blir tilgjengelige. Du blir bedt om å installere oppdateringen når nedlastingen er fullført. - PL Automatyczne pobieraj aktualizacje programu Squeezebox Server, gdy będą dostępne. Po zakończeniu pobierania zostanie wyświetlony monit o zainstalowanie aktualizacji. - RU Автоматически загружать доступные обновления Squeezebox Server. После окончания загрузки обновления появится предложение установить его. - SV Ladda ner Squeezebox Server-uppdateringar automatiskt när de är tillgängliga. Du ombeds installera uppdateringen när nedladdningen har slutförts. + CS Automaticky stahovat aktualizace Logitech Media Server, pokud jsou k dispozici. Po dokončení stahování budete vyzváni k instalaci aktualizace. + DA Hent automatisk opdateringer til Logitech Media Server når de udkommer. Når opdateringerne er overført til computeren, bliver du bedt om at installere dem + DE Verfügbare Updates für Logitech Media Server werden automatisch heruntergeladen. Nach dem Herunterladen werden Sie zur Installation des Updates aufgefordert. + EN Automatically download Logitech Media Server updates when they're available. You'll then be prompted to install the update as soon as the download has finished. + ES Descargar actualizaciones de Logitech Media Server automáticamente cuando estén disponibles. Se le indicará que instale la actualización en cuanto haya acabado la descarga. + FI Lataa Logitech Media Serverin päivitykset automaattisesti, kun ne ovat saatavilla. Ohjelma kehottaa asentamaan päivityksen heti, kun se on ladattu. + FR Télécharger automatiquement les mises à jour Logitech Media Server disponibles. Vous serez ensuite invité à installer la mises à jour à la fin du téléchargement. + IT Scarica automaticamente gli aggiornamenti a Logitech Media Server quando sono disponibili. Al termine del download verrà chiesto di installare l'aggiornamento. + NL Updates voor Logitech Media Server automatisch downloaden wanneer deze beschikbaar zijn. Je wordt dan gevraagd de updates te installeren zodra het downloaden voltooid is. + NO Last ned Logitech Media Server-oppdateringer automatisk når de blir tilgjengelige. Du blir bedt om å installere oppdateringen når nedlastingen er fullført. + PL Automatyczne pobieraj aktualizacje programu Logitech Media Server, gdy będą dostępne. Po zakończeniu pobierania zostanie wyświetlony monit o zainstalowanie aktualizacji. + RU Автоматически загружать доступные обновления Logitech Media Server. После окончания загрузки обновления появится предложение установить его. + SV Ladda ner Logitech Media Server-uppdateringar automatiskt när de är tillgängliga. Du ombeds installera uppdateringen när nedladdningen har slutförts. SETUP_AUTO_DOWNLOAD_0 CS Neprovádět automatické stahování aktualizací @@ -7543,7 +7556,7 @@ SETUP_SEARCHSUBSTRING_DESC CS Pokud hledáte hudbu, můžete pomocí Squeezebox hledat odpovídající položky obsahující slova, která začínají stejnými písmeny jako hledaný řetězec, nebo obsahující slova, která mají hledaný řetězec kdekoliv ve slově. Například hledání začátku slov "RAIN" najde položky se slovem "RAINBOW". Hledání uvnitř slov vrátí také položku obsahující slovo "TRAIN". DA Når du søger efter musik, kan Squeezebox enten finde elementer med ord som begynder på de samme bogstaver som din søgestreng, eller elementer med ord som indeholder søgestrengen et på et vilkårligt sted. For eksempel vil søgestrengen ved søgning efter begyndelse af ord finde elementer med ordet "RAINBOW". Søgning efter vilkårligt sted vil også returnere elementer som indeholder ordet "TRAIN". DE Beim Suchen können Sie Squeezebox anweisen, den gewünschten Ausdruck nur am Wortanfang zu suchen, oder auch als beliebigen Teil eines Wortes- Beispiel: Wenn Sie den Wortanfang nach 'RAIN' durchsuchen, werden Einträge mit 'RAINBOW' oder auch 'TRAIN' gefunden. - EN When you search for music, you can have Squeezebox find matches for items that contain words that begin with the same letters in your search string or contain words that have the search string anywhere in the word. For example, searching the beginnings of words for "RAIN" in would find items with the word "RAINBOW". Searching within words would also return item containing the word "TRAIN". + EN When you search for media files, you can have your server find matches for items that contain words that begin with the same letters in your search string or contain words that have the search string anywhere in the word. For example, searching the beginnings of words for "RAIN" in would find items with the word "RAINBOW". Searching within words would also return item containing the word "TRAIN". ES Cuando se busca música, se puede hacer que Squeezebox encuentre coincidencias con elementos que contengan palabras que empiecen por las mismas letras que la cadena de búsqueda o que contengan palabras que tengan la cadena de búsqueda en cualquier parte de la palabra. Por ejemplo, buscar principios de palabras por "RAIN" encontraría elementos con la palabra "RAINBOW". Buscar dentro de palabras también encontraría elementos con la palabra "TRAIN". FI Kun suoritat musiikkihakuja, voit määrittää Squeezeboxin etsimään vastaavuuksia kahdella tavalla. Se voi joko etsiä sanoja, jotka alkavat samoilla kirjaimilla kuin hakumerkkijono, tai se voi etsiä sanoja, jotka sisältävät hakumerkkijonon jossakin kohtaa sanaa. Jos se esimerkiksi hakee sanoja, joiden alussa on "RAIN", se löytäisi esimerkiksi sanan "RAINBOW". Jos se suorittaisi haun sanojen sisällä, se löytäisi myös sanan "TRAIN". FR Lors d'une recherche dans la bibliothèque, Squeezebox peut afficher comme résultat les éléments contenant les mots spécifiés ou seulement les éléments dont le nom débute par les mots spécifiés. Par exemple, une recherche sur RAIN affichera les morceaux contenant le mot RAINBOW si vous sélectionnez la recherche par début de mot. Si vous sélectionnez l'option de recherche à l'intérieur des mots, TRAIN sera également renvoyé comme résultat. @@ -7682,22 +7695,22 @@ SETUP_PERSISTPLAYLISTS ZH_CN 维护Client播放表 SETUP_PERSISTPLAYLISTS_DESC - CS Squeezebox Server si může pamatovat poslední seznam skladeb, které byly právě přehrávány při spuštění aplikace. - DA Squeezebox Server kan huske den sidst benyttede afspilningsliste når programmet genstartes. - DE Squeezebox Server kann die letzte Wiedergabeliste speichern, die beim Starten der Anwendung abgespielt wurde. - EN Squeezebox Server can remember the last playlist of songs that were Now Playing when the application starts. - ES Cuando se inicia Squeezebox Server, el reproductor puede recordar la última lista de reproducción de canciones que se estaba reproduciendo. - FI Kun Squeezebox Server käynnistyy, se muistaa viimeksi soitetun soittoluettelon. + CS Logitech Media Server si může pamatovat poslední seznam skladeb, které byly právě přehrávány při spuštění aplikace. + DA Logitech Media Server kan huske den sidst benyttede afspilningsliste når programmet genstartes. + DE Logitech Media Server kann die letzte Wiedergabeliste speichern, die beim Starten der Anwendung abgespielt wurde. + EN Logitech Media Server can remember the last playlist of songs that were Now Playing when the application starts. + ES Cuando se inicia Logitech Media Server, el reproductor puede recordar la última lista de reproducción de canciones que se estaba reproduciendo. + FI Kun Logitech Media Server käynnistyy, se muistaa viimeksi soitetun soittoluettelon. FR Le serveur peut conserver le contenu de la dernière liste de lecture de la platine lorsqu'il est redémarré. HE השרת יכול לזכור את רשימת ההשמעה האחרונה של שירים שהיו מוגדרים תחת 'מושמע כעת' עם הפעלת השרת. - IT All'avvio, Squeezebox Server è in grado di ricordare l'ultima playlist di brani riprodotti. + IT All'avvio, Logitech Media Server è in grado di ricordare l'ultima playlist di brani riprodotti. JA サーバーソフトウェアは、最後に再生していたプレイリストを記憶しておくことができます。 - NL Squeezebox Server kan de laatste playlist voor 'Speelt nu' onthouden en deze laden wanneer de server start. - NO Squeezebox Server kan huske siste spilleliste som var i Spilles nå når programmet starter. - PL Program Squeezebox Server może wyświetlić ostanie listy odtwarzania utworów w kategorii Teraz odtwarzane po uruchomieniu aplikacji. + NL Logitech Media Server kan de laatste playlist voor 'Speelt nu' onthouden en deze laden wanneer de server start. + NO Logitech Media Server kan huske siste spilleliste som var i Spilles nå når programmet starter. + PL Program Logitech Media Server może wyświetlić ostanie listy odtwarzania utworów w kategorii Teraz odtwarzane po uruchomieniu aplikacji. PT O servidor pode manter a playlist de músicas actual quando é re-iniciado. - RU Squeezebox Server может запоминать последний плей-лист песен, воспроизводившихся при запуске приложения. - SV Squeezebox Server kan komma ihåg den senast spelade aktuella spellistan tills nästa gång programmet körs. + RU Logitech Media Server может запоминать последний плей-лист песен, воспроизводившихся при запуске приложения. + SV Logitech Media Server kan komma ihåg den senast spelade aktuella spellistan tills nästa gång programmet körs. ZH_CN 服务器可以记住在起动前最后使用的播放表。 SETUP_PERSISTPLAYLISTS_1 @@ -7758,22 +7771,22 @@ SETUP_RESHUFFLEONREPEAT ZH_CN 在重复后再度随机抽样 SETUP_RESHUFFLEONREPEAT_DESC - CS Pokud je to požadováno, Squeezebox Server může opět opět náhodně seřadit seznamy skladeb po každém úplném přehrání seznamu skladeb. + CS Pokud je to požadováno, Logitech Media Server může opět opět náhodně seřadit seznamy skladeb po každém úplném přehrání seznamu skladeb. DA Numrene på afspilningslisten kan blandes i en ny vilkårlig rækkefølge når alle numrene er afspillet og afspilningen starter forfra. - DE Squeezebox Server kann nach dem kompletten Durchspielen einer zufälligen Wiedergabeliste diese erneut mischen. - EN Squeezebox Server can reshuffle shuffled playlists after each complete pass through the list, if desired. - ES Squeezebox Server puede establecer un nuevo orden aleatorio de las listas de reproducción aleatorias después de cada pase completo por la lista, si así se desea. - FI Jos haluat, Squeezebox Server voi sekoittaa sekoitetut soittoluettelot uudelleen aina, kun soittoluettelo on kuunneltu loppuun. + DE Logitech Media Server kann nach dem kompletten Durchspielen einer zufälligen Wiedergabeliste diese erneut mischen. + EN Logitech Media Server can reshuffle shuffled playlists after each complete pass through the list, if desired. + ES Logitech Media Server puede establecer un nuevo orden aleatorio de las listas de reproducción aleatorias después de cada pase completo por la lista, si así se desea. + FI Jos haluat, Logitech Media Server voi sekoittaa sekoitetut soittoluettelot uudelleen aina, kun soittoluettelo on kuunneltu loppuun. FR Le serveur peut mélanger de nouveau la liste de lecture à chaque répétition. HE השרת יכול לסדר מחדש בסדר אקראי רשימות השמעה שכבר מסודרות בסדר אקראי לאחר כל מעבר מלא על הרשימה, אם אתה מעוניין בכך. - IT Se lo si desidera, Squeezebox Server può ripetere la riproduzione casuale delle playlist dopo la riproduzione di ciascuna di esse. + IT Se lo si desidera, Logitech Media Server può ripetere la riproduzione casuale delle playlist dopo la riproduzione di ciascuna di esse. JA サーバーソフトウェアは、リピート時に、再度ランダムをかけるよう選択することができます。 - NL Squeezebox Server kan de volgorde van liedjes in een geshuffelde playlist telkens nadat de lijst afgespeeld is, opnieuw veranderen. - NO Squeezebox Server kan omrokkere spillelister på nytt etter hver gjennomspilling av en liste. - PL Program Squeezebox Server może w razie potrzeby po każdym pełnym przejściu ponownie sortować listy posortowane losowo. + NL Logitech Media Server kan de volgorde van liedjes in een geshuffelde playlist telkens nadat de lijst afgespeeld is, opnieuw veranderen. + NO Logitech Media Server kan omrokkere spillelister på nytt etter hver gjennomspilling av en liste. + PL Program Logitech Media Server może w razie potrzeby po każdym pełnym przejściu ponownie sortować listy posortowane losowo. PT O servidor pode re-misturar a lista de músicas no final dela, se necessário. - RU Squeezebox Server может повторно перемешивать плей-листы после воспроизведения всех песен списка. - SV Squeezebox Server kan blanda om blandade spellistor varje gång hela listan gåtts igenom. + RU Logitech Media Server может повторно перемешивать плей-листы после воспроизведения всех песен списка. + SV Logitech Media Server kan blanda om blandade spellistor varje gång hela listan gåtts igenom. ZH_CN 如有必要,服务器可以把随机抽样后的播放表在每一次播放时再度抽样决定次序。 SETUP_RESHUFFLEONREPEAT_0 @@ -7941,20 +7954,20 @@ SETUP_SPLITLIST SV Avgränsare för flera objekt i taggar SETUP_SPLITLIST_DESC - CS Squeezebox Server může z tagů ve vašich hudebních souborech získat více interpretů, názvů alb a žánrů. Pokud ve vašich tagách najde některé ze slov nebo znaků uvedených níže, vytvoří pro každou položku jednotlivé výpisy. Pokud například do seznamu níže vložíte středník, skladba s tagem interpreta "J. S. Bach;Michael Tilson Thomas" se objeví v oblasti interpretů pro "J. S. Bach" i "Michael Tilson Thomas". Po změně tohoto nastavení se spustí prohledávání vaší hudební knihovny. - DA Squeezebox Server kan udtrække flere kunstnere, albumtitler og genre fra mærkerne i dine musikfiler. Hvis Squeezebox Server finder nogle af de ord eller symboler nedenunder, vil der blive oprettet individuelle oversiger for hvert element. Hvis du for eksempel har indtastet et semikolon i listen nedenunder, vil numre med kunstnermærke "J. S. Bach;Michael Tilson Thomas" medføre at der oprettes to kunstnere, "J. S. Bach" og "Michael Tilson Thomas". Ændring af denne indstilling medfører at dit musikbibliotek bliver genindlæst. - DE Squeezebox Server kann mehrere Interpreten, Albumtitel und Stilrichtungen in den Tags von Musikdateien erkennen. Findet Squeezebox Server folgende Wörter oder Zeichen in den Tags, wird für jeden Eintrag eine andere Liste erstellt. Beispiel: Wenn Sie einen Strichpunkt als Trennzeichen definieren, wird ein Titel mit dem Interpreten-Tag 'J. S. Bach;Michael Tilson Thomas' sowohl unter 'J. S. Bach' als auch 'Michael Tilson Thomas' aufgelistet. Wenn Sie diese Einstellung ändern, wird die Musiksammlung erneut durchsucht. - EN Squeezebox Server can extract multiple artist, album titles and genres from the tags inside your music files. If it finds any of the words or characters below in your tags, it will create individual listings for each item. For example, if you put a semicolon in the list below, a song with an artist tag of "J. S. Bach;Michael Tilson Thomas" will appear in the artists area for both "J. S. Bach" and "Michael Tilson Thomas". Changing this setting will start a rescan of your music library. - ES Squeezebox Server puede extraer múltiples artistas, títulos de álbumes y géneros de las etiquetas dentro de los archivos de música. Si Squeezebox Server encuentra cualquiera de las palabras o caracteres siguientes en las etiquetas, creará listas individuales para cada elemento. Por ejemplo, si se coloca un punto y coma en la lista siguiente, una canción con una etiqueta de artista de "J. S. Bach;Michael Tilson Thomas" aparecerá en el área de artistas para ambos, "J. S. Bach" y "Michael Tilson Thomas". Si se cambia esta opción, se iniciará un nuevo examen de la biblioteca de música. - FI Squeezebox Server voi purkaa useita artisteja, levyn nimiä ja genrejä musiikkitiedostojen sisällä olevista tunnisteista. Jos palvelin löytää tunnisteista alla olevia sanoja tai merkkejä, se luo erillisen luettelon kullekin kohteelle. Jos esimerkiksi laitat puolipisteen alla olevaan luetteloon, kappale jonka artistitunniste on "J. S. Bach;Michael Tilson Thomas" tulee näkyviin artistikohtaan sekä J. S. Bachin että Michael Tilson Thomasin kohdalla. Jos tätä asetusta muutetaan, musiikkikirjasto tarkistetaan uudelleen. - FR Squeezebox Server peut extraire plusieurs noms d'artistes, titres d'albums ou genres des repères ID3 de vos fichiers musicaux. Si il détecte l'un des caractères ci-dessous dans les repères ID3, il créera une entrée différente pour chaque élément. Par exemple, si le caractère point-virgule est défini comme séparateur, un fichier contenant le repère ID3 "J. S. Bach;Michael Tilson Thomas" sera listé à la fois sous "J. S. Bach" et sous "Michael Tilson Thomas". SI vous modifiez ce réglage, votre dossier de musique sera à nouveau analysé. - HE Squeezebox Server יכול לחלץ מבצעים, שמות אלבומים וסגנונות מרובים מהתגים הכלולים בקובצי המוסיקה שלך. אם Squeezebox Server מאתר בתגים מילים או תווים מהרשימה שלהלן, הוא ייצור רשימות נפרדות עבור כל פריט. לדוגמה, אם אתה מציב נקודה-פסיק ברשימה שלהלן, שיר עם תג מבצע של "J. S. Bach;Michael Tilson Thomas" יופיע באזור המבצעים הן עבור "J. S. Bach" והן עבור "Michael Tilson Thomas". שינוי הגדרה זו יגרום להפעלת סריקה חוזרת של ספריית המוסיקה. - IT Squeezebox Server può estrarre più artisti, titoli di album o generi dai tag inseriti all'interno dei file musicali. Se trova nei tag qualsiasi parola o carattere indicato sotto, crea un elenco separato per ognuno di essi. Per esempio, inserendo un punto e virgola nella lista sottostante, un brano che ha come tag dell'artista Gino Paoli;Ornella Vanoni, apparirà nell'elenco artisti sia come Gino Paoli che come Ornella Vanoni. Cambiando questa impostazione viene eseguita un'analisi della libreria musicale. - NL Squeezebox Server kan meerdere artiesten, albumtitels en genres uit de tags in je muziekbestanden extraheren. Als de server een van de onderstaande woorden of tekens in de tags vindt, wordt voor elk item een aparte ingang in een lijst gemaakt. Als je bijvoorbeeld een puntkomma in de onderstaande lijst zet, verschijnt een liedje met de tag 'J. S. Bach;Michael Tilson Thomas' zowel bij 'J. S. Bach' als 'Michael Tilson Thomas'. Wanneer je deze instelling wijzigt, wordt je muziekcollectie opnieuw gescand. - NO Squeezebox Server kan hente flere artister, albumtitler og sjangere fra etikettene i musikkfilene dine. Hvis den finner noen av ordene eller tegnene nedenfor i etikettene, oppretter den separate lister for hvert element. Hvis du for eksempel skriver et semikolon i listen nedenfor, kommer en sang med artistetiketten «J. S. Bach;Michael Tilson Thomas» opp under både «J. S. Bach» og «Michael Tilson Thomas». Hvis du endrer denne innstillingen, blir musikkbiblioteket gjennomsøkt på nytt. - PL Program Squeezebox Server może wyodrębnić wykonawców, tytuły albumów i gatunki ze znaczników plików muzycznych. Jeżeli program Squeezebox Server znajdzie poniższe słowa lub znaki w znacznikach, utworzy listy dla każdego elementu. Na przykład umieszczenie średnika na liście poniżej, spowoduje, że utwór ze znacznikiem wykonawcy „J. S. Bach;Michael Tilson Thomas” pojawi się w obszarze wykonawców dla „J. S. Bach” i „Michael Tilson Thomas”. Zmiana tego ustawienia spowoduje ponowne przeszukanie biblioteki muzyki. - RU Squeezebox Server может извлекать из тегов музыкальных файлов имена исполнителей, названия альбомов и жанры, даже если их несколько. Если в тегах обнаружатся какие-либо из нижеперечисленных слов или символов, для каждого элемента будут созданы отдельные записи. Например, если в списке ниже поставить точку с запятой, песня с тегом исполнителя "И. С. Бах; Майкл Тилсон Томас" появится в области исполнителей и под именем "И. С. Бах", и под именем "Майкл Тилсон Томас". При изменении этой настройки будет запущено повторное сканирование медиатеки. - SV Squeezebox Server har stöd för taggar med flera artistnamn, albumtitlar eller genrer för samma låt. Om ett eller flera av orden eller tecknen i taggarna hittas, skapas självständiga poster för varje objekt. Om du t.ex. använder semikolon i listan nedan visas en låt med taggen J. S. Bach;Michael Tilson Thomas i artistområdet för både J.S. Bach och Michael Tilson Thomas. Om du ändrar den här inställningen söks musikbiblioteket igenom på nytt. + CS Logitech Media Server může z tagů ve vašich hudebních souborech získat více interpretů, názvů alb a žánrů. Pokud ve vašich tagách najde některé ze slov nebo znaků uvedených níže, vytvoří pro každou položku jednotlivé výpisy. Pokud například do seznamu níže vložíte středník, skladba s tagem interpreta "J. S. Bach;Michael Tilson Thomas" se objeví v oblasti interpretů pro "J. S. Bach" i "Michael Tilson Thomas". Po změně tohoto nastavení se spustí prohledávání vaší hudební knihovny. + DA Logitech Media Server kan udtrække flere kunstnere, albumtitler og genre fra mærkerne i dine musikfiler. Hvis Logitech Media Server finder nogle af de ord eller symboler nedenunder, vil der blive oprettet individuelle oversiger for hvert element. Hvis du for eksempel har indtastet et semikolon i listen nedenunder, vil numre med kunstnermærke "J. S. Bach;Michael Tilson Thomas" medføre at der oprettes to kunstnere, "J. S. Bach" og "Michael Tilson Thomas". Ændring af denne indstilling medfører at dit musikbibliotek bliver genindlæst. + DE Logitech Media Server kann mehrere Interpreten, Albumtitel und Stilrichtungen in den Tags von Musikdateien erkennen. Findet Logitech Media Server folgende Wörter oder Zeichen in den Tags, wird für jeden Eintrag eine andere Liste erstellt. Beispiel: Wenn Sie einen Strichpunkt als Trennzeichen definieren, wird ein Titel mit dem Interpreten-Tag 'J. S. Bach;Michael Tilson Thomas' sowohl unter 'J. S. Bach' als auch 'Michael Tilson Thomas' aufgelistet. Wenn Sie diese Einstellung ändern, wird die Musiksammlung erneut durchsucht. + EN Logitech Media Server can extract multiple artist, album titles and genres from the tags inside your music files. If it finds any of the words or characters below in your tags, it will create individual listings for each item. For example, if you put a semicolon in the list below, a song with an artist tag of "J. S. Bach;Michael Tilson Thomas" will appear in the artists area for both "J. S. Bach" and "Michael Tilson Thomas". Changing this setting will start a rescan of your music library. + ES Logitech Media Server puede extraer múltiples artistas, títulos de álbumes y géneros de las etiquetas dentro de los archivos de música. Si Logitech Media Server encuentra cualquiera de las palabras o caracteres siguientes en las etiquetas, creará listas individuales para cada elemento. Por ejemplo, si se coloca un punto y coma en la lista siguiente, una canción con una etiqueta de artista de "J. S. Bach;Michael Tilson Thomas" aparecerá en el área de artistas para ambos, "J. S. Bach" y "Michael Tilson Thomas". Si se cambia esta opción, se iniciará un nuevo examen de la biblioteca de música. + FI Logitech Media Server voi purkaa useita artisteja, levyn nimiä ja genrejä musiikkitiedostojen sisällä olevista tunnisteista. Jos palvelin löytää tunnisteista alla olevia sanoja tai merkkejä, se luo erillisen luettelon kullekin kohteelle. Jos esimerkiksi laitat puolipisteen alla olevaan luetteloon, kappale jonka artistitunniste on "J. S. Bach;Michael Tilson Thomas" tulee näkyviin artistikohtaan sekä J. S. Bachin että Michael Tilson Thomasin kohdalla. Jos tätä asetusta muutetaan, musiikkikirjasto tarkistetaan uudelleen. + FR Logitech Media Server peut extraire plusieurs noms d'artistes, titres d'albums ou genres des repères ID3 de vos fichiers musicaux. Si il détecte l'un des caractères ci-dessous dans les repères ID3, il créera une entrée différente pour chaque élément. Par exemple, si le caractère point-virgule est défini comme séparateur, un fichier contenant le repère ID3 "J. S. Bach;Michael Tilson Thomas" sera listé à la fois sous "J. S. Bach" et sous "Michael Tilson Thomas". SI vous modifiez ce réglage, votre dossier de musique sera à nouveau analysé. + HE Logitech Media Server יכול לחלץ מבצעים, שמות אלבומים וסגנונות מרובים מהתגים הכלולים בקובצי המוסיקה שלך. אם Logitech Media Server מאתר בתגים מילים או תווים מהרשימה שלהלן, הוא ייצור רשימות נפרדות עבור כל פריט. לדוגמה, אם אתה מציב נקודה-פסיק ברשימה שלהלן, שיר עם תג מבצע של "J. S. Bach;Michael Tilson Thomas" יופיע באזור המבצעים הן עבור "J. S. Bach" והן עבור "Michael Tilson Thomas". שינוי הגדרה זו יגרום להפעלת סריקה חוזרת של ספריית המוסיקה. + IT Logitech Media Server può estrarre più artisti, titoli di album o generi dai tag inseriti all'interno dei file musicali. Se trova nei tag qualsiasi parola o carattere indicato sotto, crea un elenco separato per ognuno di essi. Per esempio, inserendo un punto e virgola nella lista sottostante, un brano che ha come tag dell'artista Gino Paoli;Ornella Vanoni, apparirà nell'elenco artisti sia come Gino Paoli che come Ornella Vanoni. Cambiando questa impostazione viene eseguita un'analisi della libreria musicale. + NL Logitech Media Server kan meerdere artiesten, albumtitels en genres uit de tags in je muziekbestanden extraheren. Als de server een van de onderstaande woorden of tekens in de tags vindt, wordt voor elk item een aparte ingang in een lijst gemaakt. Als je bijvoorbeeld een puntkomma in de onderstaande lijst zet, verschijnt een liedje met de tag 'J. S. Bach;Michael Tilson Thomas' zowel bij 'J. S. Bach' als 'Michael Tilson Thomas'. Wanneer je deze instelling wijzigt, wordt je muziekcollectie opnieuw gescand. + NO Logitech Media Server kan hente flere artister, albumtitler og sjangere fra etikettene i musikkfilene dine. Hvis den finner noen av ordene eller tegnene nedenfor i etikettene, oppretter den separate lister for hvert element. Hvis du for eksempel skriver et semikolon i listen nedenfor, kommer en sang med artistetiketten «J. S. Bach;Michael Tilson Thomas» opp under både «J. S. Bach» og «Michael Tilson Thomas». Hvis du endrer denne innstillingen, blir musikkbiblioteket gjennomsøkt på nytt. + PL Program Logitech Media Server może wyodrębnić wykonawców, tytuły albumów i gatunki ze znaczników plików muzycznych. Jeżeli program Logitech Media Server znajdzie poniższe słowa lub znaki w znacznikach, utworzy listy dla każdego elementu. Na przykład umieszczenie średnika na liście poniżej, spowoduje, że utwór ze znacznikiem wykonawcy „J. S. Bach;Michael Tilson Thomas” pojawi się w obszarze wykonawców dla „J. S. Bach” i „Michael Tilson Thomas”. Zmiana tego ustawienia spowoduje ponowne przeszukanie biblioteki muzyki. + RU Logitech Media Server может извлекать из тегов музыкальных файлов имена исполнителей, названия альбомов и жанры, даже если их несколько. Если в тегах обнаружатся какие-либо из нижеперечисленных слов или символов, для каждого элемента будут созданы отдельные записи. Например, если в списке ниже поставить точку с запятой, песня с тегом исполнителя "И. С. Бах; Майкл Тилсон Томас" появится в области исполнителей и под именем "И. С. Бах", и под именем "Майкл Тилсон Томас". При изменении этой настройки будет запущено повторное сканирование медиатеки. + SV Logitech Media Server har stöd för taggar med flera artistnamn, albumtitlar eller genrer för samma låt. Om ett eller flera av orden eller tecknen i taggarna hittas, skapas självständiga poster för varje objekt. Om du t.ex. använder semikolon i listan nedan visas en låt med taggen J. S. Bach;Michael Tilson Thomas i artistområdet för både J.S. Bach och Michael Tilson Thomas. Om du ändrar den här inställningen söks musikbiblioteket igenom på nytt. SETUP_BROWSEAGELIMIT CS Omezení nové hudby @@ -8067,20 +8080,20 @@ SETUP_DISABLESTATISTICS ZH_CN 库存统计 SETUP_DISABLESTATISTICS_DESC - CS Když se objeví první stránka Squeezebox Server, aplikace prohledá vaši knihovnu hudby a zjišťuje statistiku vaší knihovny, kterou poté zobrazí na první stránce. Můžete tuto funkci zakázat, což zkrátí dobu, po kterou se poprvé otevírá webové rozhraní, zvláště u velké knihovny hudby. - DA Når Squeezebox Servers hovedmenu vises, bliver dit musikbibliotek gennemsøgt, og der laves en statistik som vises på forsiden. Du kan deaktivere denne funktion, og det vil forkorte den tid det tager at åbne den webbaserede brugerflade, navnlig hvis musikbiblioteket er stort. - DE Beim Anzeigen der Squeezebox Server-Startseite wird die ganze Musiksammlung durchsucht, um den Bestand anzeigen zu können. Sie können diese Funktion deaktivieren, wodurch die Zeit zum Öffnen der Web-Benutzeroberfläche verringert wird, besonders wenn die Musiksammlung sehr groß ist. - EN When the Squeezebox Server front page comes up, it scans your music library to figure out your library statistics and displays them on the front page. You can choose to disable this behavior, which will shorten the time it takes to initially open up the web interface, especially with a large music library. - ES Cuando se muestra la pantalla inicial de Squeezebox Server, éste examina la biblioteca de música para obtener estadísticas de la biblioteca y mostrarlas en la página inicial. Se puede optar por desactivar este comportamiento, lo que acortará el tiempo necesario para abrir la interfaz Web, especialmente con una biblioteca de música de gran tamaño. - FI Kun Squeezebox Serverin etusivu tulee näyttöön, Squeezebox Server tarkistaa musiikkikirjaston selvittääkseen kirjaston tilastot. Nämä tilastotiedot näytetään etusivulla. Halutessasi voit poistaa toiminnon käytöstä. Tämä lyhentää aikaa, joka internet-liittymän avaamiseen kuluu, erityisesti jos musiikkikirjasto on suuri. - FR Lorsque la page d'accueil du Squeezebox Server apparaît, celui-ci analyse votre collection musicale afin d'afficher des statistiques. Vous pouvez désactiver ce comportement, ce qui réduira le temps nécessaire à l'affichage de la page d'accueil, surtout si la taille de la collection est importante. - HE עם הופעת הדף הראשי של Squeezebox Server, השרת סורק את ספריית המוסיקה שלך לחישוב הנתונים הסטטיסטיים אודות הספרייה ולהצגתם בדף הראשי. באפשרותך לבחור להשבית התנהגות זו כדי לקצר את משך הזמן הנחוץ לפתיחת ממשק האינטרנט, במיוחד אם ספריית המוסיקה גדולה. - IT All'apertura della pagina iniziale di Squeezebox Server viene analizzata la libreria musicale e ne vengono calcolate e visualizzate le statistiche. È possibile scegliere di disattivare questa funzionalità, in modo da velocizzare i tempi iniziali di apertura dell'interfaccia Web, in particolare se si dispone di una libreria musicale estesa. - NL Wanneer de webpagina van Squeezebox Server verschijnt, wordt je muziekcollectie gescand om je collectiestatistieken op te halen. Deze worden vervolgens op de webpagina weergegeven. Als je dit uitschakelt, wordt de webinterface sneller geopend, vooral wanneer de muziekcollectie erg groot is. - NO Når forsiden til Squeezebox Server kommer opp, søker Squeezebox Server gjennom musikkbiblioteket ditt, og viser så en del statistikk for det. Du kan velge å deaktivere dette. Det korter ned tiden det tar å åpne nettgrensesnittet, særlig hvis du har et stort musikkbibliotek. - PL Po wyświetleniu strony głównej programu Squeezebox Server zostanie przeszukana biblioteka muzyczna w celu określenia statystyki biblioteki i wyświetlenia jej na stronie głównej. Funkcję tę można wyłączyć, co skraca czas początkowego otwarcia interfejsu internetowego, szczególnie w przypadku dużej biblioteki muzyki. - RU При появлении первой страницы Squeezebox Server производится сканирование медиатеки, в ходе которого выполняется сбор статистики для отображения на данной странице. Можно отключить это поведение, тем самым сократив время первичного открытия веб-интерфейса (особенно это касается больших медиатек). - SV När Squeezebox Servers startsida visas söks musikbiblioteket igenom och statistiken visas på startsidan. Om du avaktiverar den här funktionen öppnas webbgränssnittet snabbare, särskilt om du har ett stort musikbibliotek. + CS Když se objeví první stránka Logitech Media Server, aplikace prohledá vaši knihovnu hudby a zjišťuje statistiku vaší knihovny, kterou poté zobrazí na první stránce. Můžete tuto funkci zakázat, což zkrátí dobu, po kterou se poprvé otevírá webové rozhraní, zvláště u velké knihovny hudby. + DA Når Logitech Media Servers hovedmenu vises, bliver dit musikbibliotek gennemsøgt, og der laves en statistik som vises på forsiden. Du kan deaktivere denne funktion, og det vil forkorte den tid det tager at åbne den webbaserede brugerflade, navnlig hvis musikbiblioteket er stort. + DE Beim Anzeigen der Logitech Media Server-Startseite wird die ganze Musiksammlung durchsucht, um den Bestand anzeigen zu können. Sie können diese Funktion deaktivieren, wodurch die Zeit zum Öffnen der Web-Benutzeroberfläche verringert wird, besonders wenn die Musiksammlung sehr groß ist. + EN When the Logitech Media Server front page comes up, it scans your media library to figure out your library statistics and displays them on the front page. You can choose to disable this behavior, which will shorten the time it takes to initially open up the web interface, especially with a large library. + ES Cuando se muestra la pantalla inicial de Logitech Media Server, éste examina la biblioteca de música para obtener estadísticas de la biblioteca y mostrarlas en la página inicial. Se puede optar por desactivar este comportamiento, lo que acortará el tiempo necesario para abrir la interfaz Web, especialmente con una biblioteca de música de gran tamaño. + FI Kun Logitech Media Serverin etusivu tulee näyttöön, Logitech Media Server tarkistaa musiikkikirjaston selvittääkseen kirjaston tilastot. Nämä tilastotiedot näytetään etusivulla. Halutessasi voit poistaa toiminnon käytöstä. Tämä lyhentää aikaa, joka internet-liittymän avaamiseen kuluu, erityisesti jos musiikkikirjasto on suuri. + FR Lorsque la page d'accueil du Logitech Media Server apparaît, celui-ci analyse votre collection musicale afin d'afficher des statistiques. Vous pouvez désactiver ce comportement, ce qui réduira le temps nécessaire à l'affichage de la page d'accueil, surtout si la taille de la collection est importante. + HE עם הופעת הדף הראשי של Logitech Media Server, השרת סורק את ספריית המוסיקה שלך לחישוב הנתונים הסטטיסטיים אודות הספרייה ולהצגתם בדף הראשי. באפשרותך לבחור להשבית התנהגות זו כדי לקצר את משך הזמן הנחוץ לפתיחת ממשק האינטרנט, במיוחד אם ספריית המוסיקה גדולה. + IT All'apertura della pagina iniziale di Logitech Media Server viene analizzata la libreria musicale e ne vengono calcolate e visualizzate le statistiche. È possibile scegliere di disattivare questa funzionalità, in modo da velocizzare i tempi iniziali di apertura dell'interfaccia Web, in particolare se si dispone di una libreria musicale estesa. + NL Wanneer de webpagina van Logitech Media Server verschijnt, wordt je muziekcollectie gescand om je collectiestatistieken op te halen. Deze worden vervolgens op de webpagina weergegeven. Als je dit uitschakelt, wordt de webinterface sneller geopend, vooral wanneer de muziekcollectie erg groot is. + NO Når forsiden til Logitech Media Server kommer opp, søker Logitech Media Server gjennom musikkbiblioteket ditt, og viser så en del statistikk for det. Du kan velge å deaktivere dette. Det korter ned tiden det tar å åpne nettgrensesnittet, særlig hvis du har et stort musikkbibliotek. + PL Po wyświetleniu strony głównej programu Logitech Media Server zostanie przeszukana biblioteka muzyczna w celu określenia statystyki biblioteki i wyświetlenia jej na stronie głównej. Funkcję tę można wyłączyć, co skraca czas początkowego otwarcia interfejsu internetowego, szczególnie w przypadku dużej biblioteki muzyki. + RU При появлении первой страницы Logitech Media Server производится сканирование медиатеки, в ходе которого выполняется сбор статистики для отображения на данной странице. Можно отключить это поведение, тем самым сократив время первичного открытия веб-интерфейса (особенно это касается больших медиатек). + SV När Logitech Media Servers startsida visas söks musikbiblioteket igenom och statistiken visas på startsidan. Om du avaktiverar den här funktionen öppnas webbgränssnittet snabbare, särskilt om du har ett stort musikbibliotek. SETUP_DISABLE_STATISTICS CS Vypnout statistiku knihovny @@ -8408,22 +8421,22 @@ SETUP_WEBPROXY ZH_CN 网代理 SETUP_WEBPROXY_DESC - CS Můžete specifikovat IP adresu a port pro HTTP/Web proxy server, které se použijí při připojení Squeezebox Server k serverům mimo vaši místní síť. Používejte formát xx.xx.xx.xx:yyyy, kde xx.xx.xx.xx je IP adresa proxy serveru a yyyy číslo portu. Pokud nepoužíváte HTTP web proxy server, ponechte toto pole prázdné.. - DA Du kan specificere IP-adresse og portnummer til en HTTP/Web-proxy som Squeezebox Server skal anvende når der tilsluttes servere udenfor dit lokale netværk. Anvend formatet xx.xx.xx.xx:yyyy, hvor xx.xx.xx.xx er proxyens IP-adresse og yyyy er proxyserverens portnummer. Lad feltet være tomt hvis du ikke ønsker at anvende en HTTP-proxy. - DE Sie können die IP-Adresse und den Anschluss eines HTTP/Web-Proxys definieren, den Squeezebox Server verwenden soll, um auf Server außerhalb des lokalen Netzwerks zugreifen zu können. Verwenden Sie das Format xx.xx.xx.xx:yyyy, wobei xx.xx.xx.xx die IP-Adresse des Proxys und yyyy die Anschlussnummer ist. Lassen Sie dieses Feld leer, wenn kein HTTP-Web-Proxy genutzt wird. - EN You can specify the IP address and port for an HTTP/Web proxy to use when Squeezebox Server connects to servers outside your local network. Use the format xx.xx.xx.xx:yyyy where xx.xx.xx.xx is the IP address of the proxy, and yyyy is the port number. Leave this field blank if you don't use a HTTP web proxy. - ES Se puede especificar la dirección IP y el puerto de un proxy HTTP/Web para usarlo cuando Squeezebox Server se conecte a servidores fuera de la red local. Use el formato xx.xx.xx.xx:yyyy donde xx.xx.xx.xx es la dirección IP del proxy y donde yyyy es el número del puerto. Deje este campo en blanco si no usa un proxy Web HTTP. - FI Voit määrittää IP-osoitteen ja portin, joita HTTP- tai WWW-välityspalvelin käyttää, kun Squeezebox Server muodostaa yhteyden paikallisen verkon ulkopuolella oleviin palvelimiin. Käytä muotoa xx.xx.xx.xx:yyyy, jossa xx.xx.xx.xx on välityspalvelimen IP-osoite ja yyyy portin numero. Jätä tämä kenttä tyhjäksi, jos et käytä HTTP-välityspalvelinta. - FR Vous pouvez spécifier l'adresse IP et le port d'un proxy HTTP/Web à utiliser lorsque le Squeezebox Server tente de se connecter à un serveur qui n'appartient pas au réseau local. Utilisez le format xx.xx.xx.xx:yyyy où xx.xx.xx.xx représente l'adresse IP et yyyy le numéro de port. Ne renseignez pas ce champ si vous n'utilisez pas de proxy Web. - HE באפשרותך לציין את כתובת ה-IP והיציאה עבור שרת Proxy באינטרנט/HTTP לשימוש כאשר Squeezebox Server מתחבר לשרתים מחוץ לרשת המקומית. השתמש בתבנית xx.xx.xx.xx:yyyy כאשר xx.xx.xx.xx מייצג את כתובת ה-IP של שרת ה-Proxy ו-yyyy את מספר היציאה. השאר שדה זה ריק אם אינך משתמש בשרת Proxy מסוג HTTP באינטרנט. - IT Si può specificare l'indirizzo IP e la porta da utilizzare con un proxy HTTP/Web quando Squeezebox Server si collega a server al di fuori della propria rete locale. Utilizzare il formato xx.xx.xx.xx:yyyy dove xx.xx.xx.xx è l'indirizzo IP del proxy e yyyy è il numero della porta. Lasciare vuoto questo campo se non si utilizza alcun proxy HTTP/Web. - JA ローカルネットワーク以外でSqueezebox Serverを接続される場合に、HTTP/Web Proxyの為のIPとポート番号を設定することができます。xx.xx.xx.xx:yyyyのように入力してください。xx.xx.xx.xxはIPアドレス、yyyyはポート番号を表します。 - NL Je kunt het IP-adres en poortnummer opgeven voor een HTTP/Webproxy die gebruikt moet worden wanneer Squeezebox Server een verbinding met servers buiten je lokale netwerk moet maken. Gebruik de notatie xx.xx.xx.xx:yyyy, waarbij xx.xx.xx.xx het IP-adres van de proxy is en yyyy het poortnummer Laat dit veld leeg als je geen HTTP/Webproxy gebruikt. - NO Du kan angi IP-adresse og port for en HTTP/Webproxy som brukes når Squeezebox Server kopler til servere utenfor det lokale nettverket. Bruk formatet xx.xx.xx.xx:yyyy, der xx.xx.xx.xx er IP-adressen til proxyen, og yyyy er portnummeret. La dette feltet stå tomt hvis du ikke bruker en http-webproxy. - PL Możliwe jest określenie adresu IP portu serwera proxy HTTP/internetowego używanego przez program Squeezebox Server do łączenia z serwerami poza siecią lokalną. Użyj formatu xx.xx.xx.xx:yyyy, gdzie xx.xx.xx.xx to adres IP serwera proxy, a yyyy to numer portu. Jeżeli nie chcesz korzystać z internetowego serwera proxy HTTP, pozostaw to pole puste. - RU Можно задать IP-адрес и порт, используемые HTTP или веб-прокси при подключении Squeezebox Server к серверам вне локальной сети. Используйте формат xx.xx.xx.xx:yyyy, где xx.xx.xx.xx — IP-адрес прокси, а yyyy — номер порта. Не заполняйте это поле, если HTTP или веб-прокси не используется. - SV Du kan ange IP-adress och port för en HTTP-/webbproxy som ska användas när Squeezebox Server ansluter till servrar utanför ditt lokala nätverk. Använd formatet xx.xx.xx.xx:yyyy, där xx.xx.xx.xx är proxyns IP-adress och yyyy portnumret. Lämna fältet tomt om du inte använder någon HTTP-/webbproxy. - ZH_CN 您可以指定当Squeezebox Server连接到您本地网络以外的服务器时所使用的HTTP/网代理IP地址和端口。请使用:xx.xx.xx.xx为网代理IP地址的格式、xx.xx.xx.xx:yyyy,yyyy为端口号。如果您不使用HTTP/网代理请留空。 + CS Můžete specifikovat IP adresu a port pro HTTP/Web proxy server, které se použijí při připojení Logitech Media Server k serverům mimo vaši místní síť. Používejte formát xx.xx.xx.xx:yyyy, kde xx.xx.xx.xx je IP adresa proxy serveru a yyyy číslo portu. Pokud nepoužíváte HTTP web proxy server, ponechte toto pole prázdné.. + DA Du kan specificere IP-adresse og portnummer til en HTTP/Web-proxy som Logitech Media Server skal anvende når der tilsluttes servere udenfor dit lokale netværk. Anvend formatet xx.xx.xx.xx:yyyy, hvor xx.xx.xx.xx er proxyens IP-adresse og yyyy er proxyserverens portnummer. Lad feltet være tomt hvis du ikke ønsker at anvende en HTTP-proxy. + DE Sie können die IP-Adresse und den Anschluss eines HTTP/Web-Proxys definieren, den Logitech Media Server verwenden soll, um auf Server außerhalb des lokalen Netzwerks zugreifen zu können. Verwenden Sie das Format xx.xx.xx.xx:yyyy, wobei xx.xx.xx.xx die IP-Adresse des Proxys und yyyy die Anschlussnummer ist. Lassen Sie dieses Feld leer, wenn kein HTTP-Web-Proxy genutzt wird. + EN You can specify the IP address and port for an HTTP/Web proxy to use when Logitech Media Server connects to servers outside your local network. Use the format xx.xx.xx.xx:yyyy where xx.xx.xx.xx is the IP address of the proxy, and yyyy is the port number. Leave this field blank if you don't use a HTTP web proxy. + ES Se puede especificar la dirección IP y el puerto de un proxy HTTP/Web para usarlo cuando Logitech Media Server se conecte a servidores fuera de la red local. Use el formato xx.xx.xx.xx:yyyy donde xx.xx.xx.xx es la dirección IP del proxy y donde yyyy es el número del puerto. Deje este campo en blanco si no usa un proxy Web HTTP. + FI Voit määrittää IP-osoitteen ja portin, joita HTTP- tai WWW-välityspalvelin käyttää, kun Logitech Media Server muodostaa yhteyden paikallisen verkon ulkopuolella oleviin palvelimiin. Käytä muotoa xx.xx.xx.xx:yyyy, jossa xx.xx.xx.xx on välityspalvelimen IP-osoite ja yyyy portin numero. Jätä tämä kenttä tyhjäksi, jos et käytä HTTP-välityspalvelinta. + FR Vous pouvez spécifier l'adresse IP et le port d'un proxy HTTP/Web à utiliser lorsque le Logitech Media Server tente de se connecter à un serveur qui n'appartient pas au réseau local. Utilisez le format xx.xx.xx.xx:yyyy où xx.xx.xx.xx représente l'adresse IP et yyyy le numéro de port. Ne renseignez pas ce champ si vous n'utilisez pas de proxy Web. + HE באפשרותך לציין את כתובת ה-IP והיציאה עבור שרת Proxy באינטרנט/HTTP לשימוש כאשר Logitech Media Server מתחבר לשרתים מחוץ לרשת המקומית. השתמש בתבנית xx.xx.xx.xx:yyyy כאשר xx.xx.xx.xx מייצג את כתובת ה-IP של שרת ה-Proxy ו-yyyy את מספר היציאה. השאר שדה זה ריק אם אינך משתמש בשרת Proxy מסוג HTTP באינטרנט. + IT Si può specificare l'indirizzo IP e la porta da utilizzare con un proxy HTTP/Web quando Logitech Media Server si collega a server al di fuori della propria rete locale. Utilizzare il formato xx.xx.xx.xx:yyyy dove xx.xx.xx.xx è l'indirizzo IP del proxy e yyyy è il numero della porta. Lasciare vuoto questo campo se non si utilizza alcun proxy HTTP/Web. + JA ローカルネットワーク以外でLogitech Media Serverを接続される場合に、HTTP/Web Proxyの為のIPとポート番号を設定することができます。xx.xx.xx.xx:yyyyのように入力してください。xx.xx.xx.xxはIPアドレス、yyyyはポート番号を表します。 + NL Je kunt het IP-adres en poortnummer opgeven voor een HTTP/Webproxy die gebruikt moet worden wanneer Logitech Media Server een verbinding met servers buiten je lokale netwerk moet maken. Gebruik de notatie xx.xx.xx.xx:yyyy, waarbij xx.xx.xx.xx het IP-adres van de proxy is en yyyy het poortnummer Laat dit veld leeg als je geen HTTP/Webproxy gebruikt. + NO Du kan angi IP-adresse og port for en HTTP/Webproxy som brukes når Logitech Media Server kopler til servere utenfor det lokale nettverket. Bruk formatet xx.xx.xx.xx:yyyy, der xx.xx.xx.xx er IP-adressen til proxyen, og yyyy er portnummeret. La dette feltet stå tomt hvis du ikke bruker en http-webproxy. + PL Możliwe jest określenie adresu IP portu serwera proxy HTTP/internetowego używanego przez program Logitech Media Server do łączenia z serwerami poza siecią lokalną. Użyj formatu xx.xx.xx.xx:yyyy, gdzie xx.xx.xx.xx to adres IP serwera proxy, a yyyy to numer portu. Jeżeli nie chcesz korzystać z internetowego serwera proxy HTTP, pozostaw to pole puste. + RU Можно задать IP-адрес и порт, используемые HTTP или веб-прокси при подключении Logitech Media Server к серверам вне локальной сети. Используйте формат xx.xx.xx.xx:yyyy, где xx.xx.xx.xx — IP-адрес прокси, а yyyy — номер порта. Не заполняйте это поле, если HTTP или веб-прокси не используется. + SV Du kan ange IP-adress och port för en HTTP-/webbproxy som ska användas när Logitech Media Server ansluter till servrar utanför ditt lokala nätverk. Använd formatet xx.xx.xx.xx:yyyy, där xx.xx.xx.xx är proxyns IP-adress och yyyy portnumret. Lämna fältet tomt om du inte använder någon HTTP-/webbproxy. + ZH_CN 您可以指定当Logitech Media Server连接到您本地网络以外的服务器时所使用的HTTP/网代理IP地址和端口。请使用:xx.xx.xx.xx为网代理IP地址的格式、xx.xx.xx.xx:yyyy,yyyy为端口号。如果您不使用HTTP/网代理请留空。 SETUP_SHOWBUFFERFULLNESS CS Zobrazit kompletní vyrovnávací paměť @@ -8461,21 +8474,21 @@ SETUP_CSRFPROTECTIONLEVEL ZH_CN CSRF保护程度 SETUP_CSRFPROTECTIONLEVEL_DESC - CS Jako ochranu proti útokům typu "Podvržení požadavku mezi různými stránkami (Cross Site Request Forgery - CSRF)" Squeezebox Server používá speciální kontrolu požadavků HTTP na funkce, které mohou provádět změny ve vašem systému nebo manipulovat se seznamy skladeb nebo přehrávači. Můžete si zvolit úroveň kontroly, kterou bude Squeezebox Server používat. Výchozí úroveň je Žádná. Další podrobnosti v oddíle Nápověda. - DA Som en beskyttelse mod såkaldte CSRF-sikkerhedstrusler (Cross Site Request Forgery, dvs. falske krydshenvisninger), undersøger Squeezebox Server alle HTTP-anmodninger om funktioner som kan ændre dit system eller dine afspilningslister, ekstra grundigt. Du kan selv indstille hvilket sikkerhedsniveau Squeezebox Server skal benytte. Standard er Ingen. Der er flere oplysninger i hjælpen. - DE Zum Schutz gegen 'Cross Site Request Forgery' (CSRF)-Sicherheitsrisiken prüft Squeezebox Server HTTP-Anforderungen auf Funktionen, die das System ändern oder Wiedergabelisten oder Player beeinträchtigen können. Sie können die Schutzstufe für Squeezebox Server festlegen. Standardmäßig ist kein Wert festgelegt. Weitere Informationen finden Sie in der Hilfe. - EN To protect against "Cross Site Request Forgery" (CSRF) security threats, Squeezebox Server applies special scrutiny to HTTP requests for functions that can make changes to your system or manipulate playlists or players. You may choose the level of scrutiny for Squeezebox Server to use. The default is None. See Help Section for more details. - ES Para protegerse contra amenazas CSRF ("Cross Site Request Forgery"), Squeezebox Server aplica un análisis detallado especial a las solicitudes HTTP de funciones que puedan realizar cambios en el sistema o manipular listas de reproducción o reproductores. Se puede elegir el nivel de análisis detallado que debe usar Squeezebox Server. El valor predeterminado es Ninguno. Consulte la sección de ayuda para más detalles. - FI "Cross Site Request Forgery" (CSRF) -tietoturvauhilta suojautumista varten Squeezebox Server etsii HTTP-pyynnöistä erityisen tarkasti toimintoja, jotka voivat tehdä muutoksia järjestelmään tai muokata soittoluetteloita tai soittimia. Voit valita, kuinka tarkasti Squeezebox Server tutkii pyynnöt. Oletus on Ei mitään. Katso ohjeesta lisätietoja. - FR Pour garantir une protection contre les risques de sécurité de type "Cross Site Request Forgery" (CSRF), le Squeezebox Server applique une vérification supplémentaire aux requêtes HTTP susceptibles d'altérer le système ou de manipuler des listes de lecture ou des platines. Vous pouvez spécifier le niveau de cette vérification. La valeur par défaut est Aucune. Reportez-vous à l'aide pour plus d'informations. - HE להתגוננות מפני "זיוף בקשות מאתרים צולבים" (CSRF)‏, Squeezebox Server מחיל בדיקה קפדנית מיוחדת על בקשות HTTP עבור פונקציות שיכולות לבצע שינויים במערכת או לטפל ברשימות השמעה או בנגנים. באפשרותך לבחור את רמת הבדיקה הקפדנית שבה ישתמש השרת. ברירת המחדל היא 'בינונית'. עיין במקטע העזרה לקבלת פרטים נוספים. - IT Per ottenere protezione da minacce alla sicurezza di tipo Cross Site Request Forgery (CSRF), Squeezebox Server controlla accuratamente le richieste HTTP di funzioni che possono determinare modifiche del sistema o manipolare le playlist o il lettore. È possibile scegliere il livello di controllo che il server deve adottare. Il livello predefinito è Nessuno. Per ulteriori informazioni, consultare la sezione Guida. - NL Ter bescherming tegen CSRF-beveiligingsbedreigingen (Cross Site Request Forgery) worden HTTP-verzoeken door Squeezebox Server nauwkeurig onderzocht op functies die je systeem, playlists of muzieksystemen kunnen wijzigen. Je kunt zelf instellen hoe nauwkeurig de server moet zijn. De standaardinstelling is 'Geen'. Zie de Help-sectie voor meer informatie. - NO Squeezebox Server beskytter seg mot CSRF-sikkerhetstrusler (Cross Site Request Forgery) ved å bruke en egen undersøkelse av http-forespørsler for funksjoner som kan utføre endringer på systemet eller manipulere spillelister og spillere. Du kan angi hvilket sikkerhetsnivå Squeezebox Server skal operere med. Standard er Ingen. Du kan finne ut mer i hjelp-delen. - PL W celu ochrony przed atakiem typu „CSRF” (Cross Site Request Forgery) program Squeezebox Server dokładnie bada żądania HTTP dotyczące funkcji, które mogą wprowadzić zmiany w systemie, bądź manipulować listami odtwarzania lub odtwarzaczami. Możliwe jest określenie poziomu badania używanego przez program Squeezebox Server. Ustawienie domyślne to Brak. Zapoznaj się z Pomocą, aby uzyskać szczegółowe informacje. - RU Для защиты от угроз безопасности CSRF (подделки межсайтовых запросов) HTTP-запросы в Squeezebox Server проходят специальную проверку на наличие функций, способных повлиять на работу системы, а также на плей-листы или плееры. В Squeezebox Server можно выбрать уровень проверки. По умолчанию проверка не выполняется. Дополнительные сведения см. в разделе справки. + CS Jako ochranu proti útokům typu "Podvržení požadavku mezi různými stránkami (Cross Site Request Forgery - CSRF)" Logitech Media Server používá speciální kontrolu požadavků HTTP na funkce, které mohou provádět změny ve vašem systému nebo manipulovat se seznamy skladeb nebo přehrávači. Můžete si zvolit úroveň kontroly, kterou bude Logitech Media Server používat. Výchozí úroveň je Žádná. Další podrobnosti v oddíle Nápověda. + DA Som en beskyttelse mod såkaldte CSRF-sikkerhedstrusler (Cross Site Request Forgery, dvs. falske krydshenvisninger), undersøger Logitech Media Server alle HTTP-anmodninger om funktioner som kan ændre dit system eller dine afspilningslister, ekstra grundigt. Du kan selv indstille hvilket sikkerhedsniveau Logitech Media Server skal benytte. Standard er Ingen. Der er flere oplysninger i hjælpen. + DE Zum Schutz gegen 'Cross Site Request Forgery' (CSRF)-Sicherheitsrisiken prüft Logitech Media Server HTTP-Anforderungen auf Funktionen, die das System ändern oder Wiedergabelisten oder Player beeinträchtigen können. Sie können die Schutzstufe für Logitech Media Server festlegen. Standardmäßig ist kein Wert festgelegt. Weitere Informationen finden Sie in der Hilfe. + EN To protect against "Cross Site Request Forgery" (CSRF) security threats, Logitech Media Server applies special scrutiny to HTTP requests for functions that can make changes to your system or manipulate playlists or players. You may choose the level of scrutiny for Logitech Media Server to use. The default is None. See Help Section for more details. + ES Para protegerse contra amenazas CSRF ("Cross Site Request Forgery"), Logitech Media Server aplica un análisis detallado especial a las solicitudes HTTP de funciones que puedan realizar cambios en el sistema o manipular listas de reproducción o reproductores. Se puede elegir el nivel de análisis detallado que debe usar Logitech Media Server. El valor predeterminado es Ninguno. Consulte la sección de ayuda para más detalles. + FI "Cross Site Request Forgery" (CSRF) -tietoturvauhilta suojautumista varten Logitech Media Server etsii HTTP-pyynnöistä erityisen tarkasti toimintoja, jotka voivat tehdä muutoksia järjestelmään tai muokata soittoluetteloita tai soittimia. Voit valita, kuinka tarkasti Logitech Media Server tutkii pyynnöt. Oletus on Ei mitään. Katso ohjeesta lisätietoja. + FR Pour garantir une protection contre les risques de sécurité de type "Cross Site Request Forgery" (CSRF), le Logitech Media Server applique une vérification supplémentaire aux requêtes HTTP susceptibles d'altérer le système ou de manipuler des listes de lecture ou des platines. Vous pouvez spécifier le niveau de cette vérification. La valeur par défaut est Aucune. Reportez-vous à l'aide pour plus d'informations. + HE להתגוננות מפני "זיוף בקשות מאתרים צולבים" (CSRF)‏, Logitech Media Server מחיל בדיקה קפדנית מיוחדת על בקשות HTTP עבור פונקציות שיכולות לבצע שינויים במערכת או לטפל ברשימות השמעה או בנגנים. באפשרותך לבחור את רמת הבדיקה הקפדנית שבה ישתמש השרת. ברירת המחדל היא 'בינונית'. עיין במקטע העזרה לקבלת פרטים נוספים. + IT Per ottenere protezione da minacce alla sicurezza di tipo Cross Site Request Forgery (CSRF), Logitech Media Server controlla accuratamente le richieste HTTP di funzioni che possono determinare modifiche del sistema o manipolare le playlist o il lettore. È possibile scegliere il livello di controllo che il server deve adottare. Il livello predefinito è Nessuno. Per ulteriori informazioni, consultare la sezione Guida. + NL Ter bescherming tegen CSRF-beveiligingsbedreigingen (Cross Site Request Forgery) worden HTTP-verzoeken door Logitech Media Server nauwkeurig onderzocht op functies die je systeem, playlists of muzieksystemen kunnen wijzigen. Je kunt zelf instellen hoe nauwkeurig de server moet zijn. De standaardinstelling is 'Geen'. Zie de Help-sectie voor meer informatie. + NO Logitech Media Server beskytter seg mot CSRF-sikkerhetstrusler (Cross Site Request Forgery) ved å bruke en egen undersøkelse av http-forespørsler for funksjoner som kan utføre endringer på systemet eller manipulere spillelister og spillere. Du kan angi hvilket sikkerhetsnivå Logitech Media Server skal operere med. Standard er Ingen. Du kan finne ut mer i hjelp-delen. + PL W celu ochrony przed atakiem typu „CSRF” (Cross Site Request Forgery) program Logitech Media Server dokładnie bada żądania HTTP dotyczące funkcji, które mogą wprowadzić zmiany w systemie, bądź manipulować listami odtwarzania lub odtwarzaczami. Możliwe jest określenie poziomu badania używanego przez program Logitech Media Server. Ustawienie domyślne to Brak. Zapoznaj się z Pomocą, aby uzyskać szczegółowe informacje. + RU Для защиты от угроз безопасности CSRF (подделки межсайтовых запросов) HTTP-запросы в Logitech Media Server проходят специальную проверку на наличие функций, способных повлиять на работу системы, а также на плей-листы или плееры. В Logitech Media Server можно выбрать уровень проверки. По умолчанию проверка не выполняется. Дополнительные сведения см. в разделе справки. SV För att skydda dig mot så kallade CSRF-säkerhetshot (Cross Site Request Forgery) granskas varje HTTP-begäran extra noggrant om den gäller funktioner där datorn, spelarna eller spellistorna kan manipuleras. Du kan själv välja hur noggrant granskningen ska utföras. Standardnivån är Ingen. Mer information finns i hjälpavsnittet. - ZH_CN 为了免受"CSRF"安全威胁,Squeezebox Server会向那些可能变动您的系统或操作播放表的HTTP请求特别察视。您可以选择此察视的严密程度。缺省为中等。详情请参阅帮助部分。 + ZH_CN 为了免受"CSRF"安全威胁,Logitech Media Server会向那些可能变动您的系统或操作播放表的HTTP请求特别察视。您可以选择此察视的严密程度。缺省为中等。详情请参阅帮助部分。 SETUP_IPFILTER_HEAD CS Blokovat příchozí spojení @@ -8573,23 +8586,23 @@ SETUP_FILTERRULE_HEAD ZH_CN 允许的IP地址 SETUP_FILTERRULE_DESC - CS Pokud jste zapnuli blokování, můžete zadat adresy, kterým chcete povolit připojení ke Squeezebox Server.

              Toto pole akceptuje seznam konkrétních IP adres, zástupné znaky typu * a rozsahy IP adres v seznamu oddělovaném čárkami. Například:

              10.1.2.2 povolí připojení pouze z adresy 10.1.2.2

              10.1.2.* povolí vše s IP adresou, která bude mezi adresami 10.1.2.x.

              10.1.2.2-50 povolí připojení IP adres v rozsahu 10.1.2.2 - 10.1.2.50.

              Více položek lze kombinovat a oddělovat čárkami, například 10.1.2.2,172.16.1.*,192.168.1-254

              Speciální IP adresa 127.0.0.1 povolí webovému prohlížeči připojení ke Squeezebox Server běžícímu na stejném počítači. - DA Hvis blokeringsfunktionen er slået til, kan du angive adresser hvorfra der må etableres forbindelse til Squeezebox Server.

              Du kan angive bestemte IP-adresser, adresser med jokertegnet * samt IP-adresseområder i en kommaadskilt liste. Eksempel:

              10.1.2.2 tillader udelukkende 10.1.2.2 at etablere forbindelse

              10.1.2.* tillader forbindelser fra alt med en adresse startende med 10.1.2. og sluttende med et vilkårligt tal

              10.1.2.2-50 tillader forbindelser fra alle IP-adresser mellem 10.1.2.2 og 10.1.2.50

              Endelig kan du angive flere adresser og adresseområder, og adskille dem vha. et komma: 10.1.2.2,172.16.1.*,192.168.1-254

              Den særlige IP-adresse 127.0.0.1 gør det muligt for en webbrowser at etablere forbindelse til Squeezebox Server som kører på den samme computer. - DE Ist die Blockierung aktiviert, können Sie IP-Adressen angeben, die eine Verbindung zu Squeezebox Server herstellen dürfen.

              Dieses Feld akzeptiert eine Liste spezifischer IP-Adressen. Verwenden Sie * als Jokerzeichen und trennen Sie unterschiedliche IP-Adressen durch Komma.

              Beispiel: 10.1.2.2 akzeptiert nur 10.1.2.2

              10.1.2.* akzeptiert alle IP-Adressen, die mit '10.1.2.' beginnen.

              10.1.2.2-50 akzeptiert die IP-Adressen 10.1.2.2 – 10.1.2.50.

              Sie können mehrere Einträge durch Kommas kombinieren. Beispiel:10.1.2.2,172.16.1.*,192.168.1-255.*

              Die spezielle IP-Adresse 127.0.0.1 gestattet einem Web-Browser die Verbindung mit Squeezebox Server auf demselben Computer. - EN If you have turned on blocking you can enter the addresses that you'd like to allow to connect to Squeezebox Server.

              This field accepts a list of specific IP addresses, * style wildcards, and IP address ranges in a comma separated list. For example:

              10.1.2.2 will allow only 10.1.2.2 to connect

              10.1.2.* will allow anything with an IP address that be the 10.1.2.x addresses.

              10.1.2.2-50 will allow IP addresses in the range 10.1.2.2 - 10.1.2.50 to connect.

              Finally, multiple entries can be combined with commas, like this 10.1.2.2,172.16.1.*,192.168.1-254

              The special IP address 127.0.0.1 allows a web browser to connect to Squeezebox Server running on that same computer. - ES Si se ha activado el bloqueo, se pueden introducir las direcciones desde las que se desea permitir la conexión a Squeezebox Server.

              Este campo acepta una lista de direcciones IP específicas, comodines del tipo * e intervalos de direcciones IP en una lista separada por comas. Por ejemplo:

              10.1.2.2 sólo permitirá la conexión de 10.1.2.2

              10.1.2.* permitirá la conexión desde cualquier dirección IP con el formato 10.1.2.X

              10.1.2.2-50 permitirá conexiones desde direcciones IP pertenecientes al intervalo 10.1.2.2 - 10.1.2.50

              Por último, se pueden combinar varias entradas con comas, así: 10.1.2.2,172.16.1.*,192.168.1-254

              La dirección IP especial 127.0.0.1 permite que un navegador Web se conecte al Squeezebox Server que se esté ejecutando en ese mismo equipo. - FI Jos estäminen on otettu käyttöön, voit kirjoittaa osoitteet, joiden sallit muodostaa yhteyden Squeezebox Serveriin.

              Tähän kenttään voidaan lisätä luettelo tietyistä IP-osoitteista, *-tyylin yleismerkeistä ja pilkuilla erotettu luettelo IP-osoitteista. Esimerkiksi:

              10.1.2.2 sallii ainoastaan osoitteen 10.1.2.2,

              10.1.2.* sallii IP-osoitteet, jotka sisältävät numerot 10.1.2.x,

              10.1.2.2-50 sallii alueeseen 10.1.2.2 - 10.1.2.50 kuuluvat IP-osoitteet.

              Jos osoitteita on useita, ne voidaan erottaa pilkuin, esimerkiksi näin: 10.1.2.2,172.16.1.*,192.168.1-254

              IP-osoite 127.0.0.1 sallii selaimen muodostaa yhteyden samassa tietokoneessa toimivaan Squeezebox Serveriin. - FR Si vous avez activé le blocage, vous pouvez saisir l'adresse IP des utilisateurs qui peuvent accéder au Squeezebox Server.

              Cette zone de saisie reçoit des adresses IP spécifiques, le caractère générique * et des intervalles d'adresses IP, le tout séparé par une virgule.
              Exemple:10.1.2.2autorise uniquement cette adresse à se connecter

              10.1.2.*autorise toutes les adresses dont les trois premières composantes sont 10, 1 et 2 à se connecter

              10.1.2.2,10.1.3.*,10.1.4.2-50autorise l'adresse 10.1.2.2, toutes les adresses commençant par 10.1.3 ainsi que les adresses dans l'intervalle 10.1.4.2 à 10.1.4.50.

              Enfin, vous pouvez combiner des entrées à l'aide de virgules, par exemple10.1.2.2,172.16.1.*,192.168.1-254

              L'adresse IP 127.0.0.1 autorise un navigateur Web à se connecter au Squeezebox Server s'ils se trouvent sur le même ordinateur. - HE אם הפעלת את אפשרות החסימה, באפשרותך להזין את הכתובות שלהן ברצונך לאפשר להתחבר ל-Squeezebox Server.

              בשדה זה ניתן להזין רשימה של כתובות IP ספציפיות, תווים כלליים כגון *, וטווחים של כתובות IP ברשימה המופרדת באמצעות פסיקים. לדוגמה:

              ‎10.1.2.2 יאפשר רק ל-‎‏10.1.2.2 להתחבר.

              ‎10.1.2.*‎‎ יאפשר לכל גורם עם כתובת IP בתבנית ‎‎10.1.2.x להתחבר.

              ‎10.1.2.2-50 יאפשר לכתובות IP בטווח שבין ‎‎10.1.2.2 - 10.1.2.50‎ להתחבר.

              לסיום, ניתן לשלב רשומות מרובות באמצעות פסיקים, לדוגמה, ‎10.1.2.2,172.16.1.*,192.168.1-254‎

              כתובת ה-IP המיוחדת ‎127.0.0.1 מאפשרת לדפדפן אינטרנט להתחבר לשרת Squeezebox Server שפועל באותו מחשב. - IT Se è stato attivato il blocco, è possibile inserire gli indirizzi a cui consentire la connessione a Squeezebox Server.

              In questo campo è possibile inserire un elenco di indirizzi IP specifici, il carattere jolly * ed elenchi di intervalli di indirizzi IP separati da virgole. Ad esempio:

              se si specifica10.1.2.2, viene accettata solo la connessione con l'indirizzo 10.1.2.2

              se si specifica10.1.2.*, viene accettata la connessione con tutti gli indirizzi IP che iniziano con 10.1.2.x

              se si specifica10.1.2.2-50, viene accettata la connessione con indirizzi IP compresi tra 10.1.2.2 e 10.1.2.50

              Infine, è possibile specificare più indirizzi IP separandoli con virgole, ad esempio:10.1.2.2,172.16.1.*,192.168.1-254

              L'indirizzo IP speciale 127.0.0.1 consente di connettere un browser Web a Squeezebox Server in esecuzione sullo stesso computer. - JA ブロックする、と指定したのであれば、Squeezebox Serverに接続を許可するIPアドレスを指定することができます。

              このフィールドはIPアドレスを入力することができます。*を使ってワイルドカード指定もできます。例えば、

              10.1.2.2は、10.1.2.2のみに接続を許可しますが、

              10.1.2.*は、10.1.2.xのどのアドレスでも許可します。

              10.1.2.2-50であれば、10.1.2.2から10.1.2.50のアドレスが許可されます。

              最後に、複数のアドレスは以下のように、コンマで区切って入力できます。10.1.2.2,172.16.1.*,192.168.1-254

              127.0.0.1という特別なアドレスは、ウェブブラウザーがSqueezebox Serverに接続する時に接続を可能にします。 - NL Als je 'Blokkeren' hebt ingesteld, kun je de adressen invoeren die je toegang wilt geven tot Squeezebox Server.

              Dit veld accepteert een lijst van specifieke IP-adressen, jokertekens zoals '*' en IP-adresbereiken in een kommagescheiden lijst. Bijvoorbeeld:

              10.1.2.2 staat alleen 10.1.2.2 toe een verbinding te maken

              10.1.2.* verleent elk IP-adres met de vorm 10.1.2.x toegang.

              10.1.2.2-50 verleent IP-adressen tussen 10.1.2.2 en 10.1.2.50 toegang.

              Ten slotte kunnen meerdere adressen als volgt met komma's gecombineerd worden:10.1.2.2,172.16.1.*,192.168.1-254

              Het speciale IP-adres 127.0.0.1 verleent toegang aan webbrowsers die op dezelfde computer als Squeezebox Server zelf draaien. - NO Hvis du har aktivert blokkering kan du angi de IP-adressene som skal få kople seg til Squeezebox Server.

              I dette feltet kan du angi en kommadelt liste med IP-adresser, jokertegn som *, og en kommadelt liste med IP-adressegrupper. Eksempel:

              10.1.2.2 tillater kun at 10.1.2.2 kopler seg til.

              10.1.2.* tillater alle IP-adresser som begynner med 10.1.2.x.

              10.1.2.2-50 tillater at IP-adresser i gruppen 10.1.2.2–10.1.2.50 kopler seg til.

              Du kan også kombinere oppføringer med komma, slik som dette: 10.1.2.2,172.16.1.*,192.168.1-254

              Spesial-IP-adressen 127.0.0.1 gjør at en nettleser som kjører på samme datamaskin kan kople seg til Squeezebox Server. - PL Jeżeli włączono blokowanie, możesz wprowadzić adresy, które będą mogły się łączyć z programem Squeezebox Server.

              W tym polu można wpisać określone adresy IP, znaki wieloznaczne typu * i zakresy adresów IP na liście rozdzielonej przecinkami. Na przykład: wpisanie

              10.1.2.2 umożliwi połączenie tylko z adresu 10.1.2.2

              Wpisanie 10.1.2.* umożliwi połączenie z dowolnego adresu IP w postaci 10.1.2.x.

              Wpisanie 10.1.2.2-50 umożliwi połączenie z adresów IP w zakresie 10.1.2.2–10.1.2.50.

              Można także dodać kilka wpisów rozdzielonych przecinkami, na przykład: 10.1.2.2,172.16.1.*,192.168.1-254

              Specjalny adres IP 127.0.0.1 umożliwia przeglądarce internetowej połączenie z programem Squeezebox Server uruchomionym na tym samym komputerze. - PT Se activar o bloqueio por IP de origem, introduza aqui os endereços com permissões para ligar ao Squeezebox Server.

              Este campo aceita uma lista de endereços IP, redes (usando o caractér "*"), e segmentos de rede (usando "endereço-endereço"), separados por vírgulas. Por exemplo - RU При включенном блокировании можно ввести адреса, с которых разрешено подключение к Squeezebox Server.

              В данное поле можно ввести список разделенных запятыми IP-адресов, подстановочных знаков (*) и диапазонов IP-адресов. Например:

              10.1.2.2 — подключение будет разрешено только для IP-адреса 10.1.2.2

              10.1.2.* — разрешено для IP-адресов вида 10.1.2.x.

              10.1.2.2-50 — разрешено для IP-адресов в диапазоне 10.1.2.2 — 10.1.2.50.

              Наконец, можно ввести через запятую несколько элементов: 10.1.2.2,172.16.1.*,192.168.1-254

              Специальный IP-адрес 127.0.0.1 позволяет веб-браузеру подключаться к Squeezebox Server, запущенному на этом же компьютере. - SV Om du har aktiverat blockering kan du ange de adresser du vill ansluta till Squeezebox Server.

              Du kan ange särskilda IP-adresser, adresser med jokertecken* samt IP-adressintervall i en kommaseparerad lista. Exempel:

              10.1.2.2 tillåter endast 10.1.2.2 att ansluta.

              10.1.2.* tillåter alla IP-adresser som börjar med 10.1.2.

              10.1.2.2-50 tillåter alla IP-adresser i intervallet 10.1.2.2–10.1.2.50 .

              Olika typer av poster kan kombineras, t.ex. 10.1.2.2,172.16.1.*,192.168.1-254.

              Special-IP-adressen 127.0.0.1 tillåter en webbläsare på samma dator som Squeezebox Server att ansluta. - ZH_CN 如果您已经启动了阻拦向内连接装置,您可以在此输入允许向内连接到Squeezebox Server的IP来源地址。

              这个资料栏接受具体IP地址名单,*式的通配符,及以逗号分开的IP地址范围名单。例如:

              10.1.2.2将只允许10.1.2.2连接

              10.1.2.*将允许任何10.1.2.x的IP地址

              10.1.2.2-50将允许10.1.2.2-10.1.2.50范围内的IP地址连接

              您也可以利用逗号结合多个IP地址,例如:10.1.2.2,172.16.1.*,192.168.1-254

              特别IP地址127.0.0.1则表示允许浏览器连接到同一台电脑上的Squeezebox Server。 + CS Pokud jste zapnuli blokování, můžete zadat adresy, kterým chcete povolit připojení ke Logitech Media Server.

              Toto pole akceptuje seznam konkrétních IP adres, zástupné znaky typu * a rozsahy IP adres v seznamu oddělovaném čárkami. Například:

              10.1.2.2 povolí připojení pouze z adresy 10.1.2.2

              10.1.2.* povolí vše s IP adresou, která bude mezi adresami 10.1.2.x.

              10.1.2.2-50 povolí připojení IP adres v rozsahu 10.1.2.2 - 10.1.2.50.

              Více položek lze kombinovat a oddělovat čárkami, například 10.1.2.2,172.16.1.*,192.168.1-254

              Speciální IP adresa 127.0.0.1 povolí webovému prohlížeči připojení ke Logitech Media Server běžícímu na stejném počítači. + DA Hvis blokeringsfunktionen er slået til, kan du angive adresser hvorfra der må etableres forbindelse til Logitech Media Server.

              Du kan angive bestemte IP-adresser, adresser med jokertegnet * samt IP-adresseområder i en kommaadskilt liste. Eksempel:

              10.1.2.2 tillader udelukkende 10.1.2.2 at etablere forbindelse

              10.1.2.* tillader forbindelser fra alt med en adresse startende med 10.1.2. og sluttende med et vilkårligt tal

              10.1.2.2-50 tillader forbindelser fra alle IP-adresser mellem 10.1.2.2 og 10.1.2.50

              Endelig kan du angive flere adresser og adresseområder, og adskille dem vha. et komma: 10.1.2.2,172.16.1.*,192.168.1-254

              Den særlige IP-adresse 127.0.0.1 gør det muligt for en webbrowser at etablere forbindelse til Logitech Media Server som kører på den samme computer. + DE Ist die Blockierung aktiviert, können Sie IP-Adressen angeben, die eine Verbindung zu Logitech Media Server herstellen dürfen.

              Dieses Feld akzeptiert eine Liste spezifischer IP-Adressen. Verwenden Sie * als Jokerzeichen und trennen Sie unterschiedliche IP-Adressen durch Komma.

              Beispiel: 10.1.2.2 akzeptiert nur 10.1.2.2

              10.1.2.* akzeptiert alle IP-Adressen, die mit '10.1.2.' beginnen.

              10.1.2.2-50 akzeptiert die IP-Adressen 10.1.2.2 – 10.1.2.50.

              Sie können mehrere Einträge durch Kommas kombinieren. Beispiel:10.1.2.2,172.16.1.*,192.168.1-255.*

              Die spezielle IP-Adresse 127.0.0.1 gestattet einem Web-Browser die Verbindung mit Logitech Media Server auf demselben Computer. + EN If you have turned on blocking you can enter the addresses that you'd like to allow to connect to Logitech Media Server.

              This field accepts a list of specific IP addresses, * style wildcards, and IP address ranges in a comma separated list. For example:

              10.1.2.2 will allow only 10.1.2.2 to connect

              10.1.2.* will allow anything with an IP address that be the 10.1.2.x addresses.

              10.1.2.2-50 will allow IP addresses in the range 10.1.2.2 - 10.1.2.50 to connect.

              Finally, multiple entries can be combined with commas, like this 10.1.2.2,172.16.1.*,192.168.1-254

              The special IP address 127.0.0.1 allows a web browser to connect to Logitech Media Server running on that same computer. + ES Si se ha activado el bloqueo, se pueden introducir las direcciones desde las que se desea permitir la conexión a Logitech Media Server.

              Este campo acepta una lista de direcciones IP específicas, comodines del tipo * e intervalos de direcciones IP en una lista separada por comas. Por ejemplo:

              10.1.2.2 sólo permitirá la conexión de 10.1.2.2

              10.1.2.* permitirá la conexión desde cualquier dirección IP con el formato 10.1.2.X

              10.1.2.2-50 permitirá conexiones desde direcciones IP pertenecientes al intervalo 10.1.2.2 - 10.1.2.50

              Por último, se pueden combinar varias entradas con comas, así: 10.1.2.2,172.16.1.*,192.168.1-254

              La dirección IP especial 127.0.0.1 permite que un navegador Web se conecte al Logitech Media Server que se esté ejecutando en ese mismo equipo. + FI Jos estäminen on otettu käyttöön, voit kirjoittaa osoitteet, joiden sallit muodostaa yhteyden Logitech Media Serveriin.

              Tähän kenttään voidaan lisätä luettelo tietyistä IP-osoitteista, *-tyylin yleismerkeistä ja pilkuilla erotettu luettelo IP-osoitteista. Esimerkiksi:

              10.1.2.2 sallii ainoastaan osoitteen 10.1.2.2,

              10.1.2.* sallii IP-osoitteet, jotka sisältävät numerot 10.1.2.x,

              10.1.2.2-50 sallii alueeseen 10.1.2.2 - 10.1.2.50 kuuluvat IP-osoitteet.

              Jos osoitteita on useita, ne voidaan erottaa pilkuin, esimerkiksi näin: 10.1.2.2,172.16.1.*,192.168.1-254

              IP-osoite 127.0.0.1 sallii selaimen muodostaa yhteyden samassa tietokoneessa toimivaan Logitech Media Serveriin. + FR Si vous avez activé le blocage, vous pouvez saisir l'adresse IP des utilisateurs qui peuvent accéder au Logitech Media Server.

              Cette zone de saisie reçoit des adresses IP spécifiques, le caractère générique * et des intervalles d'adresses IP, le tout séparé par une virgule.
              Exemple:10.1.2.2autorise uniquement cette adresse à se connecter

              10.1.2.*autorise toutes les adresses dont les trois premières composantes sont 10, 1 et 2 à se connecter

              10.1.2.2,10.1.3.*,10.1.4.2-50autorise l'adresse 10.1.2.2, toutes les adresses commençant par 10.1.3 ainsi que les adresses dans l'intervalle 10.1.4.2 à 10.1.4.50.

              Enfin, vous pouvez combiner des entrées à l'aide de virgules, par exemple10.1.2.2,172.16.1.*,192.168.1-254

              L'adresse IP 127.0.0.1 autorise un navigateur Web à se connecter au Logitech Media Server s'ils se trouvent sur le même ordinateur. + HE אם הפעלת את אפשרות החסימה, באפשרותך להזין את הכתובות שלהן ברצונך לאפשר להתחבר ל-Logitech Media Server.

              בשדה זה ניתן להזין רשימה של כתובות IP ספציפיות, תווים כלליים כגון *, וטווחים של כתובות IP ברשימה המופרדת באמצעות פסיקים. לדוגמה:

              ‎10.1.2.2 יאפשר רק ל-‎‏10.1.2.2 להתחבר.

              ‎10.1.2.*‎‎ יאפשר לכל גורם עם כתובת IP בתבנית ‎‎10.1.2.x להתחבר.

              ‎10.1.2.2-50 יאפשר לכתובות IP בטווח שבין ‎‎10.1.2.2 - 10.1.2.50‎ להתחבר.

              לסיום, ניתן לשלב רשומות מרובות באמצעות פסיקים, לדוגמה, ‎10.1.2.2,172.16.1.*,192.168.1-254‎

              כתובת ה-IP המיוחדת ‎127.0.0.1 מאפשרת לדפדפן אינטרנט להתחבר לשרת Logitech Media Server שפועל באותו מחשב. + IT Se è stato attivato il blocco, è possibile inserire gli indirizzi a cui consentire la connessione a Logitech Media Server.

              In questo campo è possibile inserire un elenco di indirizzi IP specifici, il carattere jolly * ed elenchi di intervalli di indirizzi IP separati da virgole. Ad esempio:

              se si specifica10.1.2.2, viene accettata solo la connessione con l'indirizzo 10.1.2.2

              se si specifica10.1.2.*, viene accettata la connessione con tutti gli indirizzi IP che iniziano con 10.1.2.x

              se si specifica10.1.2.2-50, viene accettata la connessione con indirizzi IP compresi tra 10.1.2.2 e 10.1.2.50

              Infine, è possibile specificare più indirizzi IP separandoli con virgole, ad esempio:10.1.2.2,172.16.1.*,192.168.1-254

              L'indirizzo IP speciale 127.0.0.1 consente di connettere un browser Web a Logitech Media Server in esecuzione sullo stesso computer. + JA ブロックする、と指定したのであれば、Logitech Media Serverに接続を許可するIPアドレスを指定することができます。

              このフィールドはIPアドレスを入力することができます。*を使ってワイルドカード指定もできます。例えば、

              10.1.2.2は、10.1.2.2のみに接続を許可しますが、

              10.1.2.*は、10.1.2.xのどのアドレスでも許可します。

              10.1.2.2-50であれば、10.1.2.2から10.1.2.50のアドレスが許可されます。

              最後に、複数のアドレスは以下のように、コンマで区切って入力できます。10.1.2.2,172.16.1.*,192.168.1-254

              127.0.0.1という特別なアドレスは、ウェブブラウザーがLogitech Media Serverに接続する時に接続を可能にします。 + NL Als je 'Blokkeren' hebt ingesteld, kun je de adressen invoeren die je toegang wilt geven tot Logitech Media Server.

              Dit veld accepteert een lijst van specifieke IP-adressen, jokertekens zoals '*' en IP-adresbereiken in een kommagescheiden lijst. Bijvoorbeeld:

              10.1.2.2 staat alleen 10.1.2.2 toe een verbinding te maken

              10.1.2.* verleent elk IP-adres met de vorm 10.1.2.x toegang.

              10.1.2.2-50 verleent IP-adressen tussen 10.1.2.2 en 10.1.2.50 toegang.

              Ten slotte kunnen meerdere adressen als volgt met komma's gecombineerd worden:10.1.2.2,172.16.1.*,192.168.1-254

              Het speciale IP-adres 127.0.0.1 verleent toegang aan webbrowsers die op dezelfde computer als Logitech Media Server zelf draaien. + NO Hvis du har aktivert blokkering kan du angi de IP-adressene som skal få kople seg til Logitech Media Server.

              I dette feltet kan du angi en kommadelt liste med IP-adresser, jokertegn som *, og en kommadelt liste med IP-adressegrupper. Eksempel:

              10.1.2.2 tillater kun at 10.1.2.2 kopler seg til.

              10.1.2.* tillater alle IP-adresser som begynner med 10.1.2.x.

              10.1.2.2-50 tillater at IP-adresser i gruppen 10.1.2.2–10.1.2.50 kopler seg til.

              Du kan også kombinere oppføringer med komma, slik som dette: 10.1.2.2,172.16.1.*,192.168.1-254

              Spesial-IP-adressen 127.0.0.1 gjør at en nettleser som kjører på samme datamaskin kan kople seg til Logitech Media Server. + PL Jeżeli włączono blokowanie, możesz wprowadzić adresy, które będą mogły się łączyć z programem Logitech Media Server.

              W tym polu można wpisać określone adresy IP, znaki wieloznaczne typu * i zakresy adresów IP na liście rozdzielonej przecinkami. Na przykład: wpisanie

              10.1.2.2 umożliwi połączenie tylko z adresu 10.1.2.2

              Wpisanie 10.1.2.* umożliwi połączenie z dowolnego adresu IP w postaci 10.1.2.x.

              Wpisanie 10.1.2.2-50 umożliwi połączenie z adresów IP w zakresie 10.1.2.2–10.1.2.50.

              Można także dodać kilka wpisów rozdzielonych przecinkami, na przykład: 10.1.2.2,172.16.1.*,192.168.1-254

              Specjalny adres IP 127.0.0.1 umożliwia przeglądarce internetowej połączenie z programem Logitech Media Server uruchomionym na tym samym komputerze. + PT Se activar o bloqueio por IP de origem, introduza aqui os endereços com permissões para ligar ao Logitech Media Server.

              Este campo aceita uma lista de endereços IP, redes (usando o caractér "*"), e segmentos de rede (usando "endereço-endereço"), separados por vírgulas. Por exemplo + RU При включенном блокировании можно ввести адреса, с которых разрешено подключение к Logitech Media Server.

              В данное поле можно ввести список разделенных запятыми IP-адресов, подстановочных знаков (*) и диапазонов IP-адресов. Например:

              10.1.2.2 — подключение будет разрешено только для IP-адреса 10.1.2.2

              10.1.2.* — разрешено для IP-адресов вида 10.1.2.x.

              10.1.2.2-50 — разрешено для IP-адресов в диапазоне 10.1.2.2 — 10.1.2.50.

              Наконец, можно ввести через запятую несколько элементов: 10.1.2.2,172.16.1.*,192.168.1-254

              Специальный IP-адрес 127.0.0.1 позволяет веб-браузеру подключаться к Logitech Media Server, запущенному на этом же компьютере. + SV Om du har aktiverat blockering kan du ange de adresser du vill ansluta till Logitech Media Server.

              Du kan ange särskilda IP-adresser, adresser med jokertecken* samt IP-adressintervall i en kommaseparerad lista. Exempel:

              10.1.2.2 tillåter endast 10.1.2.2 att ansluta.

              10.1.2.* tillåter alla IP-adresser som börjar med 10.1.2.

              10.1.2.2-50 tillåter alla IP-adresser i intervallet 10.1.2.2–10.1.2.50 .

              Olika typer av poster kan kombineras, t.ex. 10.1.2.2,172.16.1.*,192.168.1-254.

              Special-IP-adressen 127.0.0.1 tillåter en webbläsare på samma dator som Logitech Media Server att ansluta. + ZH_CN 如果您已经启动了阻拦向内连接装置,您可以在此输入允许向内连接到Logitech Media Server的IP来源地址。

              这个资料栏接受具体IP地址名单,*式的通配符,及以逗号分开的IP地址范围名单。例如:

              10.1.2.2将只允许10.1.2.2连接

              10.1.2.*将允许任何10.1.2.x的IP地址

              10.1.2.2-50将允许10.1.2.2-10.1.2.50范围内的IP地址连接

              您也可以利用逗号结合多个IP地址,例如:10.1.2.2,172.16.1.*,192.168.1-254

              特别IP地址127.0.0.1则表示允许浏览器连接到同一台电脑上的Logitech Media Server。 #miscellaneous setup strings @@ -8700,23 +8713,23 @@ SETUP_AUTHORIZE ZH_CN 密码保护 SETUP_AUTHORIZE_DESC - CS Můžete si zvolit ochranu heslem pro dálkové ovládání Squeezebox Server. Zvolte "Ochrana heslem" níže a zadejte uživatelské jméno a heslo, potom klikněte na Změnit. Od tohoto okamžiku budete muset při používání dálkového ovládání Squeezebox Server zadávat toto uživatelské jméno a heslo ve svém webovém prohlížeči. - DA Du kan vælge at beskytte adgangen til Squeezebox Servers fjernbetjening med en adgangskode. Vælg Beskyt med adgangskode, angiv et brugernavn og en adgangskode, og klik på Skift. Når du herefter ønsker at bruge Squeezebox Servers fjernbetjening, skal du angive brugernavnet og adgangskoden i browseren. - DE Sie können Squeezebox Server Remote Control mit einem Kennwort schützen. Klicken Sie unten auf 'Kennwortschutz', geben Sie einen Benutzernamen und ein Kennwort ein, und klicken Sie auf 'Ändern'. Wenn Sie dann Squeezebox Server Remote Control aufrufen, müssen Sie diesen Benutzernamen und das Kennwort eingeben. - EN You can choose to password protect Squeezebox Server Remote Control. Choose "Password protection" below and enter a username and password, then click Change. From that point on when you use Squeezebox Server Remote Control, you'll need to enter this username and password in your web browser. - ES Se puede optar por proteger Squeezebox Server Remote Control. Elija "Protección por contraseña" a continuación e introduzca un nombre de usuario y una contraseña. A continuación, haga clic en Cambiar. A partir de ese momento, cuando use Squeezebox Server Remote Control, deberá introducir ese nombre de usuario y esa contraseña en el navegador Web. - FI Halutessasi voit suojata Squeezebox Serverin kaukosäätimen salasanalla. Valitse alta Salasanasuojaus, anna käyttäjätunnus ja salasana ja valitse Muuta. Siitä eteenpäin sinun tarvitsee antaa käyttäjätunnus ja salasana selaimessa, kun käytät Squeezebox Serverin kaukosäädintä. - FR Vous pouvez protéger la télécommande du Squeezebox Server par un mot de passe. Sélectionnez "Protection par mot de passe" ci-dessous, puis cliquez sur le bouton "Modifier". Vous devrez saisir le mot de passe pour accéder à la télécommande du Squeezebox Server. - HE באפשרותך לבחור להגן על ממשק האינטרנט של Squeezebox Server באמצעות סיסמה. בחר את האפשרות "הגנה באמצעות סיסמה" שלהלן והזן שם משתמש וסיסמה, ולאחר מכן לחץ על 'שנה'. מרגע זה ואילך, כאשר תשתמש בממשק האינטרנט של Squeezebox Server, יהיה עליך להזין את שם המשתמש והסיסמה בדפדפן האינטרנט. - IT Si può scegliere di proteggere Squeezebox Server Remote Control con una password. Scegliere Protezione con password di seguito e inserire il nome utente e la password, quindi fare clic su Cambia. Da questo momento per utilizzare Squeezebox Server Remote Control è necessario inserire nel browser il nome utente e la password prescelti. - JA Squeezebox Serverのウェブインターフェースをパスワードで保護することができます。下から”パスワード保護”を選んで、ユーザー名とパスワードを指定して、「変更」をクリックして下さい。以降、Squeezebox Serverのウェブインターフェースにアクセスするにはユーザー名とパスワードが必要になります。 - NL Je kunt een wachtwoord instellen voor de Squeezebox Server Remote Control. Kies hieronder 'Wachtwoordbeveiliging' en voer een gebruikersnaam en wachtwoord in. Klik dan op 'Veranderen'. Vanaf dat moment moet je deze gebruikersnaam en dit wachtwoord invoeren om toegang te krijgen tot Squeezebox Server Remote Control. - NO Du kan passordbeskytte nettgrensesnittet til Squeezebox Server. Velg «Passordbeskyttelse» nedenfor, skriv inn brukernavn og passord, og trykk så på Endre. Etter det vil nettgrensesnittet til Squeezebox Server be deg om brukernavn og passord. - PL Program Squeezebox Server Remote Control można zabezpieczyć hasłem. Wybierz opcję „Ochrona hasłem” poniżej i wprowadź nazwę użytkownika oraz hasło, a następnie kliknij przycisk Zmień. Od tego momentu korzystanie z programu Squeezebox Server Remote Control będzie wymagało wprowadzenia tej nazwy użytkownika i hasła w przeglądarce internetowej. + CS Můžete si zvolit ochranu heslem pro dálkové ovládání Logitech Media Server. Zvolte "Ochrana heslem" níže a zadejte uživatelské jméno a heslo, potom klikněte na Změnit. Od tohoto okamžiku budete muset při používání dálkového ovládání Logitech Media Server zadávat toto uživatelské jméno a heslo ve svém webovém prohlížeči. + DA Du kan vælge at beskytte adgangen til Logitech Media Servers fjernbetjening med en adgangskode. Vælg Beskyt med adgangskode, angiv et brugernavn og en adgangskode, og klik på Skift. Når du herefter ønsker at bruge Logitech Media Servers fjernbetjening, skal du angive brugernavnet og adgangskoden i browseren. + DE Sie können Logitech Media Server Remote Control mit einem Kennwort schützen. Klicken Sie unten auf 'Kennwortschutz', geben Sie einen Benutzernamen und ein Kennwort ein, und klicken Sie auf 'Ändern'. Wenn Sie dann Logitech Media Server Remote Control aufrufen, müssen Sie diesen Benutzernamen und das Kennwort eingeben. + EN You can choose to password protect Logitech Media Server Remote Control. Choose "Password protection" below and enter a username and password, then click Change. From that point on when you use Logitech Media Server Remote Control, you'll need to enter this username and password in your web browser. + ES Se puede optar por proteger Logitech Media Server Remote Control. Elija "Protección por contraseña" a continuación e introduzca un nombre de usuario y una contraseña. A continuación, haga clic en Cambiar. A partir de ese momento, cuando use Logitech Media Server Remote Control, deberá introducir ese nombre de usuario y esa contraseña en el navegador Web. + FI Halutessasi voit suojata Logitech Media Serverin kaukosäätimen salasanalla. Valitse alta Salasanasuojaus, anna käyttäjätunnus ja salasana ja valitse Muuta. Siitä eteenpäin sinun tarvitsee antaa käyttäjätunnus ja salasana selaimessa, kun käytät Logitech Media Serverin kaukosäädintä. + FR Vous pouvez protéger la télécommande du Logitech Media Server par un mot de passe. Sélectionnez "Protection par mot de passe" ci-dessous, puis cliquez sur le bouton "Modifier". Vous devrez saisir le mot de passe pour accéder à la télécommande du Logitech Media Server. + HE באפשרותך לבחור להגן על ממשק האינטרנט של Logitech Media Server באמצעות סיסמה. בחר את האפשרות "הגנה באמצעות סיסמה" שלהלן והזן שם משתמש וסיסמה, ולאחר מכן לחץ על 'שנה'. מרגע זה ואילך, כאשר תשתמש בממשק האינטרנט של Logitech Media Server, יהיה עליך להזין את שם המשתמש והסיסמה בדפדפן האינטרנט. + IT Si può scegliere di proteggere Logitech Media Server Remote Control con una password. Scegliere Protezione con password di seguito e inserire il nome utente e la password, quindi fare clic su Cambia. Da questo momento per utilizzare Logitech Media Server Remote Control è necessario inserire nel browser il nome utente e la password prescelti. + JA Logitech Media Serverのウェブインターフェースをパスワードで保護することができます。下から”パスワード保護”を選んで、ユーザー名とパスワードを指定して、「変更」をクリックして下さい。以降、Logitech Media Serverのウェブインターフェースにアクセスするにはユーザー名とパスワードが必要になります。 + NL Je kunt een wachtwoord instellen voor de Logitech Media Server Remote Control. Kies hieronder 'Wachtwoordbeveiliging' en voer een gebruikersnaam en wachtwoord in. Klik dan op 'Veranderen'. Vanaf dat moment moet je deze gebruikersnaam en dit wachtwoord invoeren om toegang te krijgen tot Logitech Media Server Remote Control. + NO Du kan passordbeskytte nettgrensesnittet til Logitech Media Server. Velg «Passordbeskyttelse» nedenfor, skriv inn brukernavn og passord, og trykk så på Endre. Etter det vil nettgrensesnittet til Logitech Media Server be deg om brukernavn og passord. + PL Program Logitech Media Server Remote Control można zabezpieczyć hasłem. Wybierz opcję „Ochrona hasłem” poniżej i wprowadź nazwę użytkownika oraz hasło, a następnie kliknij przycisk Zmień. Od tego momentu korzystanie z programu Logitech Media Server Remote Control będzie wymagało wprowadzenia tej nazwy użytkownika i hasła w przeglądarce internetowej. PT Pode activar uma palavra chave para proteger a interface web. Escolha "Proteção por Palavra Chave" abaixo, escolha um nome de utilizador e uma palavra chave, e seleccione "Mudar". A partir desse momento necessitará de introduzir o utilizador e chave para entrar na interface web com o seu browser. - RU Можно задать пароль для пульта ДУ Squeezebox Server. Выберите "Защита паролем", введите имя пользователя и пароль, а затем нажмите кнопку "Изменить". С этого момента для входа в пульт ДУ Squeezebox Server в браузере потребуется вводить это имя пользователя и пароль. - SV Du kan välja att skydda fjärrkontrollen för Squeezebox Server med ett lösenord. Välj Lösenordsskydd nedan och ange ett användarnamn och ett lösenord. Klicka sedan på Ändra. Därefter måste du ange användarnamnet och lösenordet i webbläsaren varje gång du använder fjärrkontrollen. - ZH_CN 您可以选择将Squeezebox Server的网界面以密码保护。请选择《密码保护》并输入用户名和密码,然后单击《更动》。以后您使用Squeezebox Server的网界面时都需要输入这个用户名和密码。 + RU Можно задать пароль для пульта ДУ Logitech Media Server. Выберите "Защита паролем", введите имя пользователя и пароль, а затем нажмите кнопку "Изменить". С этого момента для входа в пульт ДУ Logitech Media Server в браузере потребуется вводить это имя пользователя и пароль. + SV Du kan välja att skydda fjärrkontrollen för Logitech Media Server med ett lösenord. Välj Lösenordsskydd nedan och ange ett användarnamn och ett lösenord. Klicka sedan på Ändra. Därefter måste du ange användarnamnet och lösenordet i webbläsaren varje gång du använder fjärrkontrollen. + ZH_CN 您可以选择将Logitech Media Server的网界面以密码保护。请选择《密码保护》并输入用户名和密码,然后单击《更动》。以后您使用Logitech Media Server的网界面时都需要输入这个用户名和密码。 SETUP_USERNAME CS Uživatelské jméno @@ -8820,40 +8833,21 @@ SETUP_REMOTESTREAMTIMEOUT ZH_CN 广播电台暂停时限 SETUP_REMOTESTREAMTIMEOUT_DESC - CS Můžete zadat dobu, po kterou se Squeezebox Server bude pokoušet připojit k internetovému rádiu nebo jinému zdroji. Níže zadejte dobu v sekundách. - DA Du kan angive hvor lang tid Squeezebox Server skal forsøge at etablere forbindelse til internetradiostationer eller andre kilder før der gives op. Angiv tidsrummet i sekunder nedenfor. - DE Sie können festlegen, wie lange Squeezebox Server versucht, eine Verbindung zu einem Internetradiosender oder einer anderen Quelle herzustellen. Geben Sie die Wartezeit in Sekunden ein. - EN You can set the length of time that Squeezebox Server will try to connect to an internet radio station or other source before giving up. Enter the amount of time, in seconds, below. - ES Se puede establecer el tiempo en el que Squeezebox Server tratará de conectarse a una emisora de radio por Internet o a otro origen antes de abandonar. Introduzca el tiempo, en segundos, a continuación. - FI Voit määrittää ajan, jonka Squeezebox Server yrittää muodostaa yhteyttä internet-radiokanavaan tai muuhun lähteeseen, ennen kuin se antaa periksi. Kirjoita aika sekunteina alle. - FR Vous pouvez définir la durée maximale pendant laquelle le Squeezebox Server tentera de se connecter à une radio Internet ou à une autre source distante. Spécifiez cette durée en secondes ci-dessous. - HE באפשרותך להגדיר את משך הזמן שבו Squeezebox Server ינסה להתחבר לתחנת רדיו באינטרנט או למקור אחר לפני שיפסיק. הזן את פרק הזמן, בשניות, בשדה שלהלן. - IT È possibile impostare l'intervallo di tempo durante il quale Squeezebox Server tenta di connettersi a una radio Internet o a un'altra sorgente prima di abbandonare il tentativo. Inserire la durata in secondi qui sotto. - NL Je kunt instellen hoe lang Squeezebox Server moet proberen een verbinding te maken met een internetradiostation of andere bron, voordat Squeezebox Server het opgeeft. Voer hieronder de tijd in seconden in: - NO Du kan angi hvor lenge Squeezebox Server skal forsøke å få kontakt med Internett-radiostasjonen eller andre kilder, før den gir opp. Angi tiden i sekunder nedenfor. - PL Można określić czas, przez jaki program Squeezebox Server będzie próbował nawiązać połączenie z internetową stacją radiową lub innym źródłem. Wprowadź czas w sekundach. - RU Можно настроить продолжительность попыток подключения Squeezebox Server к радиостанции Интернета или другому источнику. Введите ниже время в секундах. - SV Du kan ange hur länge Squeezebox Server ska försöka ansluta till en webbradiostation eller annan källa innan försöket ges upp. Ange tiden i sekunder nedan. - ZH_CN 您可以设置Squeezebox Server尝试连接到互联网电台或其它服务的时限。请在如下输入以秒为单位的时限。 - -MP3DIR - CS Vaše složka Hudba - DA Din musikmappe - DE Musikordner - EN Your Music Folder - ES Su carpeta de música - FI Musiikkikansio - FR Dossier de musique - HE תיקיית המוסיקה שלך - IT Cartella Musica - JA インターネットラジオ接続タイムアウト(秒): - NL Je muziekmap - NO Musikkmappe - PL Twój folder muzyki - PT Pasta de Música Pessoal - RU Папка "Музыка" - SV Din musikmapp - ZH_CN 您的音乐文件夹 + CS Můžete zadat dobu, po kterou se Logitech Media Server bude pokoušet připojit k internetovému rádiu nebo jinému zdroji. Níže zadejte dobu v sekundách. + DA Du kan angive hvor lang tid Logitech Media Server skal forsøge at etablere forbindelse til internetradiostationer eller andre kilder før der gives op. Angiv tidsrummet i sekunder nedenfor. + DE Sie können festlegen, wie lange Logitech Media Server versucht, eine Verbindung zu einem Internetradiosender oder einer anderen Quelle herzustellen. Geben Sie die Wartezeit in Sekunden ein. + EN You can set the length of time that Logitech Media Server will try to connect to an internet radio station or other source before giving up. Enter the amount of time, in seconds, below. + ES Se puede establecer el tiempo en el que Logitech Media Server tratará de conectarse a una emisora de radio por Internet o a otro origen antes de abandonar. Introduzca el tiempo, en segundos, a continuación. + FI Voit määrittää ajan, jonka Logitech Media Server yrittää muodostaa yhteyttä internet-radiokanavaan tai muuhun lähteeseen, ennen kuin se antaa periksi. Kirjoita aika sekunteina alle. + FR Vous pouvez définir la durée maximale pendant laquelle le Logitech Media Server tentera de se connecter à une radio Internet ou à une autre source distante. Spécifiez cette durée en secondes ci-dessous. + HE באפשרותך להגדיר את משך הזמן שבו Logitech Media Server ינסה להתחבר לתחנת רדיו באינטרנט או למקור אחר לפני שיפסיק. הזן את פרק הזמן, בשניות, בשדה שלהלן. + IT È possibile impostare l'intervallo di tempo durante il quale Logitech Media Server tenta di connettersi a una radio Internet o a un'altra sorgente prima di abbandonare il tentativo. Inserire la durata in secondi qui sotto. + NL Je kunt instellen hoe lang Logitech Media Server moet proberen een verbinding te maken met een internetradiostation of andere bron, voordat Logitech Media Server het opgeeft. Voer hieronder de tijd in seconden in: + NO Du kan angi hvor lenge Logitech Media Server skal forsøke å få kontakt med Internett-radiostasjonen eller andre kilder, før den gir opp. Angi tiden i sekunder nedenfor. + PL Można określić czas, przez jaki program Logitech Media Server będzie próbował nawiązać połączenie z internetową stacją radiową lub innym źródłem. Wprowadź czas w sekundach. + RU Можно настроить продолжительность попыток подключения Logitech Media Server к радиостанции Интернета или другому источнику. Введите ниже время в секундах. + SV Du kan ange hur länge Logitech Media Server ska försöka ansluta till en webbradiostation eller annan källa innan försöket ges upp. Ange tiden i sekunder nedan. + ZH_CN 您可以设置Logitech Media Server尝试连接到互联网电台或其它服务的时限。请在如下输入以秒为单位的时限。 LANGUAGE CS Jazyk @@ -8908,7 +8902,7 @@ SETUP_GROUPDISCS_DESC PL Możliwe jest określenie, czy zestawy kilku dysków są traktowane jako pojedynczy album (z jedną nazwą) czy jako kilka albumów, gdzie każdy dysk ma unikatową nazwę, na przykład „Tytuł albumu (dysk 2 z 3)”. Zmiana tego ustawienia spowoduje ponowne przeszukanie biblioteki muzyki. RU Можно указать, рассматривать ли набор из нескольких дисков как единый альбом (с единым именем) или как несколько альбомов, у каждого из которых свое уникальное имя для каждого из дисков, например "Название альбома (диск 2 из 3)". При изменении этой настройки будет запущено повторное сканирование медиатеки. SV Du kan ange om de ingående skivorna i en box ska behandlas som ett album eller flera separata album. Om du ändrar den här inställningen söks musikbiblioteket igenom på nytt. - ZH_CN 您可以指定由多个光碟组成的合集是否视为一个单一的乐谱帖(以一个名字)或保持为个别单独的专辑。例如“专辑标题(光碟1)”。更动此设置Squeezebox Server将开始重新扫描您的音乐库。 + ZH_CN 您可以指定由多个光碟组成的合集是否视为一个单一的乐谱帖(以一个名字)或保持为个别单独的专辑。例如“专辑标题(光碟1)”。更动此设置Logitech Media Server将开始重新扫描您的音乐库。 SETUP_GROUPDISCS_0 CS Považovat vícediskové sady za více alb @@ -9097,19 +9091,19 @@ SETUP_SN_SYNC SV mysqueezebox.com-integration SETUP_SN_SYNC_DESC - CS Standardně je mnoho nastavení přehrávače synchronizováno mezi Squeezebox Server a mysqueezebox.com. Tuto funkci vypnete volbou Zakázat. - DA Som standard synkroniseres mange af afspillerindstillingerne mellem Squeezebox Server og mysqueezebox.com. Du kan deaktivere denne funktion ved at vælge Deaktiver nedenfor. - DE Standardmäßig werden zahlreiche Player-Einstellungen zwischen Squeezebox Server und mysqueezebox.com synchronisiert. Hier können Sie diese Funktionalität deaktivieren. - EN By default, many player settings are synchronized between Squeezebox Server and mysqueezebox.com. To disable this feature, select the Disabled option below. - ES De modo predeterminado, muchas configuraciones de reproductor se sincronizan entre Squeezebox Server y mysqueezebox.com. Para desactivar esta función, seleccione la opción Desactivado a continuación. - FI Monet soitinasetukset on synkronoitu oletuksena Squeezebox Serverin ja mysqueezebox.comin välillä. Jos haluat poistaa tämän toiminnon käytöstä, valitse alta Poista käytöstä. - FR Par défaut, de nombreux réglages de platine sont synchronisés entre le Squeezebox Server et mysqueezebox.com. Pour désactiver cette fonctionnalité, sélectionnez l'option appropriée ci-dessous. - IT Per impostazione predefinita numerose impostazioni del lettore in Squeezebox Server e mysqueezebox.com sono sincronizzate. Per disattivare questa caratteristica, selezionare l'opzione Disattiva in basso. - NL Standaard worden vele muzieksysteeminstellingen tussen Squeezebox Server en mysqueezebox.com gesynchroniseerd. Als je deze functie wilt uitschakelen, selecteer je de optie Uitgeschakeld hieronder. - NO Som standard er mange spillerinnstillinger synkronisert mellom Squeezebox Server og mysqueezebox.com. Hvis du vil deaktivere denne funksjonen, velger du Deaktivert nedenfor. - PL Domyślnie wiele ustawień odtwarzacza jest synchronizowanych między programem Squeezebox Server a usługą mysqueezebox.com. Aby wyłączyć tę funkcję, wybierz opcję Wyłączone poniżej. - RU Многие настройки плеера по умолчанию синхронизованы между Squeezebox Server и mysqueezebox.com. Чтобы отключить эту возможность, выберите ниже параметр "Отключено". - SV Som standard synkroniseras många spelarinställningar mellan Squeezebox Server och mysqueezebox.com. Du avaktiverar funktionen genom att välja Avaktiverat nedan. + CS Standardně je mnoho nastavení přehrávače synchronizováno mezi Logitech Media Server a mysqueezebox.com. Tuto funkci vypnete volbou Zakázat. + DA Som standard synkroniseres mange af afspillerindstillingerne mellem Logitech Media Server og mysqueezebox.com. Du kan deaktivere denne funktion ved at vælge Deaktiver nedenfor. + DE Standardmäßig werden zahlreiche Player-Einstellungen zwischen Logitech Media Server und mysqueezebox.com synchronisiert. Hier können Sie diese Funktionalität deaktivieren. + EN By default, many player settings are synchronized between Logitech Media Server and mysqueezebox.com. To disable this feature, select the Disabled option below. + ES De modo predeterminado, muchas configuraciones de reproductor se sincronizan entre Logitech Media Server y mysqueezebox.com. Para desactivar esta función, seleccione la opción Desactivado a continuación. + FI Monet soitinasetukset on synkronoitu oletuksena Logitech Media Serverin ja mysqueezebox.comin välillä. Jos haluat poistaa tämän toiminnon käytöstä, valitse alta Poista käytöstä. + FR Par défaut, de nombreux réglages de platine sont synchronisés entre le Logitech Media Server et mysqueezebox.com. Pour désactiver cette fonctionnalité, sélectionnez l'option appropriée ci-dessous. + IT Per impostazione predefinita numerose impostazioni del lettore in Logitech Media Server e mysqueezebox.com sono sincronizzate. Per disattivare questa caratteristica, selezionare l'opzione Disattiva in basso. + NL Standaard worden vele muzieksysteeminstellingen tussen Logitech Media Server en mysqueezebox.com gesynchroniseerd. Als je deze functie wilt uitschakelen, selecteer je de optie Uitgeschakeld hieronder. + NO Som standard er mange spillerinnstillinger synkronisert mellom Logitech Media Server og mysqueezebox.com. Hvis du vil deaktivere denne funksjonen, velger du Deaktivert nedenfor. + PL Domyślnie wiele ustawień odtwarzacza jest synchronizowanych między programem Logitech Media Server a usługą mysqueezebox.com. Aby wyłączyć tę funkcję, wybierz opcję Wyłączone poniżej. + RU Многие настройки плеера по умолчанию синхронизованы между Logitech Media Server и mysqueezebox.com. Чтобы отключить эту возможность, выберите ниже параметр "Отключено". + SV Som standard synkroniseras många spelarinställningar mellan Logitech Media Server och mysqueezebox.com. Du avaktiverar funktionen genom att välja Avaktiverat nedan. SETUP_SN_SYNC_ENABLE CS Povolit, udržovat nastavení přehrávače v synchronizaci. @@ -9202,19 +9196,19 @@ SETUP_SN_REPORT_STATS_DISABLE SV Nej, rapportera inte statistik. SETUP_NO_JAVASCRIPT - CS Před přístupem ke Squeezebox Server se prosím ujistěte, že používáte poslední prohlížeč (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 nebo vyšší), a že je na vašem prohlížeči povolen JavaScript. Alternativně můžete používat jednodušší skin, např.Klasický nebo Do ruky (optimalizován pro malé obrazovky). - DA Du skal bruge en forholdsvis ny browser for at få adgang til Squeezebox Server (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 eller senere), og JavaScript skal være aktiveret i browseren. Alternativt kan du benytte et enklere layout, fx Klassisk eller Håndholdt (optimeret til små skærme). - DE Für den Zugriff auf Squeezebox Server benötigen Sie eine aktuelle Version eines Browsers (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7 +, Opera 9 oder höher). Außerdem muss im Browser JavaScript aktiviert sein. Sie können auch eine einfachere Benutzeroberfläche wie Classic oder Handheld (für kleine Bildschirme optimiert) wählen. - EN In order to access Squeezebox Server, please make sure you are using a recent browser (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 or later), and JavaScript is enabled in your browser. Alternatively you can use a simpler skin, such as Classic or Handheld (optimized for small screens). - ES Para acceder a Squeezebox Server, debe utilizar un navegador reciente (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7 o posterior, Opera 9 o posterior) con la opción JavaScript activada. O puede utilizar una máscara más simple, por ejemplo una Classic o Handheld (optimizada para pantallas pequeñas). - FI Squeezebox Serverin käyttö edellyttää, että käytät uutta selainta (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 ja uudemmat). Lisäksi JavaScriptin on oltava käytössä selaimessa. Vaihtoehtoisesti voit käyttää yksinkertaisempaa olemusta, kuten esimerkiksi vaihtoehtoa Classic tai Handheld (optimoitu pienille näytöille). - FR Pour accéder au Squeezebox Server, utilisez un navigateur récent (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 ou version ultérieure) et activez JavaScript pour ce navigateur. Vous pouvez également utiliser une apparence d'interface plus légère, telle que Classic ou Handheld (optimisée pour les écrans de petite taille). - IT Per accedere a Squeezebox Server, assicurarsi di utilizzare un browser recente (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7 o versioni successive, Opera 9 o versioni successive) e di attivare JavaScript all'interno del browser. In alternativa è possibile utilizzare una skin quale Classic o Handheld (ottimizzata per schermi piccoli). - NL Je moet een recente browser gebruiken (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 of later) en JavaScript in je browser inschakelen om Squeezebox Server te kunnen oproepen. Je kunt ook een eenvoudigere skin gebruiken, zoals Classic of Handheld (geoptimaliseerd voor kleine schermen). - NO Du må bruke en oppdatert versjon av nettleseren (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 eller nyere) samt ha JavaScript aktivert i nettleseren for å komme inn på Squeezebox Server. Du kan eventuelt bruke et enklere grensesnitt, som Classic eller Handheld (laget for små skjermer). - PL Aby uzyskać dostęp do programu Squeezebox Server, sprawdź czy korzystasz z najnowszej przeglądarki (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 lub nowszej), a obsługa skryptów JavaScript w przeglądarce jest włączona. Można także użyć prostej karnacji, takiej jak Klasyczna lub Urządzenie przenośne (zoptymalizowana dla małych ekranów). - RU Для доступа к Squeezebox Server необходим современный обозреватель (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 или более поздние версии), в котором включен JavaScript. Либо можно использовать упрощенную оболочку, например Classic или Handheld (специально для устройств с маленьким экраном). - SV Använd en aktuell webbläsare (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 eller senare) och kontrollera att JavaScript är aktiverat i webbläsaren för att få tillgång till Squeezebox Server. Alternativt kan du använda ett enklare skal, t.ex. Classic eller Handheld (optimerat för små skärmar). + CS Před přístupem ke Logitech Media Server se prosím ujistěte, že používáte poslední prohlížeč (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 nebo vyšší), a že je na vašem prohlížeči povolen JavaScript. Alternativně můžete používat jednodušší skin, např.Klasický nebo Do ruky (optimalizován pro malé obrazovky). + DA Du skal bruge en forholdsvis ny browser for at få adgang til Logitech Media Server (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 eller senere), og JavaScript skal være aktiveret i browseren. Alternativt kan du benytte et enklere layout, fx Klassisk eller Håndholdt (optimeret til små skærme). + DE Für den Zugriff auf Logitech Media Server benötigen Sie eine aktuelle Version eines Browsers (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7 +, Opera 9 oder höher). Außerdem muss im Browser JavaScript aktiviert sein. Sie können auch eine einfachere Benutzeroberfläche wie Classic oder Handheld (für kleine Bildschirme optimiert) wählen. + EN In order to access Logitech Media Server, please make sure you are using a recent browser (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 or later), and JavaScript is enabled in your browser. Alternatively you can use a simpler skin, such as Classic or Handheld (optimized for small screens). + ES Para acceder a Logitech Media Server, debe utilizar un navegador reciente (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7 o posterior, Opera 9 o posterior) con la opción JavaScript activada. O puede utilizar una máscara más simple, por ejemplo una Classic o Handheld (optimizada para pantallas pequeñas). + FI Logitech Media Serverin käyttö edellyttää, että käytät uutta selainta (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 ja uudemmat). Lisäksi JavaScriptin on oltava käytössä selaimessa. Vaihtoehtoisesti voit käyttää yksinkertaisempaa olemusta, kuten esimerkiksi vaihtoehtoa Classic tai Handheld (optimoitu pienille näytöille). + FR Pour accéder au Logitech Media Server, utilisez un navigateur récent (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 ou version ultérieure) et activez JavaScript pour ce navigateur. Vous pouvez également utiliser une apparence d'interface plus légère, telle que Classic ou Handheld (optimisée pour les écrans de petite taille). + IT Per accedere a Logitech Media Server, assicurarsi di utilizzare un browser recente (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7 o versioni successive, Opera 9 o versioni successive) e di attivare JavaScript all'interno del browser. In alternativa è possibile utilizzare una skin quale Classic o Handheld (ottimizzata per schermi piccoli). + NL Je moet een recente browser gebruiken (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 of later) en JavaScript in je browser inschakelen om Logitech Media Server te kunnen oproepen. Je kunt ook een eenvoudigere skin gebruiken, zoals Classic of Handheld (geoptimaliseerd voor kleine schermen). + NO Du må bruke en oppdatert versjon av nettleseren (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 eller nyere) samt ha JavaScript aktivert i nettleseren for å komme inn på Logitech Media Server. Du kan eventuelt bruke et enklere grensesnitt, som Classic eller Handheld (laget for små skjermer). + PL Aby uzyskać dostęp do programu Logitech Media Server, sprawdź czy korzystasz z najnowszej przeglądarki (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 lub nowszej), a obsługa skryptów JavaScript w przeglądarce jest włączona. Można także użyć prostej karnacji, takiej jak Klasyczna lub Urządzenie przenośne (zoptymalizowana dla małych ekranów). + RU Для доступа к Logitech Media Server необходим современный обозреватель (Firefox®, Apple Safari®, Microsoft® Internet Explorer 7+, Opera 9 или более поздние версии), в котором включен JavaScript. Либо можно использовать упрощенную оболочку, например Classic или Handheld (специально для устройств с маленьким экраном). + SV Använd en aktuell webbläsare (Firefox®, Apple Safari®, Microsoft® Internet Explorer 6, Opera 9 eller senare) och kontrollera att JavaScript är aktiverat i webbläsaren för att få tillgång till Logitech Media Server. Alternativt kan du använda ett enklare skal, t.ex. Classic eller Handheld (optimerat för små skärmar). SETUP_WIZARD_SQN_PLEASE CS Přihlašte se svojí emailovou adresou mysqueezebox.com a heslem a pokračujte . @@ -9265,7 +9259,7 @@ SETUP_WIZARD_SHARE_WIN CS

              Pokud chcete přistupovat ke své hudbě uložené na jiném počítači nebo na sdíleném síťovém disku, ujistěte se, že sdílený disk je připojen a je dostupný z vašeho souborového systému. Jakmile je disk dostupný, objeví se ve výběrovém okně vlevo. Pokud znáte cestu k disku, můžete ji zadat níže. DA

              Hvis du vil have adgang til musikfiler som ligger på en anden computer eller et delt netværksdrev, skal du sikre dig at det delte drev er tilsluttet og der er adgang til det. Når drevet er tilgængeligt, kan det vælges i vinduet til venstre. Hvis du kender stien til drevet du vil have adgang til, kan du angive den nedenfor. DE

              Wenn Sie auf Musik, die auf einem anderen Computer oder einem Netzlaufwerk gespeichert ist, zugreifen möchten, vergewissern Sie sich, dass das Laufwerk im Dateisystem verfügbar ist. Verfügbare Laufwerke werden im Auswahlfenster links angezeigt. Wenn Sie den Pfad des gewünschten Laufwerks kennen, geben Sie ihn unten ein. - EN

              If you want to access any of your music stored on another computer or a shared network drive, please make sure that the shared drive is mounted and available to your file system. Once the drive is available, it will appear in the selection window to the left. If you know the path of the drive you wish to access you can enter it below. + EN

              If you want to access any of your media stored on another computer or a shared network drive, please make sure that the shared drive is mounted and available to your file system. Once the drive is available, it will appear in the selection window to the left. If you know the path of the drive you wish to access you can enter it below. ES

              Si desea acceder a música almacenada en otro ordenador o en una unidad de red compartida, asegúrese de que ésta está montada y disponible para su sistema de archivos. Cuando la unidad esté disponible, aparecerá en la ventana de selección de la izquierda. Si conoce la ruta de la unidad a la que quiere acceder, puede introducirla aquí. FI

              Jos haluat käyttää musiikkitiedostoja, jotka on tallennettu toiseen tietokoneeseen tai jaettuun verkkoasemaan, varmista että jaettu asema on kiinnitetty ja tiedostojärjestelmän käytettävissä. Kun asema on käytettävissä, se ilmestyy näkyviin vasemmalla olevaan valintaikkunaan. Jos tiedät käyttämäsi aseman polun, kirjoita se alle. FR

              Si vous souhaitez accéder à des morceaux stockés sur un autre ordinateur ou sur un lecteur partagé en réseau, vérifiez que le lecteur est monté et qu'il est disponible dans votre système de fichiers. Si le lecteur est disponible, il s'affiche dans la fenêtre de sélection de gauche. Si vous connaissez le chemin d'accès au lecteur, vous pouvez le spécifier ci-dessous. @@ -9280,7 +9274,7 @@ SETUP_WIZARD_SHARE_OTHERS CS

              Pokud chcete přistupovat ke své hudbě uložené na jiném počítači nebo na sdílené síťové jednotce, ujistěte se, že sdílena jednotka je připojena a je dostupná z vašeho souborového systému. Jakmile je jednotka dostupná, objeví se ve výběrovém okně vlevo. Pokud znáte cestu k jednotce, ke které chcete přistupovat, můžete ji zadat níže. DA

              Hvis du vil have adgang til musikfiler som ligger på en anden computer eller et delt netværksdrev, skal du sikre dig at det delte drev er tilsluttet og der er adgang til det. Når drevet er tilgængeligt, kan det vælges i vinduet til venstre. Hvis du kender stien til drevet du vil have adgang til, kan du angive den nedenfor. DE

              Wenn Sie auf Musik, die auf einem anderen Computer oder einem Netzwerk-Volume gespeichert ist, zugreifen möchten, vergewissern Sie sich, dass das Volume im Dateisystem verfügbar ist. Verfügbare Volumes werden im Auswahlfenster links angezeigt. Wenn Sie den Pfad des gewünschten Volume kennen, geben Sie ihn unten ein. - EN

              If you want to access any of your music stored on another computer or a shared network volume, please make sure that the shared volume is mounted and available to your file system. Once the volume is available, it will appear in the selection window to the left. If you know the path of the volume you wish to access you can enter it below. + EN

              If you want to access any of your media stored on another computer or a shared network volume, please make sure that the shared volume is mounted and available to your file system. Once the volume is available, it will appear in the selection window to the left. If you know the path of the volume you wish to access you can enter it below. ES

              Si desea acceder a música almacenada en otro ordenador o en un volumen de red compartido, asegúrese de que éste está montado y disponible para su sistema de archivos. Cuando el volumen esté disponible, aparecerá en la ventana de selección de la izquierda. Si conoce la ruta del volumen al que quiere acceder, puede introducirla aquí. FI

              Jos haluat käyttää musiikkitiedostoja, jotka on tallennettu toiseen tietokoneeseen tai jaettuun verkkoasemaan, varmista että jaettu asema on kiinnitetty ja tiedostojärjestelmän käytettävissä. Kun asema on käytettävissä, se ilmestyy näkyviin vasemmalla olevaan valintaikkunaan. Jos tiedät käyttämäsi aseman polun, kirjoita se alle. FR

              Si vous souhaitez accéder à des morceaux stockés sur un autre ordinateur ou sur un volume partagé en réseau, vérifiez que le volume est monté et qu'il est disponible dans votre système de fichiers. Si le volume est disponible, il s'affiche dans la fenêtre de sélection de gauche. Si vous connaissez le chemin d'accès au volume, vous pouvez le spécifier ci-dessous. @@ -9322,7 +9316,7 @@ SETUP_WIZARD_PLAYLISTDIR_DESC SV Ange sökväg till mappen med dina spellistor. SETUP_WIZARD_SUMMARY_DESC - CS Squeezebox Server nyní používá následující nastavení: + CS Logitech Media Server nyní používá následující nastavení: DA Squeezebox benytter nu følgende indstillinger: DE Squeezebox nutzt jetzt folgende Einstellungen: EN Squeezebox is now using the following settings: @@ -9367,34 +9361,34 @@ SETUP_WIZARD_SUMMARY_MUSICSOURCE SV Musikkälla SETUP_WIZARD_DONE - CS Nastavení Squeezebox Server ukončeno! - DA Konfigurationen af Squeezebox Server er gennemført. - DE Squeezebox Server wurde eingerichtet! - EN Squeezebox Server Setup Done! - ES Configuración de Squeezebox Server completada. - FI Squeezebox Serverin asennus on valmis - FR Configuration du Squeezebox Server effectuée. - IT Configurazione di Squeezebox Server completata - NL Installatie van Squeezebox Server voltooid! - NO Konfigurasjonen for Squeezebox Server er ferdig! - PL Konfiguracja programu Squeezebox Server została zakończona! - RU Установка Squeezebox Server завершена! - SV Konfigurationen av Squeezebox Server är klar! + CS Nastavení Logitech Media Server ukončeno! + DA Konfigurationen af Logitech Media Server er gennemført. + DE Logitech Media Server wurde eingerichtet! + EN Logitech Media Server Setup Done! + ES Configuración de Logitech Media Server completada. + FI Logitech Media Serverin asennus on valmis + FR Configuration du Logitech Media Server effectuée. + IT Configurazione di Logitech Media Server completata + NL Installatie van Logitech Media Server voltooid! + NO Konfigurasjonen for Logitech Media Server er ferdig! + PL Konfiguracja programu Logitech Media Server została zakończona! + RU Установка Logitech Media Server завершена! + SV Konfigurationen av Logitech Media Server är klar! SETUP_WIZARD_DONE_DESC - CS Vaše nastavení byla uložena. Nyní můžete začít používat váš Squeezebox.

              Pokud jste zvolili místní zdroj hudby, Squeezebox Server nyní začne indexovat vaši sbírku. Prosím vyčkejte — brzy budete mít přístup ke všem svým hudebním souborům.

              Nyní můžete zavřít toto okno nebo kliknutím sem pokračovat na dálkové ovládání Squeezebox Server. - DA Indstillingerne er gemt. Nu kan du begynde at bruge Squeezebox.

              Hvis du valgte en lokal musikkilde, begynder Squeezebox Server at indeksere din musiksamling. Du skal bare have lidt tålmodighed, det varer ikke længe før du kan lytte til alle dine musikfiler.

              Du kan lukke vinduet eller klikke her for at gå til Squeezebox Servers fjernbetjening. - DE Die Einstellungen wurden gespeichert. Sie können Squeezebox jetzt nutzen.

              Wenn Sie eine lokale Musikquelle gewählt haben, beginnt Squeezebox Server mit dem Indizieren der Sammlung. Wir bitten um etwas Geduld. Sie erhalten bald Zugriff auf alle Musikdateien.

              Sie können dieses Fenster schließen oder hier klicken, um die Squeezebox Server-Fernbedienung aufzurufen. - EN Your settings have been saved. You're now ready to use your Squeezebox.

              If you selected a local music source, Squeezebox Server will now start indexing your collection. Please be patient — you'll soon have access to all of your music files.

              You can now close this window or click here to proceed to Squeezebox Server Remote Control. - ES La configuración se ha guardado. Ya puede empezar a utilizar Squeezebox.

              Si ha seleccionado un origen de música local, Squeezebox Server iniciará la creación de un índice de su colección. Le rogamos que tenga paciencia; no tardará en tener acceso a todos sus archivos de música.

              Ahora puede cerrar esta ventana o hacer clic aquí para pasar a Squeezebox Server Remote Control. - FI Asetukset on tallennettu. Olet nyt valmis käyttämään Squeezeboxia.

              Jos valitsit paikallisen musiikkilähteen, Squeezebox Server aloittaa nyt kokoelmasi indeksoinnin. Ole kärsivällinen — voit pian käyttää kaikkia musiikkitiedostojasi.

              Voit nyt sulkea tämän ikkunan tai jatkaa Squeezebox Serverin kaukosäätimeen napsauttamalla tästä. - FR Vos réglages ont été enregistrés. Vous pouvez maintenant utiliser la Squeezebox.

              Si vous avez sélectionné une source musicale locale, le Squeezebox Server va procéder à l'indexation de votre collection. Veuillez patienter pendant l'opération. Vous allez bientôt pouvoir accéder à vos fichiers musicaux.

              Vous pouvez fermer cette fenêtre ou cliquer ici pour accéder à la télécommande du Squeezebox Server. - IT Le impostazioni sono state salvate. È ora possibile utilizzare lo Squeezebox.

              Se è stata selezionata una sorgente musicale locale, Squeezebox Server avvierà ora l'indicizzazione della raccolta. Attendere. I file musicali saranno accessibili tra qualche istante.

              Chiudere questa finestra o fare clic qui per passare a Squeezebox Server Remote Control. - NL Je instellingen zijn opgeslagen. Je kunt Squeezebox nu gebruiken.

              Als je een lokale muziekbron hebt geselecteerd, indexeert Squeezebox nu je collectie. Een moment geduld — je kunt al snel bij al je muziekbestanden.

              Je kunt dit venster nu sluiten of hier klikken om naar Squeezebox Server Remote Control te gaan. - NO Innstillingene er lagret. Nå er du klar til å ta i bruk Squeezebox.

              Hvis du velger en lokal musikkilde, vil Squeezebox Server nå begynne å indeksere samlingen din. Dette kan ta litt tid, men du vil snart ha tilgang til alle musikkfilene dine.

              Du kan nå lukke dette vinduet, eller klikke her for å gå videre til nettgrensesnittet til Squeezebox Server. - PL Ustawienia zostały zapisane. Możesz teraz korzystać z programu Squeezebox.

              Jeżeli wybrano lokalne źródło muzyki, program Squeezebox Server rozpocznie indeksowanie kolekcji. Prosimy o cierpliwość — wkrótce uzyskasz dostęp do wszystkich plików muzycznych.

              Możesz teraz zamknąć to okno lub kliknąć tutaj, aby przejść do programu Squeezebox Server Remote Control. - RU Ваши настройки сохранены. Теперь можно начать работу с программой Squeezebox.

              Если выбран локальный источник музыкальных файлов, Squeezebox Server начнет индексировать коллекцию. Пожалуйста, подождите: скоро все музыкальные файлы будут доступны.

              Теперь можно закрыть это окно или щелкнуть здесь, чтобы перейти к пульту ДУ Squeezebox Server. - SV Inställningarna har sparats. Nu kan du börja använda Squeezebox.

              Om du har valt en lokal musikkälla kommer din samling nu att indexeras. Det kan ta en liten stund, men du får snart tillgång till dina musikfiler.

              Nu kan du stänga det här fönstret eller klicka här för att fortsätta till fjärrstyrningen av Squeezebox Server. + CS Vaše nastavení byla uložena. Nyní můžete začít používat váš Squeezebox.

              Pokud jste zvolili místní zdroj hudby, Logitech Media Server nyní začne indexovat vaši sbírku. Prosím vyčkejte — brzy budete mít přístup ke všem svým hudebním souborům.

              Nyní můžete zavřít toto okno nebo kliknutím sem pokračovat na dálkové ovládání Logitech Media Server. + DA Indstillingerne er gemt. Nu kan du begynde at bruge Squeezebox.

              Hvis du valgte en lokal musikkilde, begynder Logitech Media Server at indeksere din musiksamling. Du skal bare have lidt tålmodighed, det varer ikke længe før du kan lytte til alle dine musikfiler.

              Du kan lukke vinduet eller klikke her for at gå til Logitech Media Servers fjernbetjening. + DE Die Einstellungen wurden gespeichert. Sie können Squeezebox jetzt nutzen.

              Wenn Sie eine lokale Musikquelle gewählt haben, beginnt Logitech Media Server mit dem Indizieren der Sammlung. Wir bitten um etwas Geduld. Sie erhalten bald Zugriff auf alle Musikdateien.

              Sie können dieses Fenster schließen oder hier klicken, um die Logitech Media Server-Fernbedienung aufzurufen. + EN Your settings have been saved. You're now ready to use your Squeezebox.

              If you selected a local music source, Logitech Media Server will now start indexing your collection. Please be patient — you'll soon have access to all of your music files.

              You can now close this window or click here to proceed to Logitech Media Server Remote Control. + ES La configuración se ha guardado. Ya puede empezar a utilizar Squeezebox.

              Si ha seleccionado un origen de música local, Logitech Media Server iniciará la creación de un índice de su colección. Le rogamos que tenga paciencia; no tardará en tener acceso a todos sus archivos de música.

              Ahora puede cerrar esta ventana o hacer clic aquí para pasar a Logitech Media Server Remote Control. + FI Asetukset on tallennettu. Olet nyt valmis käyttämään Squeezeboxia.

              Jos valitsit paikallisen musiikkilähteen, Logitech Media Server aloittaa nyt kokoelmasi indeksoinnin. Ole kärsivällinen — voit pian käyttää kaikkia musiikkitiedostojasi.

              Voit nyt sulkea tämän ikkunan tai jatkaa Logitech Media Serverin kaukosäätimeen napsauttamalla tästä. + FR Vos réglages ont été enregistrés. Vous pouvez maintenant utiliser la Squeezebox.

              Si vous avez sélectionné une source musicale locale, le Logitech Media Server va procéder à l'indexation de votre collection. Veuillez patienter pendant l'opération. Vous allez bientôt pouvoir accéder à vos fichiers musicaux.

              Vous pouvez fermer cette fenêtre ou cliquer ici pour accéder à la télécommande du Logitech Media Server. + IT Le impostazioni sono state salvate. È ora possibile utilizzare lo Squeezebox.

              Se è stata selezionata una sorgente musicale locale, Logitech Media Server avvierà ora l'indicizzazione della raccolta. Attendere. I file musicali saranno accessibili tra qualche istante.

              Chiudere questa finestra o fare clic qui per passare a Logitech Media Server Remote Control. + NL Je instellingen zijn opgeslagen. Je kunt Squeezebox nu gebruiken.

              Als je een lokale muziekbron hebt geselecteerd, indexeert Squeezebox nu je collectie. Een moment geduld — je kunt al snel bij al je muziekbestanden.

              Je kunt dit venster nu sluiten of hier klikken om naar Logitech Media Server Remote Control te gaan. + NO Innstillingene er lagret. Nå er du klar til å ta i bruk Squeezebox.

              Hvis du velger en lokal musikkilde, vil Logitech Media Server nå begynne å indeksere samlingen din. Dette kan ta litt tid, men du vil snart ha tilgang til alle musikkfilene dine.

              Du kan nå lukke dette vinduet, eller klikke her for å gå videre til nettgrensesnittet til Logitech Media Server. + PL Ustawienia zostały zapisane. Możesz teraz korzystać z programu Squeezebox.

              Jeżeli wybrano lokalne źródło muzyki, program Logitech Media Server rozpocznie indeksowanie kolekcji. Prosimy o cierpliwość — wkrótce uzyskasz dostęp do wszystkich plików muzycznych.

              Możesz teraz zamknąć to okno lub kliknąć tutaj, aby przejść do programu Logitech Media Server Remote Control. + RU Ваши настройки сохранены. Теперь можно начать работу с программой Squeezebox.

              Если выбран локальный источник музыкальных файлов, Logitech Media Server начнет индексировать коллекцию. Пожалуйста, подождите: скоро все музыкальные файлы будут доступны.

              Теперь можно закрыть это окно или щелкнуть здесь, чтобы перейти к пульту ДУ Logitech Media Server. + SV Inställningarna har sparats. Nu kan du börja använda Squeezebox.

              Om du har valt en lokal musikkälla kommer din samling nu att indexeras. Det kan ta en liten stund, men du får snart tillgång till dina musikfiler.

              Nu kan du stänga det här fönstret eller klicka här för att fortsätta till fjärrstyrningen av Logitech Media Server. SETUP_WIZARD_NEXT CS Další @@ -12919,6 +12913,15 @@ BROWSE_MUSIC_FOLDER SV Musikmapp ZH_CN 浏览音乐文件夹 +BROWSE_VIDEO_FOLDER + EN Video Folder + +BROWSE_ALL_VIDEOS + EN All Videos + +BROWSE_ALL_PICTURES + EN All Pictures + SYNCHRONIZE CS Synchronizovat DA Synkroniser @@ -13298,46 +13301,46 @@ DELETE_WARNING ZH_CN 您确定要删除吗?请选择《确定删除》来删除您的播放表。 SCAN_WARNING - CS Squeezebox Server stále prohledává vaši knihovnu hudby,takže některé položky se v této oblasti ještě nezobrazí. - DA Squeezebox Server gennemsøger stadig din musiksamling. Det kan betyde at nogle numre endnu ikke vises her. - DE Squeezebox Server durchsucht immer noch den Musikordner. Deshalb werden evtl. einige Objekte noch nicht in diesem Bereich angezeigt. - EN Squeezebox Server is still scanning your music library, so some items may not appear in this area yet. - ES Squeezebox Server todavía está examinado la biblioteca de música, por lo que puede que algunos elementos no aparezcan aún en esta área. - FI Squeezebox Server tarkistaa yhä musiikkikirjastoasi. Jotkin kohteet eivät ehkä näy vielä tässä kohdassa. - FR Le Squeezebox Server n'a pas terminé d'analyser votre dossier de musique. Certains éléments peuvent ne pas apparaître dans la liste pour l'instant. - HE Squeezebox Server עדיין סורק את ספריית המוסיקה שלך, כך שייתכן שפריטים מסוימים טרם מופיעים באזור זה. - IT Analisi della libreria musicale in Squeezebox Server ancora in corso. Alcune voci potrebbero non essere ancora visualizzate in questa area. - JA Squeezebox Serverは、現在音楽ライブラリをスキャンしています。よって、いくつかのアイテムはまだ表示されていないかもしれません。 - NL De Squeezebox Server is bezig je muziekfolder te doorzoeken en toont daarom nog niet je hele muziekcollectie. - NO Squeezebox Server søker fremdeles i musikkbiblioteket, så noen elementer kan ennå mangle her. - PL Program Squeezebox Server nadal przeszukuje bibliotekę muzyczną, więc niektóre elementy mogą nie być jeszcze widoczne w tym obszarze. - PT O Squeezebox Server ainda está a analisar o arquivo musical, portanto é possível que não apareçam ainda alguns items nesta àrea. - RU Squeezebox Server продолжает сканирование медиатеки, поэтому в данной области некоторые элементы могут отсутствовать. + CS Logitech Media Server stále prohledává vaši knihovnu hudby,takže některé položky se v této oblasti ještě nezobrazí. + DA Logitech Media Server gennemsøger stadig din musiksamling. Det kan betyde at nogle numre endnu ikke vises her. + DE Logitech Media Server durchsucht immer noch den Musikordner. Deshalb werden evtl. einige Objekte noch nicht in diesem Bereich angezeigt. + EN Logitech Media Server is still scanning your media library, so some items may not appear in this area yet. + ES Logitech Media Server todavía está examinado la biblioteca de música, por lo que puede que algunos elementos no aparezcan aún en esta área. + FI Logitech Media Server tarkistaa yhä musiikkikirjastoasi. Jotkin kohteet eivät ehkä näy vielä tässä kohdassa. + FR Le Logitech Media Server n'a pas terminé d'analyser votre dossier de musique. Certains éléments peuvent ne pas apparaître dans la liste pour l'instant. + HE Logitech Media Server עדיין סורק את ספריית המוסיקה שלך, כך שייתכן שפריטים מסוימים טרם מופיעים באזור זה. + IT Analisi della libreria musicale in Logitech Media Server ancora in corso. Alcune voci potrebbero non essere ancora visualizzate in questa area. + JA Logitech Media Serverは、現在音楽ライブラリをスキャンしています。よって、いくつかのアイテムはまだ表示されていないかもしれません。 + NL De Logitech Media Server is bezig je muziekfolder te doorzoeken en toont daarom nog niet je hele muziekcollectie. + NO Logitech Media Server søker fremdeles i musikkbiblioteket, så noen elementer kan ennå mangle her. + PL Program Logitech Media Server nadal przeszukuje bibliotekę muzyczną, więc niektóre elementy mogą nie być jeszcze widoczne w tym obszarze. + PT O Logitech Media Server ainda está a analisar o arquivo musical, portanto é possível que não apareçam ainda alguns items nesta àrea. + RU Logitech Media Server продолжает сканирование медиатеки, поэтому в данной области некоторые элементы могут отсутствовать. SV Sökningen av ditt musikbibliotek pågår fortfarande, så det är inte säkert att alla objekt visas här än. - ZH_CN Squeezebox Server正在扫描您的音乐库,因此一些项目还未能在这里出现。 + ZH_CN Logitech Media Server正在扫描您的音乐库,因此一些项目还未能在这里出现。 HOME_SCAN_WARNING - CS Squeezebox Server nyní prohledává vaši knihovnu skladeb. Prosím, počkejte, může to chvíli trvat. - DA Squeezebox Server gennemsøger stadig dit musikbibliotek. Vent lidt, det kan godt tage et stykke tid. - DE Squeezebox Server liest die Musikbibliothek. Dieser Vorgang kann eine Weile dauern. - EN Squeezebox Server is still scanning your music library. Please be patient as this may take a while. - ES Squeezebox Server sigue examinado la biblioteca de música. Tenga paciencia ya que puede llevar cierto tiempo. - FI Squeezebox Server tarkistaa yhä musiikkikirjastoasi. Ole kärsivällinen, sillä tähän saattaa kulua hetki. - FR Le Squeezebox Server analyse le contenu de votre collection musicale. Veuillez patienter. - HE Squeezebox Server עדיין סורק את ספריית המוסיקה שלך. אנא המתן בסבלנות; הפעולה עשויה להימשך זמן מה. + CS Logitech Media Server nyní prohledává vaši knihovnu skladeb. Prosím, počkejte, může to chvíli trvat. + DA Logitech Media Server gennemsøger stadig dit musikbibliotek. Vent lidt, det kan godt tage et stykke tid. + DE Logitech Media Server liest die Musikbibliothek. Dieser Vorgang kann eine Weile dauern. + EN Logitech Media Server is still scanning your media library. Please be patient as this may take a while. + ES Logitech Media Server sigue examinado la biblioteca de música. Tenga paciencia ya que puede llevar cierto tiempo. + FI Logitech Media Server tarkistaa yhä musiikkikirjastoasi. Ole kärsivällinen, sillä tähän saattaa kulua hetki. + FR Le Logitech Media Server analyse le contenu de votre collection musicale. Veuillez patienter. + HE Logitech Media Server עדיין סורק את ספריית המוסיקה שלך. אנא המתן בסבלנות; הפעולה עשויה להימשך זמן מה. IT Ricerca nella libreria musicale in corso. Attendere. L'operazione potrebbe richiedere alcuni minuti. - NL Squeezebox Server is je muziekcollectie aan het scannen. Een ogenblik geduld. Dit kan even duren. - NO Squeezebox Server søker fremdeles i musikkbiblioteket ditt. Vær tålmodig, da dette kan ta en stund. - PL Program Squeezebox Server nadal przeszukuje bibliotekę muzyczną. Prosimy o cierpliwość - może to chwilę potrwać. - RU Squeezebox Server выполняет сканирование медиатеки. Пожалуйста, подождите. + NL Logitech Media Server is je muziekcollectie aan het scannen. Een ogenblik geduld. Dit kan even duren. + NO Logitech Media Server søker fremdeles i musikkbiblioteket ditt. Vær tålmodig, da dette kan ta en stund. + PL Program Logitech Media Server nadal przeszukuje bibliotekę muzyczną. Prosimy o cierpliwość - może to chwilę potrwać. + RU Logitech Media Server выполняет сканирование медиатеки. Пожалуйста, подождите. SV Sökningen av ditt musikbibliotek pågår fortfarande. Det kan ta en liten stund. Tack för ditt tålamod. - ZH_CN Squeezebox Server正在扫描您的音乐库,这也许需要一些时间,敬请耐心稍候。 + ZH_CN Logitech Media Server正在扫描您的音乐库,这也许需要一些时间,敬请耐心稍候。 SCAN_CLICK CS Chcete-li procházet přímo svoji složku Hudba, klepněte na DA Hvis du vil gennemse hele din musiksamling, skal du klikke på DE Klicken Sie zum direkten Durchsuchen des Musikordners - EN To browse your music folder directly, click + EN To browse your media folder directly, click ES Para examinar directamente la carpeta de música, haga clic en FI Selaa musiikkikansiota suoraan napsauttamalla FR Pour parcourir votre dossier de musique directement, cliquer sur @@ -13533,34 +13536,34 @@ PLAYERIR_SETTINGS ZH_CN 红外线设置 SERVER_STATUS - CS Stav Squeezebox Server - DA Status for Squeezebox Server - DE Squeezebox Server-Status - EN Squeezebox Server Status - ES Estado de Squeezebox Server - FI Squeezebox Serverin tila - FR Etat du Squeezebox Server - IT Stato di Squeezebox Server - NL Status van Squeezebox Server - NO Status for Squeezebox Server - PL Stan programu Squeezebox Server - RU Статус Squeezebox Server - SV Squeezebox Server-status + CS Stav Logitech Media Server + DA Status for Logitech Media Server + DE Logitech Media Server-Status + EN Logitech Media Server Status + ES Estado de Logitech Media Server + FI Logitech Media Serverin tila + FR Etat du Logitech Media Server + IT Stato di Logitech Media Server + NL Status van Logitech Media Server + NO Status for Logitech Media Server + PL Stan programu Logitech Media Server + RU Статус Logitech Media Server + SV Logitech Media Server-status SERVER_STATUS_DESC - CS Informace o všech zjištěných zařízeních připojených ke Squeezebox Server - DA Oplysninger om alle enheder der er sluttet til Squeezebox Server - DE Informationen auf allen identifizierten mit Squeezebox Server verbundenen Geräten - EN Information on all identified devices connected to Squeezebox Server - ES Información sobre todos los dispositivos identificados conectados a Squeezebox Server - FI Kaikkien tunnistettujen Squeezebox Serveriin yhdistettyjen laitteiden tiedot - FR Informations sur tous les dispositifs identifiés connectés au Squeezebox Server - IT Informazioni su tutti i dispositivi rilevati connessi a Squeezebox Server - NL Informatie over alle geïdentificeerde apparaten die met Squeezebox Server verbonden zijn - NO Informasjon om alle identifiserte enheter som er koplet til Squeezebox Server. - PL Informacje na wszystkich zidentyfikowanych urządzeniach połączonych ze Squeezebox Server - RU Информация обо всех найденных устройствах, подключенных к Squeezebox Server - SV Information om alla identifierade enheter som anslutits till Squeezebox Server + CS Informace o všech zjištěných zařízeních připojených ke Logitech Media Server + DA Oplysninger om alle enheder der er sluttet til Logitech Media Server + DE Informationen auf allen identifizierten mit Logitech Media Server verbundenen Geräten + EN Information on all identified devices connected to Logitech Media Server + ES Información sobre todos los dispositivos identificados conectados a Logitech Media Server + FI Kaikkien tunnistettujen Logitech Media Serveriin yhdistettyjen laitteiden tiedot + FR Informations sur tous les dispositifs identifiés connectés au Logitech Media Server + IT Informazioni su tutti i dispositivi rilevati connessi a Logitech Media Server + NL Informatie over alle geïdentificeerde apparaten die met Logitech Media Server verbonden zijn + NO Informasjon om alle identifiserte enheter som er koplet til Logitech Media Server. + PL Informacje na wszystkich zidentyfikowanych urządzeniach połączonych ze Logitech Media Server + RU Информация обо всех найденных устройствах, подключенных к Logitech Media Server + SV Information om alla identifierade enheter som anslutits till Logitech Media Server BASIC_SERVER_SETTINGS CS Základní nastavení @@ -13614,23 +13617,23 @@ SERVER_SETTINGS ZH_CN 服务器设置 SQUEEZEBOX_SERVER_SETTINGS - CS Nastavení Squeezebox Server - DA Indstillinger for Squeezebox Server - DE Squeezebox Server-Einstellungen - EN Squeezebox Server Settings - ES Configuración de Squeezebox Server - FI Squeezebox Serverin asetukset - FR Réglages du Squeezebox Server - HE הגדרות Squeezebox Server - IT Impostazioni di Squeezebox Server - JA Squeezebox Serverセッティング - NL Instellingen van Squeezebox Server - NO Innstillinger for Squeezebox Server - PL Ustawienia programu Squeezebox Server - PT Configurações do Squeezebox Server - RU Настройки Squeezebox Server - SV Squeezebox Server-inställningar - ZH_CN Squeezebox Server设置 + CS Nastavení Logitech Media Server + DA Indstillinger for Logitech Media Server + DE Logitech Media Server-Einstellungen + EN Logitech Media Server Settings + ES Configuración de Logitech Media Server + FI Logitech Media Serverin asetukset + FR Réglages du Logitech Media Server + HE הגדרות Logitech Media Server + IT Impostazioni di Logitech Media Server + JA Logitech Media Serverセッティング + NL Instellingen van Logitech Media Server + NO Innstillinger for Logitech Media Server + PL Ustawienia programu Logitech Media Server + PT Configurações do Logitech Media Server + RU Настройки Logitech Media Server + SV Logitech Media Server-inställningar + ZH_CN Logitech Media Server设置 INTERFACE_SETTINGS CS Rozhraní @@ -13889,7 +13892,7 @@ DEBUG_SCANNER_CHOOSE CS Snímač hudby DA Musiksøgning DE Musikscanner - EN Music Scanner + EN Media Scanner ES Detector de música FI Musiikkihaku FR Analyseur de musique @@ -13931,20 +13934,20 @@ DEBUG_DEFAULT SV Återställ loggningsinställningar SETUP_GROUP_DEBUG_DESC - CS Squeezebox Server má řadu nastavení protokolování, která lze použít pro zapsání podrobných informací o provozu serveru a scanneru. Každá kategorie protokolů má určitou závažnost pro protokolování. Volba "Ladění" je nejvíce informativní, volba "Vypnuto" nejméně. - DA Squeezebox Server har en række indstillinger til logføring som kan bruges til at registrere detaljerede oplysninger om serveren og musiksøgninger. Hver logføringskategori kan indstilles til at registrere flere eller færre oplysninger. Fejlsøgning giver flest detaljer og Fra ingen. - DE Squeezebox Server enthält eine Reihe von Protokolleinstellungen, mit denen Sie umfangreiche Angaben über Squeezebox Server- und Scanner-Vorgänge aufzeichnen können. Jede Protokollkategorie unterliegt einer Begrenzung in der Protokollierung ("Debug" mit der höchsten Wortanzahl, "Off" mit der niedrigsten). - EN Squeezebox Server has a number of logging settings that can be used to record detailed information about server and scanner operation. Each logging category has a severity for logging. With "Debug" being the most verbose, and "Off" being the least. - ES Squeezebox Server tiene diversos parámetros de registro que se pueden usar para registrar información detallada del funcionamiento del servidor y de examen. Cada categoría de registro tiene una severidad para registro. "Depuración" es la más detallada, y "Desactivado" la menos. - FI Squeezebox Serverissä on useita kirjausasetuksia, joilla voidaan kirjata yksityiskohtaisia tietoja palvelimen toiminnasta ja hauista. Jokaisessa kirjausluokassa voidaan asettaa kirjauksen aste. "Virheenkorjaus" on niistä monisanaisin, "Ei käytössä" vähäsanaisin. - FR Le Squeezebox Server est doté d'un certain nombre de réglages de journalisation pouvant enregistrer des informations détaillées sur les opérations du serveur et de l'analyseur. L'enregistrement dans chaque catégorie de journalisation dépend d'un niveau de sévérité défini, le niveau "Débogage" étant le plus détaillé et "Désactivé" étant le moins détaillé. - HE Squeezebox Server כולל מספר הגדרות של איתור באגים שניתן להשתמש בהן לתיעוד מידע מפורט אודות הפעלת השרת. סמן את הפריטים שברצונך לתעד ביומן לצורך הצגה ולחץ על 'שנה' כדי להתחיל לתעד את המידע ביומן. באפשרותך להציג את הרשומות האחרונות שתועדו ביומן. - IT In Squeezebox Server sono disponibili numerose impostazioni per registrare informazioni dettagliate sul funzionamento del server e dell'analisi. Per ogni categoria di dati da registrare è possibile selezionare il livello di gravità: Debug definisce il livello più dettagliato mentre Disattivato quello meno dettagliato. - NL Squeezebox Server heeft een aantal registratie-instellingen waarmee gedetailleerde informatie over server- en scannerwerking verzameld kan worden. Elke categorie heeft een ernstniveau, waarbij 'Debuggen' het meest uitgebreid en 'Uit' het meest beknopt is. - NO Squeezebox Server har flere innstillinger for loggføring som kan brukes til å ta opp detaljert informasjon om serveren og søk. Hver loggføringskategori har en alvorlighetsgrad for loggføring. «Feilsøking» er mest detaljert, og «Av» er minst. - PL Program Squeezebox Server udostępnia różne opcje rejestrowania szczegółowych informacji o działaniu programu i mechanizmu przeszukiwania. Każda kategoria rejestrowania ma kategorię ważności. Opcja „Debuguj” zapewnia najbardziej, a „Wył.” najmniej dokładne informacje. - RU В Squeezebox Server предусмотрены различные настройки ведения журнала, с помощью которых можно записывать подробные сведения о работе сервера и сканера. У каждой категории ведения журнала есть уровень серьезности. Самый подробный уровень — "Отладка", наименее подробный — "Отключено". - SV Det finns ett antal loggningsinställningar i Squeezebox Server som du kan använda om du vill registrera information om serveraktivitet och sökningar. Du kan ange ange hur mycket som ska loggas i varje kategori. Inställningen Felsökning innebär den utförligaste loggningen och Av den minst utförliga. + CS Logitech Media Server má řadu nastavení protokolování, která lze použít pro zapsání podrobných informací o provozu serveru a scanneru. Každá kategorie protokolů má určitou závažnost pro protokolování. Volba "Ladění" je nejvíce informativní, volba "Vypnuto" nejméně. + DA Logitech Media Server har en række indstillinger til logføring som kan bruges til at registrere detaljerede oplysninger om serveren og musiksøgninger. Hver logføringskategori kan indstilles til at registrere flere eller færre oplysninger. Fejlsøgning giver flest detaljer og Fra ingen. + DE Logitech Media Server enthält eine Reihe von Protokolleinstellungen, mit denen Sie umfangreiche Angaben über Logitech Media Server- und Scanner-Vorgänge aufzeichnen können. Jede Protokollkategorie unterliegt einer Begrenzung in der Protokollierung ("Debug" mit der höchsten Wortanzahl, "Off" mit der niedrigsten). + EN Logitech Media Server has a number of logging settings that can be used to record detailed information about server and scanner operation. Each logging category has a severity for logging. With "Debug" being the most verbose, and "Off" being the least. + ES Logitech Media Server tiene diversos parámetros de registro que se pueden usar para registrar información detallada del funcionamiento del servidor y de examen. Cada categoría de registro tiene una severidad para registro. "Depuración" es la más detallada, y "Desactivado" la menos. + FI Logitech Media Serverissä on useita kirjausasetuksia, joilla voidaan kirjata yksityiskohtaisia tietoja palvelimen toiminnasta ja hauista. Jokaisessa kirjausluokassa voidaan asettaa kirjauksen aste. "Virheenkorjaus" on niistä monisanaisin, "Ei käytössä" vähäsanaisin. + FR Le Logitech Media Server est doté d'un certain nombre de réglages de journalisation pouvant enregistrer des informations détaillées sur les opérations du serveur et de l'analyseur. L'enregistrement dans chaque catégorie de journalisation dépend d'un niveau de sévérité défini, le niveau "Débogage" étant le plus détaillé et "Désactivé" étant le moins détaillé. + HE Logitech Media Server כולל מספר הגדרות של איתור באגים שניתן להשתמש בהן לתיעוד מידע מפורט אודות הפעלת השרת. סמן את הפריטים שברצונך לתעד ביומן לצורך הצגה ולחץ על 'שנה' כדי להתחיל לתעד את המידע ביומן. באפשרותך להציג את הרשומות האחרונות שתועדו ביומן. + IT In Logitech Media Server sono disponibili numerose impostazioni per registrare informazioni dettagliate sul funzionamento del server e dell'analisi. Per ogni categoria di dati da registrare è possibile selezionare il livello di gravità: Debug definisce il livello più dettagliato mentre Disattivato quello meno dettagliato. + NL Logitech Media Server heeft een aantal registratie-instellingen waarmee gedetailleerde informatie over server- en scannerwerking verzameld kan worden. Elke categorie heeft een ernstniveau, waarbij 'Debuggen' het meest uitgebreid en 'Uit' het meest beknopt is. + NO Logitech Media Server har flere innstillinger for loggføring som kan brukes til å ta opp detaljert informasjon om serveren og søk. Hver loggføringskategori har en alvorlighetsgrad for loggføring. «Feilsøking» er mest detaljert, og «Av» er minst. + PL Program Logitech Media Server udostępnia różne opcje rejestrowania szczegółowych informacji o działaniu programu i mechanizmu przeszukiwania. Każda kategoria rejestrowania ma kategorię ważności. Opcja „Debuguj” zapewnia najbardziej, a „Wył.” najmniej dokładne informacje. + RU В Logitech Media Server предусмотрены различные настройки ведения журнала, с помощью которых можно записывать подробные сведения о работе сервера и сканера. У каждой категории ведения журнала есть уровень серьезности. Самый подробный уровень — "Отладка", наименее подробный — "Отключено". + SV Det finns ett antal loggningsinställningar i Logitech Media Server som du kan använda om du vill registrera information om serveraktivitet och sökningar. Du kan ange ange hur mycket som ska loggas i varje kategori. Inställningen Felsökning innebär den utförligaste loggningen och Av den minst utförliga. DEBUGGING_SETTINGS CS Protokolování @@ -14348,22 +14351,22 @@ FORGET_PLAYER ZH_CN 遗忘此播放机 FORGET_PLAYER_DESC - CS Pokud již delší dobu nepoužíváte tento přehrávač nebo se tento přehrávač zobrazuje dvakát ve vašem seznamu přehrávačů, můžete určit, aby Squeezebox Server tento přehrávač ignoroval. - DA Hvis du ikke længere anvender denne afspiller, eller afspilleren optræder to gange på listen over afspillere, kan du vælge at Squeezebox Server skal glemme denne afspiller. + CS Pokud již delší dobu nepoužíváte tento přehrávač nebo se tento přehrávač zobrazuje dvakát ve vašem seznamu přehrávačů, můžete určit, aby Logitech Media Server tento přehrávač ignoroval. + DA Hvis du ikke længere anvender denne afspiller, eller afspilleren optræder to gange på listen over afspillere, kan du vælge at Logitech Media Server skal glemme denne afspiller. DE Wenn Sie den Player nicht weiter verwenden möchten oder der Player doppelt vorkommt, können Sie ihn aus der Serverliste löschen. - EN If you no longer are using this player or this player appears twice in your list of players, you can choose to have Squeezebox Server forget about this player. - ES Si ya no usa este reproductor, o si aparece dos veces en la lista de reproductores, se puede indicar a Squeezebox Server que se olvide de este reproductor. - FI Jos et enää käytä soitinta tai jos soitin esiintyy kahdesti soitinluettelossa, voit määrätä Squeezebox Serverin unohtamaan soittimen. + EN If you no longer are using this player or this player appears twice in your list of players, you can choose to have Logitech Media Server forget about this player. + ES Si ya no usa este reproductor, o si aparece dos veces en la lista de reproductores, se puede indicar a Logitech Media Server que se olvide de este reproductor. + FI Jos et enää käytä soitinta tai jos soitin esiintyy kahdesti soitinluettelossa, voit määrätä Logitech Media Serverin unohtamaan soittimen. FR Si vous n'utilisez plus cette platine ou si elle apparaît plus d'une fois dans la liste des platines, vous pouvez choisir de la retirer de la liste. HE אם אינך משתמש עוד בנגן זה, או אם הנגן מופיע פעמיים ברשימת הנגנים, באפשרותך לגרום לשרת להתעלם מהנגן. - IT Se non si utilizza più questo lettore o se il lettore compare due volte nell'elenco dei lettori, si può fare in modo che Squeezebox Server lo ignori. + IT Se non si utilizza più questo lettore o se il lettore compare due volte nell'elenco dei lettori, si può fare in modo che Logitech Media Server lo ignori. JA このプレーヤーをもう使用していない場合、あるいは、このプレーヤーが2つリストに載っている場合、このプレーヤーを消去することができます。 - NL Als je dit muzieksysteem niet langer gebruikt of dit systeem twee keer voorkomt in de lijst met muzieksystemen, kun je Squeezebox Server dit systeem laten 'vergeten'. - NO Hvis du ikke bruker denne spilleren, eller hvis den vises to ganger i listen over spillere, kan du få Squeezebox Server til å glemme den. - PL Jeżeli odtwarzacz nie jest już używany lub jest wyświetlany dwukrotnie na liście odtwarzaczy, program Squeezebox Server może nie używać tego odtwarzacza. + NL Als je dit muzieksysteem niet langer gebruikt of dit systeem twee keer voorkomt in de lijst met muzieksystemen, kun je Logitech Media Server dit systeem laten 'vergeten'. + NO Hvis du ikke bruker denne spilleren, eller hvis den vises to ganger i listen over spillere, kan du få Logitech Media Server til å glemme den. + PL Jeżeli odtwarzacz nie jest już używany lub jest wyświetlany dwukrotnie na liście odtwarzaczy, program Logitech Media Server może nie używać tego odtwarzacza. PT Se não usar mais este cliente (nome ou IP), ou se o cliente aparecer várias vezes, pode "esquecê-lo". - RU Если данный плеер больше не используется или отображается в списке плееров дважды, можно удалить его из Squeezebox Server. - SV Om du inte använder den här spelaren eller om den visas två gånger i listan över spelare, kan Squeezebox Server ta bort spelaren. + RU Если данный плеер больше не используется или отображается в списке плееров дважды, можно удалить его из Logitech Media Server. + SV Om du inte använder den här spelaren eller om den visas två gånger i listan över spelare, kan Logitech Media Server ta bort spelaren. ZH_CN 如果您不再使用这个播放机或这个播放机重复出现,您可以选择让服务器遗忘这个播放机。 FORGET_PLAYER_LINK @@ -14385,25 +14388,6 @@ FORGET_PLAYER_LINK SV Ta bort den här spelaren ZH_CN 遗忘此播放机 -MP3DIR_IS_NOW - CS Adresář, kde jsou vaše hudební soubory uloženy na vašem pevném disku: - DA Mappen hvor dine musikfiler er gemt på harddisken: - DE Das Verzeichnis, in dem sich ihre Musikdateien auf der Festplatte befinden: - EN The directory where your music files are stored on your hard disk: - ES La carpeta del disco duro donde se guardan los archivos de música: - FI Hakemisto, johon musiikkitiedostot on tallennettu kiintolevyllä: - FR Le dossier où vos fichiers MP3 sont stockés sur votre disque dur: - HE הספרייה שבה מאוחסנים קובצי המוסיקה בדיסק הקשיח: - IT La directory del disco rigido in cui sono memorizzati i file musicali: - JA 音楽ファイルが保存されているフォルダー : - NL De map waarin je muziekbestanden op je vaste schijf worden opgeslagen: - NO Katalogen på harddisken der MP3-filer er lagret: - PL Katalog przechowywania plików muzycznych na dysku twardym: - PT A directoria que tem os ficheiros MP3 no disco - RU Каталог на жестком диске, где хранятся музыкальные файлы: - SV Den mapp på hårddisken där dina musikfiler är lagrade: - ZH_CN 您的音乐文件存放在硬盘上的目录: - SECONDS CS sekund DA sekunder @@ -14462,19 +14446,19 @@ CURRENT_WEB_SKIN ZH_CN 当前的网外壳: WEB_NO_COOKIES_WARNING - CS Váš prohlížeč nepřijímá soubory cookie. Může to mít za následek neočekávané chování při ovládání Squeezebox Server. Než budete pokračovat, povolte příjem souborů cookie ve vašem prohlížeči. - DA Din browser accepterer ikke cookies. Det kan føre til uventede handlinger i brugen af din Squeezebox Server. Aktivér cookies i browseren inden du fortsætter. - DE Ihr Browser akzeptiert keine Cookies. Dies kann zu unerwartetem Verhalten bei der Steuerung Ihres Squeezebox Servers führen. Aktivieren Sie Cookies in Ihrem Browser, bevor Sie fortfahren. - EN Your browser does not accept cookies. This can lead to unexpected behaviour controlling your Squeezebox Server. Please enable cookies in your browser before you continue. - ES Su navegador no acepta cookies. Esto puede provocar un comportamiento inesperado al controlar Squeezebox Server. Active las cookies en el navegador antes de continuar. + CS Váš prohlížeč nepřijímá soubory cookie. Může to mít za následek neočekávané chování při ovládání Logitech Media Server. Než budete pokračovat, povolte příjem souborů cookie ve vašem prohlížeči. + DA Din browser accepterer ikke cookies. Det kan føre til uventede handlinger i brugen af din Logitech Media Server. Aktivér cookies i browseren inden du fortsætter. + DE Ihr Browser akzeptiert keine Cookies. Dies kann zu unerwartetem Verhalten bei der Steuerung Ihres Logitech Media Servers führen. Aktivieren Sie Cookies in Ihrem Browser, bevor Sie fortfahren. + EN Your browser does not accept cookies. This can lead to unexpected behaviour controlling your Logitech Media Server. Please enable cookies in your browser before you continue. + ES Su navegador no acepta cookies. Esto puede provocar un comportamiento inesperado al controlar Logitech Media Server. Active las cookies en el navegador antes de continuar. FI Selaimesi ei hyväksy evästeitä. Tämä saattaa aiheuttaa yllätyksiä Squeezebox-palvelimen hallinnassa. Salli evästeet selaimesta ja jatka vasta sitten. - FR Votre navigateur n'accepte pas les cookies. Ceci peut affecter le fonctionnement de votre Squeezebox Server. Veuillez activer les cookies dans votre navigateur avant de continuer. - IT Il browser in uso non accetta i cookie. Ciò può provocare un comportamento imprevisto di Squeezebox Server. Prima di continuare, abilitare i cookie nel browser. - NL Je browser accepteert geen cookies. Dit kan leiden tot onverwacht gedrag bij het bedienen van je Squeezebox Server. Schakel cookies in je browser in voordat je verdergaat. - NO Nettleseren din godtar ikke informasjonskapsler. Dette kan føre til uønsket oppførsel ved bruk av Squeezebox Server. Aktiver informasjonskapsler i nettleseren før du fortsetter. - PL Twoja przeglądarka nie akceptuje plików cookie. Może to wywołać nieoczekiwane skutki podczas sterowania programem Squeezebox Server. Włącz najpierw obsługę plików cookie w przeglądarce. - RU Браузер не принимает файлы cookie. Это может привести к непредвиденным результатам при управлении Squeezebox Server. Перед продолжением работы разрешите использование файлов cookie в браузере. - SV Din webbläsare accepterar inte cookies. Detta kan leda till problem när du använder Squeezebox Server. Aktivera cookies i din webbläsare innan du fortsätter. + FR Votre navigateur n'accepte pas les cookies. Ceci peut affecter le fonctionnement de votre Logitech Media Server. Veuillez activer les cookies dans votre navigateur avant de continuer. + IT Il browser in uso non accetta i cookie. Ciò può provocare un comportamento imprevisto di Logitech Media Server. Prima di continuare, abilitare i cookie nel browser. + NL Je browser accepteert geen cookies. Dit kan leiden tot onverwacht gedrag bij het bedienen van je Logitech Media Server. Schakel cookies in je browser in voordat je verdergaat. + NO Nettleseren din godtar ikke informasjonskapsler. Dette kan føre til uønsket oppførsel ved bruk av Logitech Media Server. Aktiver informasjonskapsler i nettleseren før du fortsetter. + PL Twoja przeglądarka nie akceptuje plików cookie. Może to wywołać nieoczekiwane skutki podczas sterowania programem Logitech Media Server. Włącz najpierw obsługę plików cookie w przeglądarce. + RU Браузер не принимает файлы cookie. Это может привести к непредвиденным результатам при управлении Logitech Media Server. Перед продолжением работы разрешите использование файлов cookie в браузере. + SV Din webbläsare accepterar inte cookies. Detta kan leda till problem när du använder Logitech Media Server. Aktivera cookies i din webbläsare innan du fortsätter. DISPLAY_PLUGINS CS Zobrazit nabídku Doplňky na přehrávači Slim: @@ -14715,23 +14699,23 @@ NO_PLAYER_FOUND ZH_CN 未能找到您的播放机。 NO_PLAYER_DETAILS - CS Pokud vlastníte Squeezebox nebo Transporter:
              • Ujistěte se, že přehrávač je zapojen a že nastavení sítě jsou správná. Po připojení přehrávače klepněte na tlačítko Obnovit.

              Pokud nemáte Squeezebox ani Transporter:

              • Můžete poslouchat hudbu ze své knihovny s pomocí SoftSqueeze, což je softwarová verze Squeezeboxu.
              • K poslechu hudby ze své knihovny se Squeezebox Server můžete použít softwarový přehrávač MP3 (například Winamp nebo iTunes), který připojíte k této adrese URL: http://localhost:9000/stream.mp3
              - DA Hvis du har en Squeezebox eller Transporter:
              • Kontroller at din afspiller er sluttet til, og at netværksindstillingerne er korrekte. Klik på opdateringsknappen når afspilleren er tilsluttet.

              Hvis du ikke har en Squeezebox eller Transporter:

              • Du kan lytte til dit musikbibliotek vha. SoftSqueeze, en softwareversion af Squeezebox.
              • Du kan også bruge et program til at afspille mp3-filer (fx Winamp eller iTunes) til at høre filerne sammen med Squeezebox Server ved at etablere forbindelse til denne adresse: http://localhost:9000/stream.mp3
              - DE Sie besitzen Squeezebox oder Transporter:
              • Überprüfen Sie, ob der Player korrekt angeschlossen ist und die Netzwerkeinstellungen stimmen und klicken Sie im Browser auf 'Aktualisieren', wenn der Player angeschlossen ist.

              Sie besitzen weder Squeezebox noch Transporter:

              • Sie können mit SoftSqueeze, einer Software-Version der Squeezebox, ihre Musiksammlung anhören.
              • Mit einer Software zur Wiedergabe von MP3 (z.B. WinAmp oder iTunes) können Sie über folgende URL auf Squeezebox Server zugreifen: http://localhost:9000/stream.mp3
              - EN If you own a Squeezebox or Transporter:
              • Make sure that your player is plugged in and its networking settings are correct. Click the Refresh button once your player is connected.

              If you do not own a Squeezebox or Transporter:

              • You can listen to your music library using SoftSqueeze, a software version of Squeezebox.
              • You can use MP3 player software (such as Winamp or iTunes) to listen to your music library with Squeezebox Server by connecting to this URL: http://localhost:9000/stream.mp3
              - ES Si posee un dispositivo Squeezebox o Transporter:
              • Asegúrese de que el reproductor está conectado y de que la configuración de red es correcta. Haga clic en el botón Actualizar cuando el reproductor esté conectado.

              Si no posee un dispositivo Squeezebox o Transporter:

              • Se puede escuchar la biblioteca de música mediante SoftSqueeze, una versión en software de Squeezebox.
              • Se puede usar un reproductor en software de MP3 (como Winamp o iTunes) para escuchar la biblioteca de música con Squeezebox Server conectándose a esta URL: http://localhost:9000/stream.mp3
              - FI Jos sinulla on Squeezebox tai Transporter:
              • Varmista, että soitin on liitetty ja että sen verkkoasetukset on määritetty oikein. Napsauta Päivitä-painiketta, kun soittimella on verkkoyhteys.

              Jos sinulla ei ole Squeezeboxia tai Transporteria:

              • Voit kuunnella musiikkikirjastossasi olevaa musiikkia SoftSqueezen avulla. Se on Squeezeboxin ohjelmistoversio.
              • Voit käyttää MP3-soitinohjelmistoa (esim. Winamp tai iTunes) musiikkikirjastossasi olevan musiikin kuunteluun Squeezebox Serverin kanssa käymällä tässä URL-osoitteessa: http://localhost:9000/stream.mp3
              - FR Si vous possédez une Squeezebox ou Transporter:
              • Vérifiez que la platine est branchée et que les réglages du réseau sont corrects. Cliquez sur le bouton Actualiser une fois la platine connectée pour actualiser la page.

              Si vous ne possédez pas de Squeezebox ou Transporter:

              • Vous pouvez écouter votre collection musicale à l'aide de SoftSqueeze, une version logicielle de la Squeezebox.
              • Vous pouvez utiliser un logiciel de lecture de MP3, tel que Winamp ou iTunes, pour écouter votre collection musicale avec le Squeezebox Server en vous connectant à l'URL suivante: http://localhost:9000/stream.mp3
              . - HE אם יש ברשותך התקן Squeezebox או Transporter:
              • ודא שהנגן מחובר לחשמל ושהגדרות העבודה ברשת שלו נכונות. לאחר חיבור הנגן, לחץ על הלחצן 'רענן'.

              אם אין ברשותך התקן Squeezebox או Transporter:

              • באפשרותך להאזין לספריית המוסיקה שלך באמצעות SoftSqueeze, גרסת תוכנה של Squeezebox.
              • באפשרותך להשתמש בתוכנת נגן של קובצי MP3 (כגון Winamp או iTunes) כדי להאזין לספריית המוסיקה באמצעות Squeezebox Server על-ידי התחברות לכתובת ה-URL הבאה: http://localhost:9000/stream.mp3
              - IT Se si possiede uno Squeezebox o un Transporter:
              • Verificare che il lettore sia collegato e che le relative impostazioni di rete siano corrette. Una volta collegato il lettore, fare clic sul pulsante Aggiorna.

              Se non si possiede uno Squeezebox o un Transporter:

              • È possibile ascoltare la libreria musicale mediante SoftSqueeze, la versione software di Squeezebox.
              • È possibile ascoltare la libreria musicale in Squeezebox Server tramite software per lettori MP3 (ad esempio Winamp o iTunes) accedendo al seguente URL: http://localhost:9000/stream.mp3
              + CS Pokud vlastníte Squeezebox nebo Transporter:
              • Ujistěte se, že přehrávač je zapojen a že nastavení sítě jsou správná. Po připojení přehrávače klepněte na tlačítko Obnovit.

              Pokud nemáte Squeezebox ani Transporter:

              • Můžete poslouchat hudbu ze své knihovny s pomocí SoftSqueeze, což je softwarová verze Squeezeboxu.
              • K poslechu hudby ze své knihovny se Logitech Media Server můžete použít softwarový přehrávač MP3 (například Winamp nebo iTunes), který připojíte k této adrese URL: http://localhost:9000/stream.mp3
              + DA Hvis du har en Squeezebox eller Transporter:
              • Kontroller at din afspiller er sluttet til, og at netværksindstillingerne er korrekte. Klik på opdateringsknappen når afspilleren er tilsluttet.

              Hvis du ikke har en Squeezebox eller Transporter:

              • Du kan lytte til dit musikbibliotek vha. SoftSqueeze, en softwareversion af Squeezebox.
              • Du kan også bruge et program til at afspille mp3-filer (fx Winamp eller iTunes) til at høre filerne sammen med Logitech Media Server ved at etablere forbindelse til denne adresse: http://localhost:9000/stream.mp3
              + DE Sie besitzen Squeezebox oder Transporter:
              • Überprüfen Sie, ob der Player korrekt angeschlossen ist und die Netzwerkeinstellungen stimmen und klicken Sie im Browser auf 'Aktualisieren', wenn der Player angeschlossen ist.

              Sie besitzen weder Squeezebox noch Transporter:

              • Sie können mit SoftSqueeze, einer Software-Version der Squeezebox, ihre Musiksammlung anhören.
              • Mit einer Software zur Wiedergabe von MP3 (z.B. WinAmp oder iTunes) können Sie über folgende URL auf Logitech Media Server zugreifen: http://localhost:9000/stream.mp3
              + EN If you own a Squeezebox or Transporter:
              • Make sure that your player is plugged in and its networking settings are correct. Click the Refresh button once your player is connected.

              If you do not own a Squeezebox or Transporter:

              • You can listen to your music library using SoftSqueeze, a software version of Squeezebox.
              • You can use MP3 player software (such as Winamp or iTunes) to listen to your music library with Logitech Media Server by connecting to this URL: http://localhost:9000/stream.mp3
              + ES Si posee un dispositivo Squeezebox o Transporter:
              • Asegúrese de que el reproductor está conectado y de que la configuración de red es correcta. Haga clic en el botón Actualizar cuando el reproductor esté conectado.

              Si no posee un dispositivo Squeezebox o Transporter:

              • Se puede escuchar la biblioteca de música mediante SoftSqueeze, una versión en software de Squeezebox.
              • Se puede usar un reproductor en software de MP3 (como Winamp o iTunes) para escuchar la biblioteca de música con Logitech Media Server conectándose a esta URL: http://localhost:9000/stream.mp3
              + FI Jos sinulla on Squeezebox tai Transporter:
              • Varmista, että soitin on liitetty ja että sen verkkoasetukset on määritetty oikein. Napsauta Päivitä-painiketta, kun soittimella on verkkoyhteys.

              Jos sinulla ei ole Squeezeboxia tai Transporteria:

              • Voit kuunnella musiikkikirjastossasi olevaa musiikkia SoftSqueezen avulla. Se on Squeezeboxin ohjelmistoversio.
              • Voit käyttää MP3-soitinohjelmistoa (esim. Winamp tai iTunes) musiikkikirjastossasi olevan musiikin kuunteluun Logitech Media Serverin kanssa käymällä tässä URL-osoitteessa: http://localhost:9000/stream.mp3
              + FR Si vous possédez une Squeezebox ou Transporter:
              • Vérifiez que la platine est branchée et que les réglages du réseau sont corrects. Cliquez sur le bouton Actualiser une fois la platine connectée pour actualiser la page.

              Si vous ne possédez pas de Squeezebox ou Transporter:

              • Vous pouvez écouter votre collection musicale à l'aide de SoftSqueeze, une version logicielle de la Squeezebox.
              • Vous pouvez utiliser un logiciel de lecture de MP3, tel que Winamp ou iTunes, pour écouter votre collection musicale avec le Logitech Media Server en vous connectant à l'URL suivante: http://localhost:9000/stream.mp3
              . + HE אם יש ברשותך התקן Squeezebox או Transporter:
              • ודא שהנגן מחובר לחשמל ושהגדרות העבודה ברשת שלו נכונות. לאחר חיבור הנגן, לחץ על הלחצן 'רענן'.

              אם אין ברשותך התקן Squeezebox או Transporter:

              • באפשרותך להאזין לספריית המוסיקה שלך באמצעות SoftSqueeze, גרסת תוכנה של Squeezebox.
              • באפשרותך להשתמש בתוכנת נגן של קובצי MP3 (כגון Winamp או iTunes) כדי להאזין לספריית המוסיקה באמצעות Logitech Media Server על-ידי התחברות לכתובת ה-URL הבאה: http://localhost:9000/stream.mp3
              + IT Se si possiede uno Squeezebox o un Transporter:
              • Verificare che il lettore sia collegato e che le relative impostazioni di rete siano corrette. Una volta collegato il lettore, fare clic sul pulsante Aggiorna.

              Se non si possiede uno Squeezebox o un Transporter:

              • È possibile ascoltare la libreria musicale mediante SoftSqueeze, la versione software di Squeezebox.
              • È possibile ascoltare la libreria musicale in Logitech Media Server tramite software per lettori MP3 (ad esempio Winamp o iTunes) accedendo al seguente URL: http://localhost:9000/stream.mp3
              JA プレーヤーがつながれ、ネットワークセッティングが正しいことを確認してください。「更新」を押して、プレーヤへの接続を再度試みてください。 - NL Als je een Squeezebox of Transporter hebt:
              • Zorg ervoor dat je muzieksysteem op het netwerk is aangesloten en dat de netwerkinstellingen kloppen. Klik op de knop Vernieuwen wanneer je systeem is aangesloten.

              Als je geen Squeezebox of Transporter hebt:

              • Je kunt naar je muziekcollectie luisteren met SoftSqueeze, een softwareversie van de Squeezebox.
              • Je kunt mp3-spelersoftware (zoals Winamp of iTunes) gebruiken om met Squeezebox Server naar je muziekcollectie te luisteren. Maak hiervoor een verbinding met de volgende URL: http://localhost:9000/stream.mp3
              - NO Hvis du har en Squeezebox eller en Transporter:
              • Kontroller at spilleren er plugget inn, og at nettverksinnstillingene stemmer. Klikk på Oppdater så snart spilleren er koplet til.

              Hvis du ikke har en Squeezebox eller en Transporter:

              • Du kan lytte til musikkbiblioteket ditt med SoftSqueeze, en programvareversjon av Squeezebox.
              • Du kan bruke mp3-spiller-programvare (som Winamp eller iTunes) til å lytte til musikkbiblioteket ditt med Squeezebox Server ved å gå til denne url-en: http://localhost:9000/stream.mp3
              - PL Jeżeli korzystasz z urządzenia Squeezebox lub Transporter:
              • Sprawdź, czy odtwarzacz jest podłączony do źródła zasilania, a ustawienia sieciowe są prawidłowe. Po podłączeniu odtwarzacza kliknij przycisk Odśwież.

              Jeżeli nie korzystasz z urządzenia Squeezebox lub Transporter:

              • Możesz słuchać muzyki z biblioteki, używając programu SoftSqueeze, programowej wersji urządzenia Squeezebox.
              • W celu słuchania muzyki z biblioteki w programie Squeezebox Server możesz użyć oprogramowania odtwarzacza plików MP3 (na przykład Winamp lub iTunes), przechodząc pod następujący adres URL: http://localhost:9000/stream.mp3
              + NL Als je een Squeezebox of Transporter hebt:
              • Zorg ervoor dat je muzieksysteem op het netwerk is aangesloten en dat de netwerkinstellingen kloppen. Klik op de knop Vernieuwen wanneer je systeem is aangesloten.

              Als je geen Squeezebox of Transporter hebt:

              • Je kunt naar je muziekcollectie luisteren met SoftSqueeze, een softwareversie van de Squeezebox.
              • Je kunt mp3-spelersoftware (zoals Winamp of iTunes) gebruiken om met Logitech Media Server naar je muziekcollectie te luisteren. Maak hiervoor een verbinding met de volgende URL: http://localhost:9000/stream.mp3
              + NO Hvis du har en Squeezebox eller en Transporter:
              • Kontroller at spilleren er plugget inn, og at nettverksinnstillingene stemmer. Klikk på Oppdater så snart spilleren er koplet til.

              Hvis du ikke har en Squeezebox eller en Transporter:

              • Du kan lytte til musikkbiblioteket ditt med SoftSqueeze, en programvareversjon av Squeezebox.
              • Du kan bruke mp3-spiller-programvare (som Winamp eller iTunes) til å lytte til musikkbiblioteket ditt med Logitech Media Server ved å gå til denne url-en: http://localhost:9000/stream.mp3
              + PL Jeżeli korzystasz z urządzenia Squeezebox lub Transporter:
              • Sprawdź, czy odtwarzacz jest podłączony do źródła zasilania, a ustawienia sieciowe są prawidłowe. Po podłączeniu odtwarzacza kliknij przycisk Odśwież.

              Jeżeli nie korzystasz z urządzenia Squeezebox lub Transporter:

              • Możesz słuchać muzyki z biblioteki, używając programu SoftSqueeze, programowej wersji urządzenia Squeezebox.
              • W celu słuchania muzyki z biblioteki w programie Logitech Media Server możesz użyć oprogramowania odtwarzacza plików MP3 (na przykład Winamp lub iTunes), przechodząc pod następujący adres URL: http://localhost:9000/stream.mp3
              PT Verifique se o cliente está ligado e se as configurações da rede estão correctas. Actualize esta página para verificar de novo a presença do leitor. - RU Если вы приобрели Squeezebox или Transporter.
              • Убедитесь, что плеер подключен и настройки сети правильные. После подключения плеера к сети нажмите кнопку "Обновить".

              Если вы не приобрели Squeezebox и Transporter.

              • Можете слушать песни из своей медиатеки с помощью SoftSqueeze — программной версии Squeezebox.
              • А благодаря программе для MP3-плееров (Winamp или iTunes) вы сможете слушать музыку в Squeezebox Server, подключившись к следующему URL: http://localhost:9000/stream.mp3
              - SV Om du har en Squeezebox- eller Transporter-spelare
              • kontrollerar du att spelaren är ansluten och att nätverksinställningarna är korrekta. Klicka på uppdateringsknappen när spelaren är ansluten.

              Om du inte har någon Squeezebox- eller Transporter-spelare

              • kan du lyssna på ditt musikbibliotek med SoftSqueeze, en programvaruversion av Squeezebox.
              • Du kan använda program för mp3-spelare som Winamp och iTunes för att lyssna på ditt musikbibliotek via Squeezebox Server genom att ansluta till den här webbadressen: http://localhost:9000/stream.mp3
              . - ZH_CN 如果您拥有Squeezebox播放机:
              • 请确保播放机已插电及其网络设置无误。当您的播放机连接好后请单击《刷新》。

              如果您未能拥有Squeezebox播放机:

              • 您可以利用软体式播放机SoftSqueeze从您的音乐库播放音乐。
              • 您可以利用MP3播放软件如Winamp或iTunes来欣赏Squeezebox Server所流出的音乐。请连接到此URL:http://localhost:9000/stream.mp3
              。 + RU Если вы приобрели Squeezebox или Transporter.
              • Убедитесь, что плеер подключен и настройки сети правильные. После подключения плеера к сети нажмите кнопку "Обновить".

              Если вы не приобрели Squeezebox и Transporter.

              • Можете слушать песни из своей медиатеки с помощью SoftSqueeze — программной версии Squeezebox.
              • А благодаря программе для MP3-плееров (Winamp или iTunes) вы сможете слушать музыку в Logitech Media Server, подключившись к следующему URL: http://localhost:9000/stream.mp3
              + SV Om du har en Squeezebox- eller Transporter-spelare
              • kontrollerar du att spelaren är ansluten och att nätverksinställningarna är korrekta. Klicka på uppdateringsknappen när spelaren är ansluten.

              Om du inte har någon Squeezebox- eller Transporter-spelare

              • kan du lyssna på ditt musikbibliotek med SoftSqueeze, en programvaruversion av Squeezebox.
              • Du kan använda program för mp3-spelare som Winamp och iTunes för att lyssna på ditt musikbibliotek via Logitech Media Server genom att ansluta till den här webbadressen: http://localhost:9000/stream.mp3
              . + ZH_CN 如果您拥有Squeezebox播放机:
              • 请确保播放机已插电及其网络设置无误。当您的播放机连接好后请单击《刷新》。

              如果您未能拥有Squeezebox播放机:

              • 您可以利用软体式播放机SoftSqueeze从您的音乐库播放音乐。
              • 您可以利用MP3播放软件如Winamp或iTunes来欣赏Logitech Media Server所流出的音乐。请连接到此URL:http://localhost:9000/stream.mp3
              。 PLAYER_NEEDS_UPGRADE CS Vyžadována aktualizace softwaru @@ -14860,44 +14844,44 @@ UPGRADE_COMPLETE ZH_CN 韧件更新 CHECKVERSION_PROBLEM - CS Problém při vyhledávání aktualizací Squeezebox Server. (Chybový kód %s) - DA Der opstod et problem under søgningen efter opdateringer til Squeezebox Server: (Fejlkode %s) - DE Beim Suchen nach einem Squeezebox Server-Update ist ein Problem aufgetreten: (Fehlercode %s) - EN There was a problem while checking for updates to Squeezebox Server. (Error code %s) - ES Problema al buscar actualizaciones para Squeezebox Server. (Código de error %s) - FI Squeezebox Server-päivitysten tarkistamisessa oli ongelmia (virhekoodi %s). - FR Une erreur s'est produite pendant la recherche de mises à jour du Squeezebox Server: Code d'erreur %s. - HE התעוררה בעיה במהלך החיפוש אחר עדכונים עבור Squeezebox Server. (קוד שגיאה %s) - IT Problema durante la verifica della disponibilità di aggiornamenti per Squeezebox Server. (Codice errore %s) - NL Er is een fout opgetreden tijdens het controleren op updates voor Squeezebox Server. (Foutcode %s) - NO Det oppsto et problem under søk etter nye oppdateringer for Squeezebox Server. (Feilkode %s) - PL Podczas sprawdzania dostępności aktualizacji programu Squeezebox Server wystąpił problem (kod błędu %s). - RU При поиске обновлений для Squeezebox Server возникла проблема. (Код ошибки %s) - SV Det uppstod ett fel vid sökningen efter uppdateringar för Squeezebox Server. (Felkod %s) - ZH_CN 当与Squeezebox Server查证韧件更新时出现错误。(Error code %s) + CS Problém při vyhledávání aktualizací Logitech Media Server. (Chybový kód %s) + DA Der opstod et problem under søgningen efter opdateringer til Logitech Media Server: (Fejlkode %s) + DE Beim Suchen nach einem Logitech Media Server-Update ist ein Problem aufgetreten: (Fehlercode %s) + EN There was a problem while checking for updates to Logitech Media Server. (Error code %s) + ES Problema al buscar actualizaciones para Logitech Media Server. (Código de error %s) + FI Logitech Media Server-päivitysten tarkistamisessa oli ongelmia (virhekoodi %s). + FR Une erreur s'est produite pendant la recherche de mises à jour du Logitech Media Server: Code d'erreur %s. + HE התעוררה בעיה במהלך החיפוש אחר עדכונים עבור Logitech Media Server. (קוד שגיאה %s) + IT Problema durante la verifica della disponibilità di aggiornamenti per Logitech Media Server. (Codice errore %s) + NL Er is een fout opgetreden tijdens het controleren op updates voor Logitech Media Server. (Foutcode %s) + NO Det oppsto et problem under søk etter nye oppdateringer for Logitech Media Server. (Feilkode %s) + PL Podczas sprawdzania dostępności aktualizacji programu Logitech Media Server wystąpił problem (kod błędu %s). + RU При поиске обновлений для Logitech Media Server возникла проблема. (Код ошибки %s) + SV Det uppstod ett fel vid sökningen efter uppdateringar för Logitech Media Server. (Felkod %s) + ZH_CN 当与Logitech Media Server查证韧件更新时出现错误。(Error code %s) CHECKVERSION_ERROR - CS Při kontrole aktualizací pro Squeezebox Server vznikla chyba: - DA Der opstod en fejl under søgningen efter opdateringer til Squeezebox Server: - DE Beim Suchen nach einem Squeezebox Server-Update ist ein Fehler aufgetreten: - EN There was an error while checking for updates to Squeezebox Server: - ES Error al buscar actualizaciones para Squeezebox Server: - FI Squeezebox Server -päivitysten tarkistamisessa tapahtui virhe: - FR Une erreur s'est produite pendant la recherche de mises à jour du Squeezebox Server: - HE אירעה שגיאה במהלך החיפוש אחר עדכונים עבור Squeezebox Server: - IT Errore durante il tentativo di aggiornamento di Squeezebox Server: - NL Er is een fout opgetreden tijdens het controleren op updates van Squeezebox Server: - NO Det oppsto en feil da det ble sett etter nye oppdateringer for Squeezebox Server: - PL Podczas sprawdzania dostępności aktualizacji programu Squeezebox Server wystąpił błąd: - RU При проверке обновлений Squeezebox Server произошла ошибка: - SV Det uppstod ett fel vid sökningen efter uppdateringar för Squeezebox Server: - ZH_CN 与Squeezebox Server查证韧间更新时出现错误: + CS Při kontrole aktualizací pro Logitech Media Server vznikla chyba: + DA Der opstod en fejl under søgningen efter opdateringer til Logitech Media Server: + DE Beim Suchen nach einem Logitech Media Server-Update ist ein Fehler aufgetreten: + EN There was an error while checking for updates to Logitech Media Server: + ES Error al buscar actualizaciones para Logitech Media Server: + FI Logitech Media Server -päivitysten tarkistamisessa tapahtui virhe: + FR Une erreur s'est produite pendant la recherche de mises à jour du Logitech Media Server: + HE אירעה שגיאה במהלך החיפוש אחר עדכונים עבור Logitech Media Server: + IT Errore durante il tentativo di aggiornamento di Logitech Media Server: + NL Er is een fout opgetreden tijdens het controleren op updates van Logitech Media Server: + NO Det oppsto en feil da det ble sett etter nye oppdateringer for Logitech Media Server: + PL Podczas sprawdzania dostępności aktualizacji programu Logitech Media Server wystąpił błąd: + RU При проверке обновлений Logitech Media Server произошла ошибка: + SV Det uppstod ett fel vid sökningen efter uppdateringar för Logitech Media Server: + ZH_CN 与Logitech Media Server查证韧间更新时出现错误: NEED_PATH CS Musíte zadat cestu k adresáři obsahujícímu vaše hudební soubory. DA Du skal angive stien til mappen med dine mp3-filer. DE Sie müssen einen Pfad zum Order mit den Musikdateien angeben. - EN You need to specify a path to your directory containing your music files. + EN You need to specify a path to your directory containing your media files. ES Debe especificar una ruta al directorio que contiene los archivos de música. FI Sinun on määritettävä polku hakemistoon, jossa musiikkitiedostot ovat. FR Vous devez spécifier le chemin d'accès au dossier qui contient vos fichiers MP3. @@ -14932,21 +14916,21 @@ NEED_PLAYLIST_PATH ZH_CN 您必须指定存有播放表目录的路径。 CSRF_ERROR_INFO - CS Chcete-li odeslat požadavek na toto URL ze Záložek/Oblíbených nebo jinými prostředky, než odkazem z webového rozhraní Squeezebox Server, musíte použít URL s bezpečnostním parametrem \"cauth\". Pokud jste dostali toto chybové hlášení při přechodu na odkaz z webového rozhraní Squeezebox Server, měli byste se přesvědčit, zda váš webový prohlížeč (včetně proxy serverů a softwaru proti spywaru a na ochranu soukromí) umožňuje odesílání záhlaví \"Referer\". Níže je příslušné URL pro URL, na které jste se pokusili přejít. - DA Hvis du vil åbne siden som denne adresse henviser til, fra et bogmærke/en favorit, eller på andre måder end ved at klikke på et link fra Squeezebox Servers webbaserede brugerflade, skal adressen rumme sikkerhedsparameteren "cauth". Hvis denne fejl opstod da du klikkede på et link i Squeezebox Servers webbaserede brugerflade, skal du sikre dig at din browser (herunder indstillinger for proxyservere og antispywareprogrammer m.v.) tillader headere med henvisninger (Referer). Nedenfor er den rigtigt konfigurerede adresse som du forsøgte at få adgang til. - DE Damit Sie diese URL aus einem Favoriten/Lesezeichen oder einem anderen Verfahren als aus der Squeezebox Server-Benutzeroberfläche aufrufen können, müssen Sie eine URL mit dem Sicherheitsparameter 'cauth' verwenden. Trat dieser Fehler auf, als Sie auf einen Link in der Squeezebox Server-Web-Benutzeroberfläche klickten, sollten Sie prüfen, ob der Browser (sowie Proxyserver und Spyware/Firewall-Software) das Senden von 'Referer'-Kopfzeilen zulässt. Dies ist die korrekte URL für die gewünschte Verbindung: - EN In order to request this URL from a Bookmark/Favorite, or some means other than following a link from the Squeezebox Server web interface, you will need to use a URL with a \"cauth\" security parameter. If you received this error when following a link from the Squeezebox Server web interface, you will want to make sure your web browser software (including proxy servers and spyware/privacy software) is allowing \"Referer\" headers to be sent. Below is the appropriate URL for the URL you attempted. - ES Para solicitar esta URL de un marcador/favorito, o por otro medio que no consista en seguir un vínculo desde la interfaz Web de Squeezebox Server, deberá usar una URL con un parámetro de seguridad \"cauth\". Si recibió este error al seguir un vínculo desde la interfaz Web de Squeezebox Server, conviene que se asegure de que el software del navegador Web (incluidos servidores y software para spyware/privacidad) permite el envío de encabezados \"Referer\". A continuación se muestra la URL correcta para la URL a la que se intentó acceder. - FI Jos haluat pyytää tämän URL:n kirjanmerkistä tai suosikista tai jotenkin muuten kuin Squeezebox Serverin internet-liittymän linkin välityksellä, sinun täytyy käyttää URL:ää, jolla on \"cauth\"-suojausparametri. Jos tämä virhe tapahtui, kun napsautit Squeezebox Serverin internet-liittymässä olevaa linkkiä, varmista että selainohjelma (mukaan luettuna välityspalvelin ja vakoiluohjelmien torjuntaohjelma tai yksityisyydensuojaohjelma) sallii \"Referer\"-otsikoiden lähettämisen. Alla on kokeilemasi URL-osoitteen asianmukainen URL-osoite. - FR Pour demander cette URL à partir d'un signet ou d'un moyen autre qu'à partir d'un lien dans l'interface du Squeezebox Server, vous devez utiliser l'URL avec un paramètre de sécurité \"cauth\". Si cette erreur s'est produite lorsque vous avez suivi un lien à partir de l'interface Web du Squeezebox Server, vérifiez que votre navigateur, vos serveurs proxy et votre programme anti logiciels espions autorisent l'envoi d'en-têtes \"Referer\". Vous trouverez ci-dessous l'URL correcte à utiliser à la place de l'URL spécifiée. - HE על מנת לבקש כתובת URL זו מפריט סימניות/מועדפים, או באמצעים שאינם שימוש בקישור ממשק האינטרנט של Squeezebox Server, יהיה עליך להשתמש בכתובת URL עם פרמטר אבטחה מסוג ‎\"cauth\"‎. אם שגיאה זו הופיעה בעת שימוש בקישור ממשק האינטרנט של Squeezebox Server, מומלץ לוודא שתוכנת דפדפן האינטרנט (לרבות שרתי ה-Proxy והתוכנות נגד ריגול/תוכנות להגנה על פרטיות) מאפשרת שליחה של כותרות מסוג ‎\"Referer\"‎. להלן כתובת ה-URL הנכונה עבור כתובת ה-URL שאליה ניסית לעבור. - IT Per accedere all'URL da un elenco di preferiti o senza selezionare un collegamento dall'interfaccia Web di Squeezebox Server, è necessario utilizzare un URL con il parametro di protezione \"cauth\". Se viene visualizzato questo messaggio di errore quando si seleziona un collegamento dall'interfaccia Web di Squeezebox Server, assicurarsi che il software del browser web in uso (inclusi i server proxy e il software antispyware) consenta l'invio delle intestazioni \"Referer\". Di seguito è riportato l'URL corretto per l'URL a cui si è tentato di accedere. - NL Als je deze URL wilt opvragen via een bladwijzer of favoriet, of een andere koppeling dan de koppelingen op de webinterface van Squeezebox Server, moet je een URL met de beveiligingsparameter cauth gebruiken. Trad deze fout op toen je een koppeling in de webinterface van Squeezebox Server volgde, dan moet je controleren of je webbrowsersoftware (inclusief proxyservers en spyware-/privacyprogramma's) het verzenden van de header Referer toestaat. Hieronder staat de correcte URL voor de URL die je probeerde. - NO Hvis du vil bruke denne url-en fra et bokmerke eller en favoritt, eller på noen annen måte enn å følge en lenke fra nettgrensesnittet til Squeezebox Server, må du bruke en url med sikkerhetsparameteren \"cauth\". Hvis du mottok denne feilen ved å følge en lenke fra nettgrensesnittet til Squeezebox Server, bør du sjekke at nettleserprogrammet (inkludert proxyservere og programvare for personvern og beskyttelse mot spionvare) tillater at \"Referer\"-hoder sendes. Nedenfor ser du riktig url for url-en du prøvde å bruke. - PL Aby zażądać użycia tego adresu URL z kategorii Zakładka/Ulubione lub wykonania innej czynności niż śledzenie łącza przez interfejs internetowy programu Squeezebox Server, należy użyć adresu URL z parametrem zabezpieczeń \"cauth\". Jeżeli błąd ten został wyświetlony podczas śledzenia łącza z interfejsu internetowego programu Squeezebox Server, należy upewnić się, że oprogramowanie przeglądarki internetowej (w tym serwery proxy i oprogramowanie do ochrony przed programami szpiegującymi/zapewniania prywatności) umożliwia wysyłanie nagłówków \"Referer\". Poniżej podano prawidłowy adres URL, jakiego należy użyć. - RU Чтобы запросить данный URL из папки "Закладки/Выбранное" или открыть его иным способом, кроме перехода по данной ссылке в веб-интерфейсе Squeezebox Server, необходимо применить к этому URL параметр безопасности \"cauth\". Если эта ошибка произошла при переходе по ссылке в веб-интерфейсе Squeezebox Server, нужно убедиться, что в веб-браузере (включая прокси-серверы и программы для защиты от шпионских программ и нарушения конфиденциальности) разрешена отправка заголовков \"Referer\". Ниже приводится правильный URL, на который вы хотели перейти. - SV Om du vill gå till den här webbadressen via bokmärken/favoriter eller på vilket annat sätt som helst förutom att följa en länk i Squeezebox Server-gränssnittet behöver du en adress med säkerhetsparametern cauth. Om det här felet inträffade när du följde en länk i Squeezebox Servers webbaserade gränssnitt bör du kontrollera att webbläsaren (inklusive inställningar för proxyservrar och spionprogram m.m.) tillåter rubriker med hänvisningar (Referer). Nedan visas den korrekt konfigurerade webbadressen du försökte öppna. - ZH_CN 如果要从Bookmark/Favorite或其他方法请求这URL(从Squeezebox Server网界面跟随链接除外),您将需要使用以\"cauth \"为安全参数的URL。如果您从Squeezebox Server网界面跟随链接而出现错误,您需要确定您的浏览器软件(包括网代理伺服器和spyware/privacy软件)允许发送\"Referer\"倒坠。下面是您试图访问的URL的正确的URL。 + CS Chcete-li odeslat požadavek na toto URL ze Záložek/Oblíbených nebo jinými prostředky, než odkazem z webového rozhraní Logitech Media Server, musíte použít URL s bezpečnostním parametrem \"cauth\". Pokud jste dostali toto chybové hlášení při přechodu na odkaz z webového rozhraní Logitech Media Server, měli byste se přesvědčit, zda váš webový prohlížeč (včetně proxy serverů a softwaru proti spywaru a na ochranu soukromí) umožňuje odesílání záhlaví \"Referer\". Níže je příslušné URL pro URL, na které jste se pokusili přejít. + DA Hvis du vil åbne siden som denne adresse henviser til, fra et bogmærke/en favorit, eller på andre måder end ved at klikke på et link fra Logitech Media Servers webbaserede brugerflade, skal adressen rumme sikkerhedsparameteren "cauth". Hvis denne fejl opstod da du klikkede på et link i Logitech Media Servers webbaserede brugerflade, skal du sikre dig at din browser (herunder indstillinger for proxyservere og antispywareprogrammer m.v.) tillader headere med henvisninger (Referer). Nedenfor er den rigtigt konfigurerede adresse som du forsøgte at få adgang til. + DE Damit Sie diese URL aus einem Favoriten/Lesezeichen oder einem anderen Verfahren als aus der Logitech Media Server-Benutzeroberfläche aufrufen können, müssen Sie eine URL mit dem Sicherheitsparameter 'cauth' verwenden. Trat dieser Fehler auf, als Sie auf einen Link in der Logitech Media Server-Web-Benutzeroberfläche klickten, sollten Sie prüfen, ob der Browser (sowie Proxyserver und Spyware/Firewall-Software) das Senden von 'Referer'-Kopfzeilen zulässt. Dies ist die korrekte URL für die gewünschte Verbindung: + EN In order to request this URL from a Bookmark/Favorite, or some means other than following a link from the Logitech Media Server web interface, you will need to use a URL with a \"cauth\" security parameter. If you received this error when following a link from the Logitech Media Server web interface, you will want to make sure your web browser software (including proxy servers and spyware/privacy software) is allowing \"Referer\" headers to be sent. Below is the appropriate URL for the URL you attempted. + ES Para solicitar esta URL de un marcador/favorito, o por otro medio que no consista en seguir un vínculo desde la interfaz Web de Logitech Media Server, deberá usar una URL con un parámetro de seguridad \"cauth\". Si recibió este error al seguir un vínculo desde la interfaz Web de Logitech Media Server, conviene que se asegure de que el software del navegador Web (incluidos servidores y software para spyware/privacidad) permite el envío de encabezados \"Referer\". A continuación se muestra la URL correcta para la URL a la que se intentó acceder. + FI Jos haluat pyytää tämän URL:n kirjanmerkistä tai suosikista tai jotenkin muuten kuin Logitech Media Serverin internet-liittymän linkin välityksellä, sinun täytyy käyttää URL:ää, jolla on \"cauth\"-suojausparametri. Jos tämä virhe tapahtui, kun napsautit Logitech Media Serverin internet-liittymässä olevaa linkkiä, varmista että selainohjelma (mukaan luettuna välityspalvelin ja vakoiluohjelmien torjuntaohjelma tai yksityisyydensuojaohjelma) sallii \"Referer\"-otsikoiden lähettämisen. Alla on kokeilemasi URL-osoitteen asianmukainen URL-osoite. + FR Pour demander cette URL à partir d'un signet ou d'un moyen autre qu'à partir d'un lien dans l'interface du Logitech Media Server, vous devez utiliser l'URL avec un paramètre de sécurité \"cauth\". Si cette erreur s'est produite lorsque vous avez suivi un lien à partir de l'interface Web du Logitech Media Server, vérifiez que votre navigateur, vos serveurs proxy et votre programme anti logiciels espions autorisent l'envoi d'en-têtes \"Referer\". Vous trouverez ci-dessous l'URL correcte à utiliser à la place de l'URL spécifiée. + HE על מנת לבקש כתובת URL זו מפריט סימניות/מועדפים, או באמצעים שאינם שימוש בקישור ממשק האינטרנט של Logitech Media Server, יהיה עליך להשתמש בכתובת URL עם פרמטר אבטחה מסוג ‎\"cauth\"‎. אם שגיאה זו הופיעה בעת שימוש בקישור ממשק האינטרנט של Logitech Media Server, מומלץ לוודא שתוכנת דפדפן האינטרנט (לרבות שרתי ה-Proxy והתוכנות נגד ריגול/תוכנות להגנה על פרטיות) מאפשרת שליחה של כותרות מסוג ‎\"Referer\"‎. להלן כתובת ה-URL הנכונה עבור כתובת ה-URL שאליה ניסית לעבור. + IT Per accedere all'URL da un elenco di preferiti o senza selezionare un collegamento dall'interfaccia Web di Logitech Media Server, è necessario utilizzare un URL con il parametro di protezione \"cauth\". Se viene visualizzato questo messaggio di errore quando si seleziona un collegamento dall'interfaccia Web di Logitech Media Server, assicurarsi che il software del browser web in uso (inclusi i server proxy e il software antispyware) consenta l'invio delle intestazioni \"Referer\". Di seguito è riportato l'URL corretto per l'URL a cui si è tentato di accedere. + NL Als je deze URL wilt opvragen via een bladwijzer of favoriet, of een andere koppeling dan de koppelingen op de webinterface van Logitech Media Server, moet je een URL met de beveiligingsparameter cauth gebruiken. Trad deze fout op toen je een koppeling in de webinterface van Logitech Media Server volgde, dan moet je controleren of je webbrowsersoftware (inclusief proxyservers en spyware-/privacyprogramma's) het verzenden van de header Referer toestaat. Hieronder staat de correcte URL voor de URL die je probeerde. + NO Hvis du vil bruke denne url-en fra et bokmerke eller en favoritt, eller på noen annen måte enn å følge en lenke fra nettgrensesnittet til Logitech Media Server, må du bruke en url med sikkerhetsparameteren \"cauth\". Hvis du mottok denne feilen ved å følge en lenke fra nettgrensesnittet til Logitech Media Server, bør du sjekke at nettleserprogrammet (inkludert proxyservere og programvare for personvern og beskyttelse mot spionvare) tillater at \"Referer\"-hoder sendes. Nedenfor ser du riktig url for url-en du prøvde å bruke. + PL Aby zażądać użycia tego adresu URL z kategorii Zakładka/Ulubione lub wykonania innej czynności niż śledzenie łącza przez interfejs internetowy programu Logitech Media Server, należy użyć adresu URL z parametrem zabezpieczeń \"cauth\". Jeżeli błąd ten został wyświetlony podczas śledzenia łącza z interfejsu internetowego programu Logitech Media Server, należy upewnić się, że oprogramowanie przeglądarki internetowej (w tym serwery proxy i oprogramowanie do ochrony przed programami szpiegującymi/zapewniania prywatności) umożliwia wysyłanie nagłówków \"Referer\". Poniżej podano prawidłowy adres URL, jakiego należy użyć. + RU Чтобы запросить данный URL из папки "Закладки/Выбранное" или открыть его иным способом, кроме перехода по данной ссылке в веб-интерфейсе Logitech Media Server, необходимо применить к этому URL параметр безопасности \"cauth\". Если эта ошибка произошла при переходе по ссылке в веб-интерфейсе Logitech Media Server, нужно убедиться, что в веб-браузере (включая прокси-серверы и программы для защиты от шпионских программ и нарушения конфиденциальности) разрешена отправка заголовков \"Referer\". Ниже приводится правильный URL, на который вы хотели перейти. + SV Om du vill gå till den här webbadressen via bokmärken/favoriter eller på vilket annat sätt som helst förutom att följa en länk i Logitech Media Server-gränssnittet behöver du en adress med säkerhetsparametern cauth. Om det här felet inträffade när du följde en länk i Logitech Media Servers webbaserade gränssnitt bör du kontrollera att webbläsaren (inklusive inställningar för proxyservrar och spionprogram m.m.) tillåter rubriker med hänvisningar (Referer). Nedan visas den korrekt konfigurerade webbadressen du försökte öppna. + ZH_CN 如果要从Bookmark/Favorite或其他方法请求这URL(从Logitech Media Server网界面跟随链接除外),您将需要使用以\"cauth \"为安全参数的URL。如果您从Logitech Media Server网界面跟随链接而出现错误,您需要确定您的浏览器软件(包括网代理伺服器和spyware/privacy软件)允许发送\"Referer\"倒坠。下面是您试图访问的URL的正确的URL。 CSRF_ERROR_MEDIUM CS

              Jelikož vaše úroveň ochrany CSRF je nasatvena na 'STŘEDNÍ', můžete použít stejnou ";cauth=" hodnotu pro libovolné URL; to znamená, že byste měli opatrnější na to, s kým sdílíte své URL.

              @@ -16404,14 +16388,14 @@ INFORMATION_SPECIFIC_PLAYER INFORMATION_MENU_SERVER CS Informace serveru - DA Squeezebox Server - DE Squeezebox Server - EN Squeezebox Server - ES Squeezebox Server + DA Logitech Media Server + DE Logitech Media Server + EN Logitech Media Server + ES Logitech Media Server FI Palvelimen tiedot - FR Squeezebox Server + FR Logitech Media Server HE מידע אודות השרת - IT Squeezebox Server + IT Logitech Media Server JA サーバー情報 NL Serverinformatie NO Server informasjon @@ -16422,7 +16406,7 @@ INFORMATION_MENU_SCAN CS Detaily hledání hudby DA Detaljer om musikindeksering DE Details zum Musik-Scan - EN Music Scan Details + EN Media Scan Details ES Detalles de examen de música FI Musiikkihaun tiedot FR Détails de l'analyse de la musique @@ -16941,6 +16925,12 @@ INFORMATION_TRACKS SV Totalt antal spår ZH_CN 音轨总数 +INFORMATION_VIDEOS + EN Total Videos + +INFORMATION_IMAGES + EN Total Images + INFORMATION_TIME CS Celková doba přehrávání DA Samlet spilletid @@ -17450,19 +17440,19 @@ SQUEEZENETWORK_SWITCHING ZH_CN 正在切换到mysqueezebox.com,请稍等。 SQUEEZENETWORK_WANT_SWITCH - CS Tento přehrávač je právě připojen k mysqueezebox.com. Chcete jej přepnout zpět na Squeezebox Server? - DA Afspilleren er tilsluttet mysqueezebox.com. Vil du skifte tilbage til Squeezebox Server igen? - DE Dieser Player ist derzeit mit mysqueezebox.com verbunden. Möchten Sie ihn wieder mit Squeezebox Server verbinden? - EN This player is currently connected to mysqueezebox.com. Do you want it to switch back to Squeezebox Server? - ES Este reproductor está conectado a mysqueezebox.com. ¿Desea regresar a Squeezebox Server? - FI Tämä soitin on yhdistetty mysqueezebox.comiin. Haluatko vaihtaa sen takaisin Squeezebox Serveriin? - FR Cette platine est actuellement connectée à mysqueezebox.com. Voulez-vous revenir au Squeezebox Server? - IT Il lettore è attualmente connesso a mysqueezebox.com. Connetterlo di nuovo Squeezebox Server? - NL Dit muzieksysteem is momenteel met mysqueezebox.com verbonden. Wil je het systeem terugschakelen naar Squeezebox Server? - NO Spilleren er koplet til mysqueezebox.com. Vil du bytte tilbake til Squeezebox Server? - PL Ten odtwarzacz jest aktualnie połączony z usługą mysqueezebox.com. Czy chcesz powrócić do programu Squeezebox Server? - RU Данный плеер подключен к mysqueezebox.com. Переключиться на Squeezebox Server? - SV Spelaren är för närvarande ansluten till mysqueezebox.com. Vill du ansluta den till Squeezebox Server istället? + CS Tento přehrávač je právě připojen k mysqueezebox.com. Chcete jej přepnout zpět na Logitech Media Server? + DA Afspilleren er tilsluttet mysqueezebox.com. Vil du skifte tilbage til Logitech Media Server igen? + DE Dieser Player ist derzeit mit mysqueezebox.com verbunden. Möchten Sie ihn wieder mit Logitech Media Server verbinden? + EN This player is currently connected to mysqueezebox.com. Do you want it to switch back to Logitech Media Server? + ES Este reproductor está conectado a mysqueezebox.com. ¿Desea regresar a Logitech Media Server? + FI Tämä soitin on yhdistetty mysqueezebox.comiin. Haluatko vaihtaa sen takaisin Logitech Media Serveriin? + FR Cette platine est actuellement connectée à mysqueezebox.com. Voulez-vous revenir au Logitech Media Server? + IT Il lettore è attualmente connesso a mysqueezebox.com. Connetterlo di nuovo Logitech Media Server? + NL Dit muzieksysteem is momenteel met mysqueezebox.com verbonden. Wil je het systeem terugschakelen naar Logitech Media Server? + NO Spilleren er koplet til mysqueezebox.com. Vil du bytte tilbake til Logitech Media Server? + PL Ten odtwarzacz jest aktualnie połączony z usługą mysqueezebox.com. Czy chcesz powrócić do programu Logitech Media Server? + RU Данный плеер подключен к mysqueezebox.com. Переключиться на Logitech Media Server? + SV Spelaren är för närvarande ansluten till mysqueezebox.com. Vill du ansluta den till Logitech Media Server istället? SQUEEZENETWORK_SB2_REQUIRED CS Bohužel je nutný novější Squeezebox. @@ -17497,19 +17487,19 @@ SQUEEZENETWORK_NO_PLAYER_CONNECTED SV Det går inte att få tillgång till mysqueezebox.com-tjänsterna eftersom ingen spelare är ansluten. SQUEEZENETWORK_NO_LOGIN - CS Pro tuto službu je vyžadován účet mysqueezebox.com. Konfigurujte jej prosím ve webovém prohlížeči v položce Squeezebox Server Settings -> mysqueezebox.com. - DA Du skal have en konto til mysqueezebox.com for at bruge denne tjeneste. Du kan konfigurere den i en browser under Indstillinger for Squeezebox Server -> mysqueezebox.com. - DE Für diesen Dienst ist ein mysqueezebox.com-Konto erforderlich. Sie können das Konto in einem Web-Browser in den Squeezebox Server-Einstellungen unter 'mysqueezebox.com' konfigurieren. - EN A mysqueezebox.com account is required for this service. Please access Squeezebox Server Settings -> mysqueezebox.com with a web browser to configure. - ES Este servicio requiere una cuenta mysqueezebox.com. Acceda a Configuración de Squeezebox Server -> mysqueezebox.com a través de un navegador Web. - FI Tähän palveluun vaaditaan mysqueezebox.com-tili. Siirry selaimella kohtaan Squeezebox Serverin asetukset -> mysqueezebox.com ja määritä asetukset. - FR Un compte mysqueezebox.com est requis pour ce service. Dans votre navigateur, rendez-vous dans Réglages du Squeezebox Server -> mysqueezebox.com pour effectuer la configuration. - IT Per questo servizio è richiesto un account mysqueezebox.com. Accedere a Impostazioni Squeezebox Server -> mysqueezebox.com tramite un browser Web per la configurazione. - NL Voor deze service is een mysqueezebox.com-account vereist. Ga via een webbrowser naar Squeezebox Server-instellingen -> mysqueezebox.com om te configureren. - NO Du trenger en konto på mysqueezebox.com for å kunne benytte denne tjenesten. Gå til Squeezebox Server-innstillinger -> mysqueezebox.com i en nettleser for å konfigurere. - PL W celu korzystania z tej usługi wymagane jest konto usługi mysqueezebox.com. Aby kontynuować, wybierz opcję Ustawienia programu Squeezebox Server -> mysqueezebox.com w przeglądarce internetowej. - RU Для данной службы требуется учетная запись mysqueezebox.com. Чтобы настроить ее, откройте в веб-браузере страницу "Настройки Squeezebox Server" -> "mysqueezebox.com". - SV Du måste ha ett mysqueezebox.com-konto för att kunna använda den här tjänsten. Öppna en webbläsare och gå till Squeezebox Server-inställningar > mysqueezebox.com om du vill konfigurera inställningarna. + CS Pro tuto službu je vyžadován účet mysqueezebox.com. Konfigurujte jej prosím ve webovém prohlížeči v položce Logitech Media Server Settings -> mysqueezebox.com. + DA Du skal have en konto til mysqueezebox.com for at bruge denne tjeneste. Du kan konfigurere den i en browser under Indstillinger for Logitech Media Server -> mysqueezebox.com. + DE Für diesen Dienst ist ein mysqueezebox.com-Konto erforderlich. Sie können das Konto in einem Web-Browser in den Logitech Media Server-Einstellungen unter 'mysqueezebox.com' konfigurieren. + EN A mysqueezebox.com account is required for this service. Please access Logitech Media Server Settings -> mysqueezebox.com with a web browser to configure. + ES Este servicio requiere una cuenta mysqueezebox.com. Acceda a Configuración de Logitech Media Server -> mysqueezebox.com a través de un navegador Web. + FI Tähän palveluun vaaditaan mysqueezebox.com-tili. Siirry selaimella kohtaan Logitech Media Serverin asetukset -> mysqueezebox.com ja määritä asetukset. + FR Un compte mysqueezebox.com est requis pour ce service. Dans votre navigateur, rendez-vous dans Réglages du Logitech Media Server -> mysqueezebox.com pour effectuer la configuration. + IT Per questo servizio è richiesto un account mysqueezebox.com. Accedere a Impostazioni Logitech Media Server -> mysqueezebox.com tramite un browser Web per la configurazione. + NL Voor deze service is een mysqueezebox.com-account vereist. Ga via een webbrowser naar Logitech Media Server-instellingen -> mysqueezebox.com om te configureren. + NO Du trenger en konto på mysqueezebox.com for å kunne benytte denne tjenesten. Gå til Logitech Media Server-innstillinger -> mysqueezebox.com i en nettleser for å konfigurere. + PL W celu korzystania z tej usługi wymagane jest konto usługi mysqueezebox.com. Aby kontynuować, wybierz opcję Ustawienia programu Logitech Media Server -> mysqueezebox.com w przeglądarce internetowej. + RU Для данной службы требуется учетная запись mysqueezebox.com. Чтобы настроить ее, откройте в веб-браузере страницу "Настройки Logitech Media Server" -> "mysqueezebox.com". + SV Du måste ha ett mysqueezebox.com-konto för att kunna använda den här tjänsten. Öppna en webbläsare och gå till Logitech Media Server-inställningar > mysqueezebox.com om du vill konfigurera inställningarna. MUSICSOURCE CS Zdroj hudby @@ -17526,6 +17516,9 @@ MUSICSOURCE RU Источник музыки SV Musikkälla +MEDIASOURCE + EN Media Source + MUSICSOURCE_SWITCH CS Zvolte prosím zdroj hudby, ke kterému chcete připojit svůj přehrávač. DA Vælg den musikkilde som afspilleren skal tilsluttes. @@ -17542,19 +17535,19 @@ MUSICSOURCE_SWITCH SV Välj musikkälla att ansluta spelaren till. SQUEEZEBOX_SERVER_WANT_SWITCH - CS Tento přehrávač je v aktuálně připojen k %s. Chcete ho přepnout na tento Squeezebox Server? - DA Denne afspiller er tilsluttet %s. Vil du skifte til Squeezebox Server? - DE Dieser Player ist derzeit verbunden mit %s. Möchten Sie auf diese Version von Squeezebox Server umschalten? - EN This player is currently connected to %s. Do you want it to switch to this Squeezebox Server? - ES Este reproductor está conectado a %s. ¿Desea conectarlo a este Squeezebox Server? - FI Tämä soitin on yhdistetty kohteeseen %s. Haluatko vaihtaa sen tähän Squeezebox Serveriin? - FR Cette platine est actuellement connectée à %s. Voulez-vous la connecter à ce Squeezebox Server? - IT Questo lettore è connesso a %s. Passare a questo Squeezebox Server? - NL Dit muzieksysteem is momenteel verbonden met %s. Wil je het systeem terugschakelen naar deze Squeezebox Server? - NO Spilleren er koplet til %s. Vil du bytte til denne Squeezebox Server? - PL Odtwarzacz jest aktualnie połączony z %s. Czy chcesz przełączyć go na ten program Squeezebox Server? - RU Данный плеер подключен к %s. Переключиться на данный Squeezebox Server? - SV Den här spelaren är för närvarande ansluten till %s. Vill du växla till denna Squeezebox Server? + CS Tento přehrávač je v aktuálně připojen k %s. Chcete ho přepnout na tento Logitech Media Server? + DA Denne afspiller er tilsluttet %s. Vil du skifte til Logitech Media Server? + DE Dieser Player ist derzeit verbunden mit %s. Möchten Sie auf diese Version von Logitech Media Server umschalten? + EN This player is currently connected to %s. Do you want it to switch to this Logitech Media Server? + ES Este reproductor está conectado a %s. ¿Desea conectarlo a este Logitech Media Server? + FI Tämä soitin on yhdistetty kohteeseen %s. Haluatko vaihtaa sen tähän Logitech Media Serveriin? + FR Cette platine est actuellement connectée à %s. Voulez-vous la connecter à ce Logitech Media Server? + IT Questo lettore è connesso a %s. Passare a questo Logitech Media Server? + NL Dit muzieksysteem is momenteel verbonden met %s. Wil je het systeem terugschakelen naar deze Logitech Media Server? + NO Spilleren er koplet til %s. Vil du bytte til denne Logitech Media Server? + PL Odtwarzacz jest aktualnie połączony z %s. Czy chcesz przełączyć go na ten program Logitech Media Server? + RU Данный плеер подключен к %s. Переключиться на данный Logitech Media Server? + SV Den här spelaren är för närvarande ansluten till %s. Vill du växla till denna Logitech Media Server? SQUEEZEBOX_SERVER_CONNECTING CS připojování k %s... @@ -17896,19 +17889,19 @@ SETUP_USEBANDASALBUMARTIST_0 ZH_CN 专辑按艺人列出 SETUP_USETPE2ASALBUMARTIST_DESC - CS Formát MP3 tagů neposkytuje standardní způsob, jak definovat Interpreta alba. Některé nástroje pro MP3 tagy používají pro Interpreta alba pole TPE2 (iTunes, Winamp, Windows Media Player), jiné je mohou používat pro zamýšlený význam "Skupina/orchestr". Zvolte význam, který má Squeezebox Server používat. Po změně tohoto nastavení začne opakované prohledávání vaší hudební knihovny. - DA MP3-mærkeformatet er en standardiseret metode til at definere en kunstner og dennes album. Nogle programmer til at håndtere mp3-mærker benytter feltet TPE2 til Albumkunstner (iTunes, Winamp, Windows Media Player) mens andre benytter det til den intenderede betydning af Band/orkester. Du skal vælge hvilken model der skal bruges i Squeezebox Server. Hvis du ændrer indstillingen, bliver hele musikbiblioteket gennemsøgt igen. + CS Formát MP3 tagů neposkytuje standardní způsob, jak definovat Interpreta alba. Některé nástroje pro MP3 tagy používají pro Interpreta alba pole TPE2 (iTunes, Winamp, Windows Media Player), jiné je mohou používat pro zamýšlený význam "Skupina/orchestr". Zvolte význam, který má Logitech Media Server používat. Po změně tohoto nastavení začne opakované prohledávání vaší hudební knihovny. + DA MP3-mærkeformatet er en standardiseret metode til at definere en kunstner og dennes album. Nogle programmer til at håndtere mp3-mærker benytter feltet TPE2 til Albumkunstner (iTunes, Winamp, Windows Media Player) mens andre benytter det til den intenderede betydning af Band/orkester. Du skal vælge hvilken model der skal bruges i Logitech Media Server. Hvis du ændrer indstillingen, bliver hele musikbiblioteket gennemsøgt igen. DE Das MP3-Tag-Format bietet keine Standardmöglichkeit zum Definieren des Interpreten des Albums. Manche MP3-Anwendungen (iTunes, Winamp, Windows Media Player) nutzen das Feld TPE2 für den Interpreten des Albums, andere nutzen es für den eigentlichen Zweck (Band/Orchester). Wählen Sie die gewünschte Bedeutung. Wenn Sie diese Einstellung ändern, wird die Musiksammlung erneut durchsucht. - EN The MP3 tag format does not provide a standard way of defining an Album Artist. Some MP3 tagging tools use the TPE2 field for Album Artist (iTunes, Winamp, Windows Media Player) while others may use it for the intended meaning of "Band/orchestra". Select the meaning you would like Squeezebox Server to use. Changing this setting will start a rescan of your music library. - ES El formato de etiquetas MP3 no proporciona una manera estándar de definir un artista de álbum. Algunas herramientas de etiquetado MP3 utilizan el campo TPE2 para artista de álbum (iTunes, Winamp, reproductor de Windows Media) mientras que otras pueden utilizarlo con el significado de "banda u orquesta". Seleccione el significado que desea que utilice Squeezebox Server. Si cambia esta configuración se volverá a examinar la biblioteca de música. - FI MP3-tagin muoto ei tarjoa standardinmukaista tapaa levyartistin määrittämiseen. Jotkin MP3-tunnistetyökalut käyttävät TPE2-kenttää levyartistille (iTunes, Winamp, Windows Media Player), joissakin toisissa työkaluissa kenttää taas saatetaan käyttää tarkoittamaan yhtyettä tai orkesteria. Valitse merkitys, jota haluat Squeezebox Serverin käyttävän. Asetuksen muuttaminen käynnistää musiikkikirjaston uudelleentarkistuksen. - FR Le format d'étiquette MP3 ne fournit pas de moyen standard pour définir un artiste d'album. Certains outils d'étiquetage MP3 utilisent le champ TPE2 pour Artiste d'album (iTunes, Winamp, Windows Media Player) tandis que d'autres peuvent l'utiliser pour la signification voulue de "Groupe/Orchestre". Sélectionnez la signification que Squeezebox Server doit utiliser. La modification de ce paramètre lancera une nouvelle analyse de votre collection musicale. + EN The MP3 tag format does not provide a standard way of defining an Album Artist. Some MP3 tagging tools use the TPE2 field for Album Artist (iTunes, Winamp, Windows Media Player) while others may use it for the intended meaning of "Band/orchestra". Select the meaning you would like Logitech Media Server to use. Changing this setting will start a rescan of your music library. + ES El formato de etiquetas MP3 no proporciona una manera estándar de definir un artista de álbum. Algunas herramientas de etiquetado MP3 utilizan el campo TPE2 para artista de álbum (iTunes, Winamp, reproductor de Windows Media) mientras que otras pueden utilizarlo con el significado de "banda u orquesta". Seleccione el significado que desea que utilice Logitech Media Server. Si cambia esta configuración se volverá a examinar la biblioteca de música. + FI MP3-tagin muoto ei tarjoa standardinmukaista tapaa levyartistin määrittämiseen. Jotkin MP3-tunnistetyökalut käyttävät TPE2-kenttää levyartistille (iTunes, Winamp, Windows Media Player), joissakin toisissa työkaluissa kenttää taas saatetaan käyttää tarkoittamaan yhtyettä tai orkesteria. Valitse merkitys, jota haluat Logitech Media Serverin käyttävän. Asetuksen muuttaminen käynnistää musiikkikirjaston uudelleentarkistuksen. + FR Le format d'étiquette MP3 ne fournit pas de moyen standard pour définir un artiste d'album. Certains outils d'étiquetage MP3 utilisent le champ TPE2 pour Artiste d'album (iTunes, Winamp, Windows Media Player) tandis que d'autres peuvent l'utiliser pour la signification voulue de "Groupe/Orchestre". Sélectionnez la signification que Logitech Media Server doit utiliser. La modification de ce paramètre lancera une nouvelle analyse de votre collection musicale. IT Il formato dei tag MP3 non fornisce un metodo standard per specificare l'artista di un album. Alcuni strumenti per l'assegnazione dei tag MP3 utilizzano il campo TPE2 per specificare l'artista dell'album (iTunes, Winamp, Windows Media Player), mentre altri lo utilizzano per indicare il gruppo o l'orchestra. Selezionare il significato che si desidera utilizzare in SqueezeCenter. La modifica di questa impostazione avvierà di nuovo l'analisi della libreria musicale. - NL De mp3-tagindeling biedt geen standaardmanier om een albumartiest te definiëren. Sommige mp3-labeltools gebruiken het TPE2-veld voor Albumartiest (iTunes, Winamp, Windows Media Player) terwijl andere het gebruiken voor de beoogde betekenis van 'Band/orkest'. Selecteer de betekenis die Squeezebox Server moet gebruiken. Wanneer je deze instelling wijzigt, wordt je muziekcollectie opnieuw gescand. - NO Etikettformatet mp3 angir ikke en standardmåte å definere en albumartist på. Noen etikettverktøy for mp3 bruker TPE2-feltet til albumartist (iTunes, Winamp, Windows Media Player), mens andre bruker det for gruppe/orkester. Velg hvordan Squeezebox Server skal tolke dette. Når du endrer denne innstillingen, startes et nytt søk i musikkbiblioteket. - PL Format znacznika pliku MP3 nie umożliwia definiowania wykonawcy albumu w standardowy sposób. Niektóre narzędzia do oznaczania plików MP3 używają do określenia wykonawcy albumu pola TPE2 (iTunes, Winamp, Windows Media Player), natomiast inne mogą używać go zgodnie z przeznaczeniem do określenia zespołu/orkiestry. Wybierz znaczenie, które ma być używane przez program Squeezebox Server. Zmiana tego ustawienia powoduje ponowne przeszukanie biblioteki muzyki. - RU Формат тега MP3 не предоставляет единого стандарта для задания исполнителя альбома. В некоторых средствах для редактирования тегов MP3 поле TPE2 используется для обозначения исполнителя альбома (например, в iTunes, Winamp, проигрывателе Windows Media), тогда как в других оно может иметь подразумеваемое значение "Группа/Оркестр". Выберите необходимое значение для использования в Squeezebox Server. При изменении этой настройки начнется повторное сканирование медиатеки. - SV Det finns inget standardsätt att ange albumartister med mp3-taggar. I vissa mp3-taggningsverktyg används TPE2-fältet för att ange albumartist (exempelvis i iTunes, Winamp och Windows Media Player), medan det i andra verktyg används för att ange band/orkester. Välj vilket alternativ Squeezebox Server använder. Om du ändrar den här inställningen påbörjas en ny sökning av musikbiblioteket. + NL De mp3-tagindeling biedt geen standaardmanier om een albumartiest te definiëren. Sommige mp3-labeltools gebruiken het TPE2-veld voor Albumartiest (iTunes, Winamp, Windows Media Player) terwijl andere het gebruiken voor de beoogde betekenis van 'Band/orkest'. Selecteer de betekenis die Logitech Media Server moet gebruiken. Wanneer je deze instelling wijzigt, wordt je muziekcollectie opnieuw gescand. + NO Etikettformatet mp3 angir ikke en standardmåte å definere en albumartist på. Noen etikettverktøy for mp3 bruker TPE2-feltet til albumartist (iTunes, Winamp, Windows Media Player), mens andre bruker det for gruppe/orkester. Velg hvordan Logitech Media Server skal tolke dette. Når du endrer denne innstillingen, startes et nytt søk i musikkbiblioteket. + PL Format znacznika pliku MP3 nie umożliwia definiowania wykonawcy albumu w standardowy sposób. Niektóre narzędzia do oznaczania plików MP3 używają do określenia wykonawcy albumu pola TPE2 (iTunes, Winamp, Windows Media Player), natomiast inne mogą używać go zgodnie z przeznaczeniem do określenia zespołu/orkiestry. Wybierz znaczenie, które ma być używane przez program Logitech Media Server. Zmiana tego ustawienia powoduje ponowne przeszukanie biblioteki muzyki. + RU Формат тега MP3 не предоставляет единого стандарта для задания исполнителя альбома. В некоторых средствах для редактирования тегов MP3 поле TPE2 используется для обозначения исполнителя альбома (например, в iTunes, Winamp, проигрывателе Windows Media), тогда как в других оно может иметь подразумеваемое значение "Группа/Оркестр". Выберите необходимое значение для использования в Logitech Media Server. При изменении этой настройки начнется повторное сканирование медиатеки. + SV Det finns inget standardsätt att ange albumartister med mp3-taggar. I vissa mp3-taggningsverktyg används TPE2-fältet för att ange albumartist (exempelvis i iTunes, Winamp och Windows Media Player), medan det i andra verktyg används för att ange band/orkester. Välj vilket alternativ Logitech Media Server använder. Om du ändrar den här inställningen påbörjas en ny sökning av musikbiblioteket. SETUP_USETPE2ASALBUMARTIST_1 CS Považovat pole TPE2 MP3 tagu za Interpreta alba. @@ -17977,7 +17970,7 @@ SETUP_POWERONRESUME SETUP_POWERONRESUME_DESC CS Můžete si zvolit, jak přehrávač obnoví aktuální seznam skladeb po vypnutí přehrávače tlačítkem POWER a jeho opětovném pozdějším zapnutí. Toto nastavení platí pro tento přehrávač a ostatní přehrávače, pokud jsou synchronizovány s tímto přehrávačem. DA Du kan vælge om afspilleren skal fortsætte med den nuværende afspilningsliste næste gang du tænder den. Indstillingen gælder denne afspiller og andre afspillere der er synkroniseret med den. - DE Hier können Sie bestimmen, wie Squeezebox Server Wiedergabelisten behandeln soll, wenn Sie den Player mit der POWER-Taste aus- und wieder einschalten. Diese Einstellung gilt für diesen und andere Player, während Sie mit diesem Player synchronisiert sind. + DE Hier können Sie bestimmen, wie Logitech Media Server Wiedergabelisten behandeln soll, wenn Sie den Player mit der POWER-Taste aus- und wieder einschalten. Diese Einstellung gilt für diesen und andere Player, während Sie mit diesem Player synchronisiert sind. EN You can choose how your player should resume the current playlist when you press the POWER button to turn the player off and then again to turn it on again later. This setting applies to this player and other players while they are synchronized to this player. ES Se puede elegir cómo debe reanudar el reproductor la lista de reproducción actual cuando se pulse el botón POWER para apagar el reproductor y de nuevo para encenderlo más tarde. Esta opción se aplica a éste y a otros reproductores mientras estén sincronizados con éste. FI Voit valita, miten soitin jatkaa nykyisen soittoluettelon soittamista, kun kytket soittimeen virran sen jälkeen, kun olet katkaissut siitä virran toiston aikana. Asetukset koskevat tätä soitinta ja muita soittimia, jos ne on synkronoitu tämän soittimen kanssa. @@ -18127,19 +18120,19 @@ ONE_BY_ONE_ARTWORK ZH_CN 1-by-1 封面图 OBJECT_RETRIEVAL_FAILURE - CS Squeezebox Server nemohl najít zdroj, který jste hledali. - DA Squeezebox Server kunne ikke hente kilden du søgte efter. - DE Squeezebox Server konnte die gesuchte Ressource nicht finden. - EN Squeezebox Server failed retrieve the resource you were looking for. - ES Squeezebox Server no pudo obtener el recurso que estaba buscando. - FI Squeezebox Server epäonnistui etsimäsi resurssin hakemisessa. - FR Le Squeezebox Server n'a pas pu récupérer la source recherchée. - HE Squeezebox Server לא הצליח לאחזר את המשאב המבוקש. + CS Logitech Media Server nemohl najít zdroj, který jste hledali. + DA Logitech Media Server kunne ikke hente kilden du søgte efter. + DE Logitech Media Server konnte die gesuchte Ressource nicht finden. + EN Logitech Media Server failed retrieve the resource you were looking for. + ES Logitech Media Server no pudo obtener el recurso que estaba buscando. + FI Logitech Media Server epäonnistui etsimäsi resurssin hakemisessa. + FR Le Logitech Media Server n'a pas pu récupérer la source recherchée. + HE Logitech Media Server לא הצליח לאחזר את המשאב המבוקש. IT Recupero risorsa richiesta non riuscito. - NL Squeezebox Server kan de gewenste hulpbron niet ophalen. - NO Squeezebox Server kunne ikke hente inn ressursen du så etter. - PL Pobranie wyszukiwanego zasobu przez program Squeezebox Server nie powiodło się. - RU Squeezebox Server не удалось получить искомый ресурс. + NL Logitech Media Server kan de gewenste hulpbron niet ophalen. + NO Logitech Media Server kunne ikke hente inn ressursen du så etter. + PL Pobranie wyszukiwanego zasobu przez program Logitech Media Server nie powiodło się. + RU Logitech Media Server не удалось получить искомый ресурс. SV Det gick inte att ladda ner den önskade resursen. SETUP_LARGETEXTFONT @@ -18693,24 +18686,24 @@ SETUP_SERVERPRIORITY PL Priorytet serwera RU Приоритет сервера SV Serverprioritet - ZH_CN Squeezebox Server服务器流程优先值 + ZH_CN Logitech Media Server服务器流程优先值 SETUP_SERVERPRIORITY_DESC - CS Můžete zadat prioritu pro Squeezebox Server. - DA Du kan specificere hvilken prioritet Squeezebox Server skal have. - DE Sie können die Priorität festlegen, mit der Squeezebox Server ausgeführt wird. - EN You can specify the priority for Squeezebox Server. - ES Se puede especificar la prioridad con la que se ejecutará Squeezebox Server. - FI Voit määrittää Squeezebox Serverin prioriteettitason. - FR Vous pouvez fixer le niveau de priorité du Squeezebox Server. - HE באפשרותך לציין את העדיפות שבה פועל Squeezebox Server. - IT È possibile specificare la priorità attribuita a Squeezebox Server. - NL Je kunt de prioriteit van Squeezebox Server binnen je server specificeren. - NO Du kan angi prioritet for Squeezebox Server. - PL Możliwe jest określenie priorytetu programu Squeezebox Server. - RU Можно задать приоритет Squeezebox Server. - SV Du kan ange prioritet för Squeezebox Server. - ZH_CN 您可以配置Squeezebox Server服务器流程的优先设置。 + CS Můžete zadat prioritu pro Logitech Media Server. + DA Du kan specificere hvilken prioritet Logitech Media Server skal have. + DE Sie können die Priorität festlegen, mit der Logitech Media Server ausgeführt wird. + EN You can specify the priority for Logitech Media Server. + ES Se puede especificar la prioridad con la que se ejecutará Logitech Media Server. + FI Voit määrittää Logitech Media Serverin prioriteettitason. + FR Vous pouvez fixer le niveau de priorité du Logitech Media Server. + HE באפשרותך לציין את העדיפות שבה פועל Logitech Media Server. + IT È possibile specificare la priorità attribuita a Logitech Media Server. + NL Je kunt de prioriteit van Logitech Media Server binnen je server specificeren. + NO Du kan angi prioritet for Logitech Media Server. + PL Możliwe jest określenie priorytetu programu Logitech Media Server. + RU Можно задать приоритет Logitech Media Server. + SV Du kan ange prioritet för Logitech Media Server. + ZH_CN 您可以配置Logitech Media Server服务器流程的优先设置。 SETUP_SCANNERPRIORITY CS Priorita skeneru @@ -20179,7 +20172,7 @@ DEBUG_SCAN_SCANNER CS Prohledávání adresáře hudby a seznamů skladeb DA Indeksering af mappe med musik og afspilningslister DE Musik & Wiedergabelisten Scanner - EN Music & Playlist Folder Scanning + EN Media & Playlist Folder Scanning ES Examen de carpetas de listas de reproducción y música FI Musiikki- ja soittoluettelokansioiden tarkistus FR Analyse du dossier de la musique et des listes de lecture @@ -20209,7 +20202,7 @@ DEBUG_SCAN_AUTO CS Automatické prohledávání hudby a seznamu skladeb DA Automatisk søgning efter musik og afspilningslister DE Automatisches Durchsuchen der Musiksammlung und Wiedergabeliste - EN Automatic Music & Playlist Scanning + EN Automatic Media & Playlist Scanning ES Examen automático de listas de reproducción y música FI Automaattinen musiikki- ja soittoluetteloiden tarkistus FR Analyse automatique des morceaux et des listes de lecture @@ -20236,34 +20229,34 @@ DEBUG_WIZARD SV Loggning av installationsguidens aktivitet SETUP_DEBUG_SERVER_LOG - CS Soubor protokolu Squeezebox Server - DA Logfil for Squeezebox Server - DE Squeezebox Server Logdatei - EN Squeezebox Server Log File - ES Archivo de registro de Squeezebox Server - FI Squeezebox Serverin lokitiedosto - FR Fichier journal du Squeezebox Server - IT File di registro di Squeezebox Server - NL Logboekbestand van Squeezebox Server - NO Squeezebox Server loggfil - PL Plik dziennika programu Squeezebox Server - RU Файл журнала Squeezebox Server - SV Loggfil för Squeezebox Server + CS Soubor protokolu Logitech Media Server + DA Logfil for Logitech Media Server + DE Logitech Media Server Logdatei + EN Logitech Media Server Log File + ES Archivo de registro de Logitech Media Server + FI Logitech Media Serverin lokitiedosto + FR Fichier journal du Logitech Media Server + IT File di registro di Logitech Media Server + NL Logboekbestand van Logitech Media Server + NO Logitech Media Server loggfil + PL Plik dziennika programu Logitech Media Server + RU Файл журнала Logitech Media Server + SV Loggfil för Logitech Media Server SETUP_DEBUG_SERVER_LOG_DESC - CS Squeezebox Server zapisuje do protokolového souboru všechny činnosti aplikace (přehrávání audio proudů, infračervené spojení, atd.) zde: - DA Squeezebox Server logfører al aktivitet (streaming, infrarøde kommandoer osv.) i følgende fil: - DE Squeezebox Server schreibt Logs aller relevanten Aktivitäten (Audio Streaming, Infrarot etc.) in folgende Datei: - EN Squeezebox Server keeps a log file for all application related activities (Audio Streaming, Infrared, etc) here: - ES Squeezebox Server mantiene un archivo de registro para todas las actividades relacionadas con la aplicación (secuencias de audio, infrarrojos, etc.) aquí: - FI Squeezebox Server pitää lokitiedostoa kaikista sovelluksiin liittyvistä toiminnoista (äänen virtautus, infrapuna jne.) täällä: - FR Le Squeezebox Server conserve un fichier journal de toutes les activités liées à l'application (diffusion audio, infrarouge, etc.), à l'emplacement suivant: - IT Squeezebox Server mantiene un file di registro per tutte le attività relative alle applicazioni (stream audio, raggi infrarossi e così via) nel seguente percorso: - NL Squeezebox Server bewaart hier een logboekbestand voor alle toepassingsactiviteiten (audio-streaming, infrarood, enz.): - NO Squeezebox Server fører en loggfil for alle programrelaterte aktiviteter (lydstrømming, infrarøde signaler osv.) her: - PL Program Squeezebox Server przechowuje plik dziennika zawierający wszystkie działania dotyczące aplikacji (strumieniowe przesyłanie dźwięku, korzystanie z podczerwieni) w tym miejscu: - RU Все действия приложений (потоковое аудио, ИК-выход и др.) записываются в файл журнала Squeezebox Server: - SV Alla aktiviteter som har att göra med Squeezebox Server (ljudströmning, infraröda signaler o.s.v.) loggas här: + CS Logitech Media Server zapisuje do protokolového souboru všechny činnosti aplikace (přehrávání audio proudů, infračervené spojení, atd.) zde: + DA Logitech Media Server logfører al aktivitet (streaming, infrarøde kommandoer osv.) i følgende fil: + DE Logitech Media Server schreibt Logs aller relevanten Aktivitäten (Audio Streaming, Infrarot etc.) in folgende Datei: + EN Logitech Media Server keeps a log file for all application related activities (Audio Streaming, Infrared, etc) here: + ES Logitech Media Server mantiene un archivo de registro para todas las actividades relacionadas con la aplicación (secuencias de audio, infrarrojos, etc.) aquí: + FI Logitech Media Server pitää lokitiedostoa kaikista sovelluksiin liittyvistä toiminnoista (äänen virtautus, infrapuna jne.) täällä: + FR Le Logitech Media Server conserve un fichier journal de toutes les activités liées à l'application (diffusion audio, infrarouge, etc.), à l'emplacement suivant: + IT Logitech Media Server mantiene un file di registro per tutte le attività relative alle applicazioni (stream audio, raggi infrarossi e così via) nel seguente percorso: + NL Logitech Media Server bewaart hier een logboekbestand voor alle toepassingsactiviteiten (audio-streaming, infrarood, enz.): + NO Logitech Media Server fører en loggfil for alle programrelaterte aktiviteter (lydstrømming, infrarøde signaler osv.) her: + PL Program Logitech Media Server przechowuje plik dziennika zawierający wszystkie działania dotyczące aplikacji (strumieniowe przesyłanie dźwięku, korzystanie z podczerwieni) w tym miejscu: + RU Все действия приложений (потоковое аудио, ИК-выход и др.) записываются в файл журнала Logitech Media Server: + SV Alla aktiviteter som har att göra med Logitech Media Server (ljudströmning, infraröda signaler o.s.v.) loggas här: SETUP_DEBUG_SCANNER_LOG CS Protokolový soubor prohledávače @@ -20281,19 +20274,19 @@ SETUP_DEBUG_SCANNER_LOG SV Loggfil for sökning SETUP_DEBUG_SCANNER_LOG_DESC - CS Squeezebox Server ukládá protokol o všech činnostech prohledávání, včetně iTunes & MusicIP zde: - DA Squeezebox Server logfører alle gennemsøgninger, også i iTunes og MusicIP, i denne fil: - DE Squeezebox Server schreibt Logs der Aktivitäten im Zusammenhang mit dem Scanner (Musikdateien, iTunes, MusicIP) in folgende Datei: - EN Squeezebox Server keeps a log file for all scanning related activities, including iTunes & MusicIP here: - ES Squeezebox Server mantiene un archivo de registro para todas las actividades de examen, incluidas las de iTunes y MusicIP aquí: - FI Squeezebox Server pitää lokitiedostoa kaikista hakuihin liittyvistä toiminnoista (mukaan lukien iTunes ja MusicIP) täällä: - FR Le Squeezebox Server conserve un fichier journal de toutes les activités d'analyse, y compris pour iTunes et MusicIP, à l'emplacement suivant: - IT Squeezebox Server mantiene un file di registro per tutte le attività relative all'analisi, inclusi iTunes e MusicIP, nel seguente percorso: - NL Squeezebox Server bewaart hier een logboekbestand voor alle scanactiviteiten (zoals iTunes en MusicIP): - NO Squeezebox Server fører en loggfil for alle søkeaktiviteter, inkludert iTunes og MusicIP, her: - PL Program Squeezebox Server przechowuje plik dziennika dla wszystkich działań związanych z przeszukiwaniem, w tym programem iTunes i MusicIP tutaj: - RU В Squeezebox Server сохраняет файл журнала для всех действий сканирования, включая iTunes MusicIP, здесь: - SV En loggfil skapas över alla aktiviteter som har att göra med sökningar, däribland iTunes och MusicIP, i Squeezebox Server: + CS Logitech Media Server ukládá protokol o všech činnostech prohledávání, včetně iTunes & MusicIP zde: + DA Logitech Media Server logfører alle gennemsøgninger, også i iTunes og MusicIP, i denne fil: + DE Logitech Media Server schreibt Logs der Aktivitäten im Zusammenhang mit dem Scanner (Musikdateien, iTunes, MusicIP) in folgende Datei: + EN Logitech Media Server keeps a log file for all scanning related activities, including iTunes & MusicIP here: + ES Logitech Media Server mantiene un archivo de registro para todas las actividades de examen, incluidas las de iTunes y MusicIP aquí: + FI Logitech Media Server pitää lokitiedostoa kaikista hakuihin liittyvistä toiminnoista (mukaan lukien iTunes ja MusicIP) täällä: + FR Le Logitech Media Server conserve un fichier journal de toutes les activités d'analyse, y compris pour iTunes et MusicIP, à l'emplacement suivant: + IT Logitech Media Server mantiene un file di registro per tutte le attività relative all'analisi, inclusi iTunes e MusicIP, nel seguente percorso: + NL Logitech Media Server bewaart hier een logboekbestand voor alle scanactiviteiten (zoals iTunes en MusicIP): + NO Logitech Media Server fører en loggfil for alle søkeaktiviteter, inkludert iTunes og MusicIP, her: + PL Program Logitech Media Server przechowuje plik dziennika dla wszystkich działań związanych z przeszukiwaniem, w tym programem iTunes i MusicIP tutaj: + RU В Logitech Media Server сохраняет файл журнала для всех действий сканирования, включая iTunes MusicIP, здесь: + SV En loggfil skapas över alla aktiviteter som har att göra med sökningar, däribland iTunes och MusicIP, i Logitech Media Server: LINES CS řádky @@ -20326,18 +20319,18 @@ SETUP_DEBUG_PERFMON_LOG SV Prestandaloggfil SETUP_DEBUG_PERFMON_LOG_DESC - CS Squeezebox Server ukládá soubor protokolu o sledování výkonu zde: - DA Squeezebox Server logfører overvågning af ydelse her: - DE Squeezebox Server speichert eine Logdatei zur Leistungsüberwachung: - EN Squeezebox Server keeps a log file for performance monitoring here: - ES Squeezebox Server mantiene un archivo de registro para supervisión de rendimiento aquí: - FI Squeezebox Server pitää lokitiedostoa suorituskyvystä täällä: - FR Le Squeezebox Server conserve un fichier journal pour le contrôle des performances, à l'emplacement suivant: - IT Squeezebox Server mantiene un file di registro per monitorare le prestazioni in questa posizione: - NL Squeezebox Server bewaart hier een logboekbestand voor prestatiecontrole: - NO Squeezebox Server fører en loggfil for ytelsesovervåking her: - PL Program Squeezebox Server przechowuje plik dziennika do monitorowania wydajności w tym miejscu: - RU Файл журнала мониторинга производительности Squeezebox Server хранится здесь: + CS Logitech Media Server ukládá soubor protokolu o sledování výkonu zde: + DA Logitech Media Server logfører overvågning af ydelse her: + DE Logitech Media Server speichert eine Logdatei zur Leistungsüberwachung: + EN Logitech Media Server keeps a log file for performance monitoring here: + ES Logitech Media Server mantiene un archivo de registro para supervisión de rendimiento aquí: + FI Logitech Media Server pitää lokitiedostoa suorituskyvystä täällä: + FR Le Logitech Media Server conserve un fichier journal pour le contrôle des performances, à l'emplacement suivant: + IT Logitech Media Server mantiene un file di registro per monitorare le prestazioni in questa posizione: + NL Logitech Media Server bewaart hier een logboekbestand voor prestatiecontrole: + NO Logitech Media Server fører en loggfil for ytelsesovervåking her: + PL Program Logitech Media Server przechowuje plik dziennika do monitorowania wydajności w tym miejscu: + RU Файл журнала мониторинга производительности Logitech Media Server хранится здесь: SV Prestandaövervakning loggas här: SETUP_DEBUG_LEVEL_OFF @@ -20498,7 +20491,7 @@ SCANNER_PROGRESS CS Detaily hledání hudby DA Detaljer om musikindeksering DE Details zum Musik-Scan - EN Music Scan Details + EN Media Scan Details ES Detalles de examen de música FI Musiikkihaun tiedot FR Détails de l'analyse de la musique @@ -20513,7 +20506,7 @@ FAILURE_PROGRESS CS Prohledávání hudby neočekávaně ukončeno (%s) DA Musiksøgningen blev afsluttet uventet (%s) DE Durchsuchen der Musiksammlung unerwartet abgebrochen (%s) - EN Music scan terminated unexpectedly (%s) + EN Media scan terminated unexpectedly (%s) ES El examen de música terminó inesperadamente (%s) FI Musiikkihaku lopetettiin odottamatta (%s) FR L'analyse de la musique s'est terminée de façon inattendue (%s) @@ -20558,7 +20551,7 @@ DISCOVERING_FILES_PROGRESS CS Vyhledávání souborů DA Søger efter filer DE Dateien werden erkannt - EN Discovering files + EN Discovering music files ES Detectando archivos FI Etsitään tiedostoja FR Détection des fichiers @@ -20618,7 +20611,22 @@ DIRECTORY_NEW_PROGRESS CS Vyhledávání nových souborů DA Scanner nye filer DE Neue Dateien werden durchsucht - EN Scanning new files + EN Scanning new music files + ES Examinando archivos nuevos + FI Tarkistetaan uudet tiedostot + FR Analyse des nouveaux fichiers + IT Analisi di nuovi file in corso + NL Nieuwe bestanden scannen + NO Søker i nye filer + PL Trwa przeszukiwanie nowych plików + RU Сканирование новых файлов + SV Söka igenom nya filer + +DIRECTORY_MEDIA_PROGRESS + CS Prohledat nové soubory + DA Søg efter nye filer + DE Neue Dateien durchsuchen + EN Scanning new media files ES Examinando archivos nuevos FI Tarkistetaan uudet tiedostot FR Analyse des nouveaux fichiers @@ -20858,7 +20866,7 @@ PROGRESS_IMPORTER_COMPLETE_DESC CS Server ukončil prohledávání vaší sbírky hudby. DA Serveren er færdig med at gennemsøge din musiksamling. DE Der Server hat das Durchsuchen Ihrer Musiksammlung abgeschlossen. - EN The server has finished scanning your music collection. + EN The server has finished scanning your media library. ES El servidor ha finalizado el examen de su colección de música. FI Palvelin on nyt lopettanut musiikkikokoelmasi tarkistuksen. FR Le serveur a terminé d'analyser la collection musicale. @@ -21006,19 +21014,19 @@ RESTART_LATER SV Starta om senare RESTARTING_PLEASE_WAIT - CS Probíhá restartování Squeezebox Server. Před pokračováním chvíli vyčkejte... - DA Squeezebox Server er ved at blive genstartet. Vent et minuts tid før du fortsætter... - DE Squeezebox Server wird neu gestartet. Warten Sie eine Minute, bis Sie fortfahren... - EN Squeezebox Server is being restarted. Please wait a minute before you continue... - ES Se está reiniciando Squeezebox Server. Espere un minuto antes de continuar... - FI Squeezebox Server käynnistetään uudelleen. Odota hetki ennen jatkamista... - FR Le Squeezebox Server est en cours de redémarrage. Patientez une minute avant de continuer... - IT È in corso il riavvio di Squeezebox Server. Attendere un momento prima di continuare... - NL Squeezebox Server wordt opnieuw gestart. Wacht even voordat je verdergaat... - NO Squeezebox Server startes på nytt. Vent litt før du fortsetter ... - PL Trwa ponowne uruchamianie programu Squeezebox Server. Poczekaj chwilę, aby kontynuować... - RU Squeezebox Server перезапускается. Подождите... - SV Squeezebox Server startas om. Vänta en minut innan du fortsätter ... + CS Probíhá restartování Logitech Media Server. Před pokračováním chvíli vyčkejte... + DA Logitech Media Server er ved at blive genstartet. Vent et minuts tid før du fortsætter... + DE Logitech Media Server wird neu gestartet. Warten Sie eine Minute, bis Sie fortfahren... + EN Logitech Media Server is being restarted. Please wait a minute before you continue... + ES Se está reiniciando Logitech Media Server. Espere un minuto antes de continuar... + FI Logitech Media Server käynnistetään uudelleen. Odota hetki ennen jatkamista... + FR Le Logitech Media Server est en cours de redémarrage. Patientez une minute avant de continuer... + IT È in corso il riavvio di Logitech Media Server. Attendere un momento prima di continuare... + NL Logitech Media Server wordt opnieuw gestart. Wacht even voordat je verdergaat... + NO Logitech Media Server startes på nytt. Vent litt før du fortsetter ... + PL Trwa ponowne uruchamianie programu Logitech Media Server. Poczekaj chwilę, aby kontynuować... + RU Logitech Media Server перезапускается. Подождите... + SV Logitech Media Server startas om. Vänta en minut innan du fortsätter ... SETUP_VIEW_SCANNING CS Prohledávání - zobrazit průběh @@ -22057,35 +22065,35 @@ ERROR_PLAYLIST_ALMOST_FULL SV Spellistan är full: %s av %s spår lades till SQUEEZEBOX_SERVER_CONNECT - CS Připojit ke Squeezebox Server - DA Etabler forbindelse til Squeezebox Server - DE Mit Squeezebox Server verbinden - EN Connect to Squeezebox Server - ES Conectar a Squeezebox Server - FI Muodosta yhteys Squeezebox Serveriin - FR Se connecter au Squeezebox Server - HE התחבר ל-Squeezebox Server - IT Connetti a Squeezebox Server - NL Verbinding maken met Squeezebox Server - NO Kople til Squeezebox Server - PL Połącz z programem Squeezebox Server - RU Подключиться к Squeezebox Server - SV Anslut till Squeezebox Server + CS Připojit ke Logitech Media Server + DA Etabler forbindelse til Logitech Media Server + DE Mit Logitech Media Server verbinden + EN Connect to Logitech Media Server + ES Conectar a Logitech Media Server + FI Muodosta yhteys Logitech Media Serveriin + FR Se connecter au Logitech Media Server + HE התחבר ל-Logitech Media Server + IT Connetti a Logitech Media Server + NL Verbinding maken met Logitech Media Server + NO Kople til Logitech Media Server + PL Połącz z programem Logitech Media Server + RU Подключиться к Logitech Media Server + SV Anslut till Logitech Media Server SQUEEZEBOX_SERVER_CONNECT_ABBR - CS Squeezebox Server - DA Squeezebox Server - DE Squeezebox Server - EN Squeezebox Server - ES Squeezebox Server - FI Squeezebox Server - FR Squeezebox Server - IT Squeezebox Server - NL Squeezebox Server - NO Squeezebox Server - PL Squeezebox Server - RU Squeezebox Server - SV Squeezebox Server + CS Logitech Media Server + DA Logitech Media Server + DE Logitech Media Server + EN Logitech Media Server + ES Logitech Media Server + FI Logitech Media Server + FR Logitech Media Server + IT Logitech Media Server + NL Logitech Media Server + NO Logitech Media Server + PL Logitech Media Server + RU Logitech Media Server + SV Logitech Media Server CLOCK CS Hodiny @@ -22118,19 +22126,19 @@ BACKUP_ALARM SV Reservalarm CONTROLPANEL_TITLE - CS Ovládací panel Squeezebox Server - DA Kontrolpanel til Squeezebox Server - DE Squeezebox Server-Systemsteuerung - EN Squeezebox Server Control Panel - ES Panel de control de Squeezebox Server - FI Squeezebox Serverin ohjauspaneeli - FR Panneau de configuration du Squeezebox Server - IT Pannello di controllo di Squeezebox Server - NL Squeezebox Server-configuratiescherm - NO Kontrollpanel for Squeezebox Server - PL Panel sterowania programu Squeezebox Server - RU Панель управления Squeezebox Server - SV Kontrollpanelen för Squeezebox Server + CS Ovládací panel Logitech Media Server + DA Kontrolpanel til Logitech Media Server + DE Logitech Media Server-Systemsteuerung + EN Logitech Media Server Control Panel + ES Panel de control de Logitech Media Server + FI Logitech Media Serverin ohjauspaneeli + FR Panneau de configuration du Logitech Media Server + IT Pannello di controllo di Logitech Media Server + NL Logitech Media Server-configuratiescherm + NO Kontrollpanel for Logitech Media Server + PL Panel sterowania programu Logitech Media Server + RU Панель управления Logitech Media Server + SV Kontrollpanelen för Logitech Media Server CONTROLPANEL_SERVERSTATUS CS Stav @@ -22255,19 +22263,19 @@ CONTROLPANEL_MUSIC_LIBRARY SV Bibliotek CONTROLPANEL_AUTHENTICATION_REQUIRED - CS Pro přístup do Squeezebox Server je vyžadována autentizace - DA Du skal godkendes for at få adgang til Squeezebox Server - DE Für den Zugriff auf Squeezebox Server ist eine Authentifizierung erforderlich - EN Authentication is required to access Squeezebox Server - ES El acceso a Squeezebox Server requiere autenticación - FI Squeezebox Serverin käyttö vaatii todennuksen - FR Une authentification est requise pour accéder au Squeezebox Server - IT Per accedere a Squeezebox Server è necessario eseguire l'autenticazione - NL Verificatie vereist voor toegang tot Squeezebox Server - NO Det kreves godkjenning for å få tilgang til Squeezebox Server - PL W celu uzyskania dostępu do programu Squeezebox Server wymagane jest uwierzytelnienie - RU Для доступа к Squeezebox Server требуется проверка подлинности - SV Det krävs autentisering för att komma åt Squeezebox Server + CS Pro přístup do Logitech Media Server je vyžadována autentizace + DA Du skal godkendes for at få adgang til Logitech Media Server + DE Für den Zugriff auf Logitech Media Server ist eine Authentifizierung erforderlich + EN Authentication is required to access Logitech Media Server + ES El acceso a Logitech Media Server requiere autenticación + FI Logitech Media Serverin käyttö vaatii todennuksen + FR Une authentification est requise pour accéder au Logitech Media Server + IT Per accedere a Logitech Media Server è necessario eseguire l'autenticazione + NL Verificatie vereist voor toegang tot Logitech Media Server + NO Det kreves godkjenning for å få tilgang til Logitech Media Server + PL W celu uzyskania dostępu do programu Logitech Media Server wymagane jest uwierzytelnienie + RU Для доступа к Logitech Media Server требуется проверка подлинности + SV Det krävs autentisering för att komma åt Logitech Media Server CONTROLPANEL_WEB_UI CS Rozhraní na webu @@ -22390,49 +22398,49 @@ CONTROLPANEL_SHOW_SCANNER_LOG SV Visa loggfilen för sökning CONTROLPANEL_UPDATE_AVAILABLE - CS Aktualizovaná verze Squeezebox Server je k dispozici a připravena k instalaci. - DA Der findes en opdateret version af Squeezebox Server som er klar til at blive installeret. - DE Eine aktualisierte Version von Squeezebox Server ist verfügbar und kann installiert werden. - EN An updated version of Squeezebox Server is available and ready to install. - ES Hay disponible una versión actualizada de Squeezebox Server y está lista para instalar. - FI Squeezebox Serverin päivitetty versio on käytettävissä ja valmiina asennusta varten. - FR Une nouvelle version du Squeezebox Server est disponible et prête à l'installation. - IT È disponibile una versione aggiornata di Squeezebox Server, pronta per essere installata. - NL Er is een bijgewerkte versie van Squeezebox Server beschikbaar voor installatie. - NO En oppdatert versjon av Squeezebox Server er tilgjengelig og klar til installering. - PL Zaktualizowana wersja programu Squeezebox Server jest dostępna i gotowa do zainstalowania. - RU Доступна и готова к установке обновленная версия Squeezebox Server. - SV En uppdaterad version av Squeezebox Server finns tillgänglig och klar att installeras. + CS Aktualizovaná verze Logitech Media Server je k dispozici a připravena k instalaci. + DA Der findes en opdateret version af Logitech Media Server som er klar til at blive installeret. + DE Eine aktualisierte Version von Logitech Media Server ist verfügbar und kann installiert werden. + EN An updated version of Logitech Media Server is available and ready to install. + ES Hay disponible una versión actualizada de Logitech Media Server y está lista para instalar. + FI Logitech Media Serverin päivitetty versio on käytettävissä ja valmiina asennusta varten. + FR Une nouvelle version du Logitech Media Server est disponible et prête à l'installation. + IT È disponibile una versione aggiornata di Logitech Media Server, pronta per essere installata. + NL Er is een bijgewerkte versie van Logitech Media Server beschikbaar voor installatie. + NO En oppdatert versjon av Logitech Media Server er tilgjengelig og klar til installering. + PL Zaktualizowana wersja programu Logitech Media Server jest dostępna i gotowa do zainstalowania. + RU Доступна и готова к установке обновленная версия Logitech Media Server. + SV En uppdaterad version av Logitech Media Server finns tillgänglig och klar att installeras. PREFPANE_UPDATE_AVAILABLE - CS Pro instalaci je k dispozici aktualizovaná verze Squeezebox Server. Přejděte na na Squeezebox Server v systémových vlastnostech pro spuštění aktualizace. - DA En opdateret version af Squeezebox Server er klar til at blive installeret. Du kan starte opgraderingen under Systemindstillinger på Squeezebox Server. - DE Eine aktualisierte Version von Squeezebox Server ist verfügbar und kann installiert werden. Wählen Sie unter 'Systemeinstellungen' die Option 'Squeezebox Server', um das Update zu starten. - EN An updated version of Squeezebox Server is available and ready to install. Visit the Squeezebox Server in System Preferences to start the upgrade. - ES Hay disponible una versión actualizada de Squeezebox Server y está lista para instalar. Visite Squeezebox Server en Preferencias del sistema para iniciar la actualización. - FI Squeezebox Serverin päivitetty versio on käytettävissä ja valmiina asennusta varten. Käynnistä päivitys Squeezebox Server -kohdassa järjestelmäasetuksissa. - FR Une version mise à jour de Squeezebox Server est disponible et peut être installée. Accédez à Squeezebox Server dans les Préférences système pour démarrer la mise à niveau. - IT È disponibile una versione aggiornata di Squeezebox Server, pronta per essere installata. Per avviare l'aggiornamento, accedere a Squeezebox Server in Preferenze di Sistema. - NL Er is een bijgewerkte versie van Squeezebox Server beschikbaar voor installatie. Ga naar Squeezebox Server in Systeemvoorkeuren om de upgrade te starten. - NO En oppdatert versjon av Squeezebox Server er tilgjengelig og klar til installering. Du kan starte oppgraderingen fra Squeezebox Server i Systemvalg. - PL Zaktualizowana wersja programu Squeezebox Server jest gotowa i dostępna do zainstalowania. Aby rozpocząć uaktualnianie, otwórz ekran programu Squeezebox Server w programie Preferencje systemowe. - RU Доступна и готова к установке обновленная версия сервера Squeezebox Server. Чтобы начать установку обновления, посетите Squeezebox Server в приложении System Preferences. - SV En uppdaterad version av Squeezebox Server finns tillgänglig och redo att installeras. Gå till Squeezebox Server i systeminställningarna för att starta uppgraderingen. + CS Pro instalaci je k dispozici aktualizovaná verze Logitech Media Server. Přejděte na na Logitech Media Server v systémových vlastnostech pro spuštění aktualizace. + DA En opdateret version af Logitech Media Server er klar til at blive installeret. Du kan starte opgraderingen under Systemindstillinger på Logitech Media Server. + DE Eine aktualisierte Version von Logitech Media Server ist verfügbar und kann installiert werden. Wählen Sie unter 'Systemeinstellungen' die Option 'Logitech Media Server', um das Update zu starten. + EN An updated version of Logitech Media Server is available and ready to install. Visit the Logitech Media Server in System Preferences to start the upgrade. + ES Hay disponible una versión actualizada de Logitech Media Server y está lista para instalar. Visite Logitech Media Server en Preferencias del sistema para iniciar la actualización. + FI Logitech Media Serverin päivitetty versio on käytettävissä ja valmiina asennusta varten. Käynnistä päivitys Logitech Media Server -kohdassa järjestelmäasetuksissa. + FR Une version mise à jour de Logitech Media Server est disponible et peut être installée. Accédez à Logitech Media Server dans les Préférences système pour démarrer la mise à niveau. + IT È disponibile una versione aggiornata di Logitech Media Server, pronta per essere installata. Per avviare l'aggiornamento, accedere a Logitech Media Server in Preferenze di Sistema. + NL Er is een bijgewerkte versie van Logitech Media Server beschikbaar voor installatie. Ga naar Logitech Media Server in Systeemvoorkeuren om de upgrade te starten. + NO En oppdatert versjon av Logitech Media Server er tilgjengelig og klar til installering. Du kan starte oppgraderingen fra Logitech Media Server i Systemvalg. + PL Zaktualizowana wersja programu Logitech Media Server jest gotowa i dostępna do zainstalowania. Aby rozpocząć uaktualnianie, otwórz ekran programu Logitech Media Server w programie Preferencje systemowe. + RU Доступна и готова к установке обновленная версия сервера Logitech Media Server. Чтобы начать установку обновления, посетите Logitech Media Server в приложении System Preferences. + SV En uppdaterad version av Logitech Media Server finns tillgänglig och redo att installeras. Gå till Logitech Media Server i systeminställningarna för att starta uppgraderingen. CONTROLPANEL_NO_UPDATE_AVAILABLE - CS K dispozici není žádná aktualizovaná verze Squeezebox Server. - DA Der findes ikke en nyere version af Squeezebox Server. - DE Es ist keine aktualisierte Version von Squeezebox Server verfügbar. - EN There's no updated Squeezebox Server version available. - ES No hay disponible ninguna versión actualizada de Squeezebox Server. - FI Squeezebox Serveristä ei ole saatavilla päivitettyä versiota. - FR Aucune nouvelle version du Squeezebox Server n'est disponible. - IT Non è disponibile alcuna versione aggiornata di Squeezebox Server. - NL Er is geen bijgewerkte versie van Squeezebox Server beschikbaar. - NO Det finnes ingen oppdatert versjon av Squeezebox Server tilgjengelig. - PL Brak dostępnej zaktualizowanej wersji programu Squeezebox Server. - RU Нет доступных обновленных версий Squeezebox Server. - SV Det finns ingen uppdaterad version av Squeezebox Server tillgänglig. + CS K dispozici není žádná aktualizovaná verze Logitech Media Server. + DA Der findes ikke en nyere version af Logitech Media Server. + DE Es ist keine aktualisierte Version von Logitech Media Server verfügbar. + EN There's no updated Logitech Media Server version available. + ES No hay disponible ninguna versión actualizada de Logitech Media Server. + FI Logitech Media Serveristä ei ole saatavilla päivitettyä versiota. + FR Aucune nouvelle version du Logitech Media Server n'est disponible. + IT Non è disponibile alcuna versione aggiornata di Logitech Media Server. + NL Er is geen bijgewerkte versie van Logitech Media Server beschikbaar. + NO Det finnes ingen oppdatert versjon av Logitech Media Server tilgjengelig. + PL Brak dostępnej zaktualizowanej wersji programu Logitech Media Server. + RU Нет доступных обновленных версий Logitech Media Server. + SV Det finns ingen uppdaterad version av Logitech Media Server tillgänglig. CONTROLPANEL_CHECK_UPDATE CS Hledat aktualizace @@ -22615,49 +22623,49 @@ CONTROLPANEL_SN_FAILURE_DESC SV Det kan röra sig om ett tillfälligt internetproblem eller om begränsningar som internetleverantören har infört. Om problemet kvarstår bör du kontrollera om brandväggen blockerar utgående trafik. CONTROLPANEL_SN_PROXY - CS Zjistili jsme, že váš Squeezebox Server je konfigurován k použití proxy serveru. V této konfiguraci nemůže být testována konektivita k mysqueezebox.com na portu 3483. - DA Din Squeezebox Server er indstillet til at bruge en proxyserver. Det betyder at forbindelsen til mysqueezebox.com via port 3483 ikke kan afprøves. - DE Ihr Squeezebox Server ist für die Verwendung eines Proxyservers konfiguriert. Bei dieser Konfiguration kann die Verbindung zu mysqueezebox.com über Port 3483 nicht getestet werden. - EN We've seen that your Squeezebox Server is configured to use a proxy server. In this configuration connectivity to mysqueezebox.com on port 3483 can't be tested. - ES Hemos comprobado que Squeezebox Server está configurado para utilizar un servidor proxy. Esta configuración no permite comprobar la conectividad a mysqueezebox.com en el puerto 3483. - FI Squeezebox Server on määritetty käyttämään välityspalvelinta. Tässä kokoonpanossa yhteyttä sivustoon mysqueezebox.com portin 3483 kautta ei voi testata. - FR La configuration de votre Squeezebox Server indique l'utilisation d'un serveur proxy. Cette configuration ne permet pas de tester la connectivité à mysqueezebox.com sur le port 3483. - IT È stato rilevato che Squeezebox Server è configurato per utilizzare un server proxy. Con questa configurazione non è possibile verificare la connessione con mysqueezebox.com sulla porta 3483. - NL Je Squeezebox Server is geconfigureerd voor gebruik van een proxyserver. In deze configuratie kan de verbinding met 'mysqueezebox.com' op poort 3483 niet getest worden. - NO Squeezebox Server er konfigurert til å bruke en proxy-server. Med denne konfigureringen kan ikke tilkoplingen til mysqueezebox.com på port 3483 testes. - PL Program Squeezebox Server jest skonfigurowany w celu użycia serwera proxy. W przypadku takiej konfiguracji nie można przetestować połączenia z witryną mysqueezebox.com na porcie 3483. - RU Обнаружено, что ваш Squeezebox Server настроен на использование прокси-сервера. В такой конфигурации подключение к сайту mysqueezebox.com на порту 3483 невозможно проверить. - SV När Squeezebox Server har konfigurerats för användning med en proxyserver går det inte att kontrollera anslutningen till port 3483 på mysqueezebox.com. + CS Zjistili jsme, že váš Logitech Media Server je konfigurován k použití proxy serveru. V této konfiguraci nemůže být testována konektivita k mysqueezebox.com na portu 3483. + DA Din Logitech Media Server er indstillet til at bruge en proxyserver. Det betyder at forbindelsen til mysqueezebox.com via port 3483 ikke kan afprøves. + DE Ihr Logitech Media Server ist für die Verwendung eines Proxyservers konfiguriert. Bei dieser Konfiguration kann die Verbindung zu mysqueezebox.com über Port 3483 nicht getestet werden. + EN We've seen that your Logitech Media Server is configured to use a proxy server. In this configuration connectivity to mysqueezebox.com on port 3483 can't be tested. + ES Hemos comprobado que Logitech Media Server está configurado para utilizar un servidor proxy. Esta configuración no permite comprobar la conectividad a mysqueezebox.com en el puerto 3483. + FI Logitech Media Server on määritetty käyttämään välityspalvelinta. Tässä kokoonpanossa yhteyttä sivustoon mysqueezebox.com portin 3483 kautta ei voi testata. + FR La configuration de votre Logitech Media Server indique l'utilisation d'un serveur proxy. Cette configuration ne permet pas de tester la connectivité à mysqueezebox.com sur le port 3483. + IT È stato rilevato che Logitech Media Server è configurato per utilizzare un server proxy. Con questa configurazione non è possibile verificare la connessione con mysqueezebox.com sulla porta 3483. + NL Je Logitech Media Server is geconfigureerd voor gebruik van een proxyserver. In deze configuratie kan de verbinding met 'mysqueezebox.com' op poort 3483 niet getest worden. + NO Logitech Media Server er konfigurert til å bruke en proxy-server. Med denne konfigureringen kan ikke tilkoplingen til mysqueezebox.com på port 3483 testes. + PL Program Logitech Media Server jest skonfigurowany w celu użycia serwera proxy. W przypadku takiej konfiguracji nie można przetestować połączenia z witryną mysqueezebox.com na porcie 3483. + RU Обнаружено, что ваш Logitech Media Server настроен на использование прокси-сервера. В такой конфигурации подключение к сайту mysqueezebox.com на порту 3483 невозможно проверить. + SV När Logitech Media Server har konfigurerats för användning med en proxyserver går det inte att kontrollera anslutningen till port 3483 på mysqueezebox.com. CONTROLPANEL_PORTCONFLICT - CS Squeezebox Server není v provozu, ale nějaká aplikace používá stejný port (%s). - DA Squeezebox Server kører ikke, men et andet program benytter den samme port (%s). - DE Squeezebox Server wird nicht ausgeführt. Port (%s) wird von einer anderen Anwendung verwendet. - EN Squeezebox Server is not running, but some application is using the same port (%s). - ES Squeezebox Server no está en ejecución, pero alguna aplicación está usando el mismo puerto (%s). - FI Squeezebox Server ei ole käynnissä, mutta jokin sovellus käyttää samaa porttia (%s). - FR Le Squeezebox Server n'est pas en cours d'exécution, mais une application utilise actuellement le même port (%s). - IT Squeezebox Server non è in esecuzione ma qualche applicazione sta utilizzando la stessa porta (%s). - NL Squeezebox Server is niet actief, maar een toepassing gebruikt dezelfde poort (%s). - NO Squeezebox Server kjører ikke, men et annet program bruker samme port (%s). - PL Program Squeezebox Server nie jest uruchomiony, ale jakaś aplikacja używa tego samego portu (%s). - RU Squeezebox Server не выполняется, но какое-то приложение использует этот же порт (%s). - SV Squeezebox Server körs inte men något program använder samma port (%s). + CS Logitech Media Server není v provozu, ale nějaká aplikace používá stejný port (%s). + DA Logitech Media Server kører ikke, men et andet program benytter den samme port (%s). + DE Logitech Media Server wird nicht ausgeführt. Port (%s) wird von einer anderen Anwendung verwendet. + EN Logitech Media Server is not running, but some application is using the same port (%s). + ES Logitech Media Server no está en ejecución, pero alguna aplicación está usando el mismo puerto (%s). + FI Logitech Media Server ei ole käynnissä, mutta jokin sovellus käyttää samaa porttia (%s). + FR Le Logitech Media Server n'est pas en cours d'exécution, mais une application utilise actuellement le même port (%s). + IT Logitech Media Server non è in esecuzione ma qualche applicazione sta utilizzando la stessa porta (%s). + NL Logitech Media Server is niet actief, maar een toepassing gebruikt dezelfde poort (%s). + NO Logitech Media Server kjører ikke, men et annet program bruker samme port (%s). + PL Program Logitech Media Server nie jest uruchomiony, ale jakaś aplikacja używa tego samego portu (%s). + RU Logitech Media Server не выполняется, но какое-то приложение использует этот же порт (%s). + SV Logitech Media Server körs inte men något program använder samma port (%s). CONTROLPANEL_PORTBLOCKED - CS Squeezebox Server je v provozu, ale nemůže se spojit s portem %s. - DA Squeezebox Server kører men kan ikke kontaktes på port %s. - DE Squeezebox Server wird ausgeführt, kann aber an Port %s nicht erreicht werden. - EN Squeezebox Server is running but can't be contacted on port %s. - ES Squeezebox Server está en ejecución pero no se puede contactar con él en el puerto %s. - FI Squeezebox Server on käynnissä, mutta siihen ei saada yhteyttä portissa %s. - FR Le Squeezebox Server est en cours d'exécution mais ne peut être contacté sur le port %s. - IT Squeezebox Server è in esecuzione ma non può essere contattato sulla porta %s - NL Squeezebox Server wordt uitgevoerd maar is niet toegankelijk via poort %s. - NO Squeezebox Server kjører, men kan ikke kontaktes på port %s - PL Program Squeezebox Server działa, ale nie można skontaktować się z nim na porcie %s. - RU Squeezebox Server выполняется, но подключение через порт %s невозможно. - SV Squeezebox Server körs men går inte att ansluta till port %s. + CS Logitech Media Server je v provozu, ale nemůže se spojit s portem %s. + DA Logitech Media Server kører men kan ikke kontaktes på port %s. + DE Logitech Media Server wird ausgeführt, kann aber an Port %s nicht erreicht werden. + EN Logitech Media Server is running but can't be contacted on port %s. + ES Logitech Media Server está en ejecución pero no se puede contactar con él en el puerto %s. + FI Logitech Media Server on käynnissä, mutta siihen ei saada yhteyttä portissa %s. + FR Le Logitech Media Server est en cours d'exécution mais ne peut être contacté sur le port %s. + IT Logitech Media Server è in esecuzione ma non può essere contattato sulla porta %s + NL Logitech Media Server wordt uitgevoerd maar is niet toegankelijk via poort %s. + NO Logitech Media Server kjører, men kan ikke kontaktes på port %s + PL Program Logitech Media Server działa, ale nie można skontaktować się z nim na porcie %s. + RU Logitech Media Server выполняется, но подключение через порт %s невозможно. + SV Logitech Media Server körs men går inte att ansluta till port %s. CONTROLPANEL_PORTBLOCKED_APPS CS Vaše spojení mohou blokovat následující aplikace: @@ -22675,19 +22683,19 @@ CONTROLPANEL_PORTBLOCKED_APPS SV Följande program kan blockera anslutningen: CONTROLPANEL_CONFLICT_CISCOVPNSTATEFULINSPECTION - CS Pokud se Squeezebox Server narazíte na problémy s konektivitou, ujistěte se laskavě, že máte vypnutý "Plný firewall (Vždy zapnuto)" - DA Hvis der er problemer med forbindelsen til og fra Squeezebox Server, skal du kontrollere at "Stateful Firewall (Always On)" er slået fra - DE Wenn es Verbindungsprobleme mit Squeezebox Server gibt, vergewissern Sie sich, dass die Option "Statusbehaftete Firewall (immer aktiv)" deaktiviert ist. - EN If you encounter connectivity issues with Squeezebox Server, please make sure "Stateful Firewall (Always On)" is turned off - ES Si surgen problemas de conectividad con Squeezebox Server, asegúrese de que la opción "Stateful Firewall (Always On)" está desactivada - FI Jos Squeezebox Serverin kanssa on yhteysongelmia, varmista, että Tilallinen palomuuri (aina käytössä) -valinta ei ole valittuna. - FR Si vous rencontrez des problèmes de connectivité avec Squeezebox Server, vérifiez que l'option "Pare-feu stateful (toujours activé)" est désactivée. - IT In caso di problemi di connessione con Squeezebox Server, verificare che il firewall con stato sia disattivato. - NL Ondervind je verbindingsproblemen met Squeezebox Server, zorg er dan voor dat 'Stateful Firewall (Altijd aan)' is uitgeschakeld - NO Hvis du har tilkoplingsproblemer med Squeezebox Server, må du sørge for at "Tilstandsbevisst brannmur (Alltid på)" er slått av + CS Pokud se Logitech Media Server narazíte na problémy s konektivitou, ujistěte se laskavě, že máte vypnutý "Plný firewall (Vždy zapnuto)" + DA Hvis der er problemer med forbindelsen til og fra Logitech Media Server, skal du kontrollere at "Stateful Firewall (Always On)" er slået fra + DE Wenn es Verbindungsprobleme mit Logitech Media Server gibt, vergewissern Sie sich, dass die Option "Statusbehaftete Firewall (immer aktiv)" deaktiviert ist. + EN If you encounter connectivity issues with Logitech Media Server, please make sure "Stateful Firewall (Always On)" is turned off + ES Si surgen problemas de conectividad con Logitech Media Server, asegúrese de que la opción "Stateful Firewall (Always On)" está desactivada + FI Jos Logitech Media Serverin kanssa on yhteysongelmia, varmista, että Tilallinen palomuuri (aina käytössä) -valinta ei ole valittuna. + FR Si vous rencontrez des problèmes de connectivité avec Logitech Media Server, vérifiez que l'option "Pare-feu stateful (toujours activé)" est désactivée. + IT In caso di problemi di connessione con Logitech Media Server, verificare che il firewall con stato sia disattivato. + NL Ondervind je verbindingsproblemen met Logitech Media Server, zorg er dan voor dat 'Stateful Firewall (Altijd aan)' is uitgeschakeld + NO Hvis du har tilkoplingsproblemer med Logitech Media Server, må du sørge for at "Tilstandsbevisst brannmur (Alltid på)" er slått av PL W przypadku wystąpienia problemów z łącznością w programie Squeezebox, upewnij się, że opcja „Zapora stanowa (zawsze włączona)” jest wyłączona - RU При возникновении проблем с подключением к Squeezebox Server убедитесь, что параметр "Брандмауэр с отслеживанием состояния (Всегда включено)" отключен - SV Om det uppstår anslutningsproblem med Squeezebox Server, bör du kontrollera att alternativet Tillståndskänslig brandvägg (alltid på) är avaktiverat + RU При возникновении проблем с подключением к Logitech Media Server убедитесь, что параметр "Брандмауэр с отслеживанием состояния (Всегда включено)" отключен + SV Om det uppstår anslutningsproblem med Logitech Media Server, bör du kontrollera att alternativet Tillståndskänslig brandvägg (alltid på) är avaktiverat CONTROLPANEL_CONFLICT_SCPERL CS Pokud provozujete SC s použitím verze perl, pak je to v pořádku a očekáváno. @@ -22720,19 +22728,19 @@ CONTROLPANEL_OTHER_ISSUE SV Eventuellt programvarukonflikt upptäcktes CONTROLPANEL_OTHER_ISSUE_ESETPORTFILTERING - CS ESET Antivirus nebo Smart Security může při spuštění Squeezebox Serveru způsobovat problémy. Pokud dojde k chybě při spuštění Squeezebox Serveru, ujistěte se, že jste zrušili zaškrtnutí filtrování portů pro SqueezeboxSvr.exe v Pokročilém nastavení ESET / Antivirus a antispyware / Ochrana webového přístupu / HTTP, HTTPS / Webové prohlížeče. - DA ESET Antivirus eller Smart Security kan skabe problemer når du starter Squeezebox Server. Hvis du ikke kan starte Squeezebox Server, skal du sørge for at porten som bruges af SqueezeSvr.exe, ikke er lukket i ESET Advanced Settings/Antivirus og antispyware/Web access protection/HTTP, HTTPS/Web browsers. - DE ESET Antivirus oder ESET Smart Security können beim Starten von Squeezebox Server Probleme verursachen. Wenn beim Starten von Squeezebox Server Fehler auftreten, sollten Sie prüfen, ob Sie unter ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers die Portfilterung für 'SqueezeSvr.exe' deaktiviert haben. - EN ESET Antivirus or Smart Security can cause problems starting Squeezebox Server. If you experience failure starting Squeezebox Server, then make sure you have unchecked port filtering for SqueezeSvr.exe in ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. - ES ESET Antivirus o Smart Security pueden producir problemas a la hora de iniciar Squeezebox Server. Si no puede iniciar Squeezebox Server, asegúrese de no tener seleccionada la opción de filtrado de puertos para SqueezeSvr.exe en ESET: Configuración avanzada/Antivirus y antiespía/Protección del tráfico de Internet/HTTP, HTTPS/Navegadores de Internet. - FI ESET Antivirus tai Smart Security saattavat aiheuttaa ongelmia Squeezebox Serverin käynnistyksessä. Jos Squeezebox Serverin käynnistys ei onnistu, varmista, että olet poistanut portinsuodatuksen valinnan SqueezeboxSvr.exe-tiedostolle kohteessa ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. - FR L'antivirus ESET ou Smart Security peut être à l'origine de difficultés au démarrage de Squeezebox Server. En cas d'échec du démarrage de Squeezebox Server, vérifiez que le filtrage des ports n'est pas activé pour SqueezeSvr.exe sous ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. - IT L'antivirus ESET o Smart Security possono causare problemi di avvio di Squeezebox Server. Se Squeezebox Server non si avvia, deselezionare il filtraggio delle porte per SqueezeSvr.exe in Impostazioni avanzate/Antivirus e antispyware/Protezione accesso Web/HTTP di ESET e nei browser HTTPS/Web. - NL ESET Antivirus of Smart Security kan problemen veroorzaken bij het opstarten van Squeezebox Server. Controleer in dit geval of je het filteren van poorten hebt uitgeschakeld voor SqueezeSvr.exe in ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. - NO ESET Antivirus og Smart Security kan skape problemer med oppstarten av Squeezebox Server. Hvis du ikke får til å starte Squeezebox Server, må du sikre at du ikke har merket av for portfiltrering for SqueezeSvr.exe i ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. - PL Program ESET Antivirus lub Smart Security może powodować problemy z uruchomieniem programu Squeezebox Server. W przypadku napotkania problemu z uruchomieniem programu Squeezebox Server należy sprawdzić, czy wyłączono opcję filtrowania portów dla programu SqueezeSvr.exe w ustawieniach zaawansowanych funkcji antywirusowych i anty-spyware programu ESET, a także w ustawieniach zabezpieczeń dostępu do sieci Web oraz protokołów HTTP/HTTPS przeglądarki internetowej. - RU Антивирусная программа ESET или Smart Security может привести к неполадкам при запуске Squeezebox Server. Если возникают ошибки при запуске Squeezebox Server, убедитесь, что для SqueezeSvr.exe отключена фильтрация портов в разделе ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. - SV Om ESET Antivirus och Smart Security är installerade kan det uppstå problem när Squeezebox Server ska startas. Vid eventuella problem bör du kontrollera att du har avmarkerat portfiltrering för SqueezeboxSvr.exe i ESET under Avancerade inställningar/Skydd mot virus och spionprogram/Webbåtkomstskydd/HTTP, HTTPS/Webbläsare. + CS ESET Antivirus nebo Smart Security může při spuštění Logitech Media Serveru způsobovat problémy. Pokud dojde k chybě při spuštění Logitech Media Serveru, ujistěte se, že jste zrušili zaškrtnutí filtrování portů pro SqueezeboxSvr.exe v Pokročilém nastavení ESET / Antivirus a antispyware / Ochrana webového přístupu / HTTP, HTTPS / Webové prohlížeče. + DA ESET Antivirus eller Smart Security kan skabe problemer når du starter Logitech Media Server. Hvis du ikke kan starte Logitech Media Server, skal du sørge for at porten som bruges af SqueezeSvr.exe, ikke er lukket i ESET Advanced Settings/Antivirus og antispyware/Web access protection/HTTP, HTTPS/Web browsers. + DE ESET Antivirus oder ESET Smart Security können beim Starten von Logitech Media Server Probleme verursachen. Wenn beim Starten von Logitech Media Server Fehler auftreten, sollten Sie prüfen, ob Sie unter ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers die Portfilterung für 'SqueezeSvr.exe' deaktiviert haben. + EN ESET Antivirus or Smart Security can cause problems starting Logitech Media Server. If you experience failure starting Logitech Media Server, then make sure you have unchecked port filtering for SqueezeSvr.exe in ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. + ES ESET Antivirus o Smart Security pueden producir problemas a la hora de iniciar Logitech Media Server. Si no puede iniciar Logitech Media Server, asegúrese de no tener seleccionada la opción de filtrado de puertos para SqueezeSvr.exe en ESET: Configuración avanzada/Antivirus y antiespía/Protección del tráfico de Internet/HTTP, HTTPS/Navegadores de Internet. + FI ESET Antivirus tai Smart Security saattavat aiheuttaa ongelmia Logitech Media Serverin käynnistyksessä. Jos Logitech Media Serverin käynnistys ei onnistu, varmista, että olet poistanut portinsuodatuksen valinnan SqueezeboxSvr.exe-tiedostolle kohteessa ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. + FR L'antivirus ESET ou Smart Security peut être à l'origine de difficultés au démarrage de Logitech Media Server. En cas d'échec du démarrage de Logitech Media Server, vérifiez que le filtrage des ports n'est pas activé pour SqueezeSvr.exe sous ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. + IT L'antivirus ESET o Smart Security possono causare problemi di avvio di Logitech Media Server. Se Logitech Media Server non si avvia, deselezionare il filtraggio delle porte per SqueezeSvr.exe in Impostazioni avanzate/Antivirus e antispyware/Protezione accesso Web/HTTP di ESET e nei browser HTTPS/Web. + NL ESET Antivirus of Smart Security kan problemen veroorzaken bij het opstarten van Logitech Media Server. Controleer in dit geval of je het filteren van poorten hebt uitgeschakeld voor SqueezeSvr.exe in ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. + NO ESET Antivirus og Smart Security kan skape problemer med oppstarten av Logitech Media Server. Hvis du ikke får til å starte Logitech Media Server, må du sikre at du ikke har merket av for portfiltrering for SqueezeSvr.exe i ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. + PL Program ESET Antivirus lub Smart Security może powodować problemy z uruchomieniem programu Logitech Media Server. W przypadku napotkania problemu z uruchomieniem programu Logitech Media Server należy sprawdzić, czy wyłączono opcję filtrowania portów dla programu SqueezeSvr.exe w ustawieniach zaawansowanych funkcji antywirusowych i anty-spyware programu ESET, a także w ustawieniach zabezpieczeń dostępu do sieci Web oraz protokołów HTTP/HTTPS przeglądarki internetowej. + RU Антивирусная программа ESET или Smart Security может привести к неполадкам при запуске Logitech Media Server. Если возникают ошибки при запуске Logitech Media Server, убедитесь, что для SqueezeSvr.exe отключена фильтрация портов в разделе ESET Advanced Settings/Antivirus and antispyware/Web access protection/HTTP, HTTPS/Web browsers. + SV Om ESET Antivirus och Smart Security är installerade kan det uppstå problem när Logitech Media Server ska startas. Vid eventuella problem bör du kontrollera att du har avmarkerat portfiltrering för SqueezeboxSvr.exe i ESET under Avancerade inställningar/Skydd mot virus och spionprogram/Webbåtkomstskydd/HTTP, HTTPS/Webbläsare. CONTROLPANEL_REFRESH CS Obnovit @@ -22796,49 +22804,49 @@ CLEANUP_SUCCESS SV Rensningen slutfördes utan problem CLEANUP_PLEASE_RESTART_SC - CS Restartujte prosím Squeezebox Server k uskutečnění změn. - DA Du skal genstarte Squeezebox Server for at ændringerne kan træde i kraft. - DE Squeezebox Server muss neu gestartet werden, damit die Änderungen in Kraft treten. - EN Please restart Squeezebox Server for the changes to take effect. - ES Reinicie Squeezebox Server para que los cambios entren en vigor. - FI Käynnistä Squeezebox Server uudelleen, jotta muutokset tulevat voimaan. - FR Redémarrez le Squeezebox Server pour appliquer les modifications. - IT Per applicare le modifiche, è necessario riavviare Squeezebox Server. - NL Start Squeezebox Server opnieuw om de wijzigingen door te voeren. - NO Du må starte Squeezebox Server på nytt for at endringene skal tre i kraft. - PL Aby wprowadzić zmiany, należy ponownie uruchomić program Squeezebox Server. - RU Перезапустите Squeezebox Server, чтобы изменения вступили в силу. - SV Ändringarna träder i kraft när du startar om Squeezebox Server. + CS Restartujte prosím Logitech Media Server k uskutečnění změn. + DA Du skal genstarte Logitech Media Server for at ændringerne kan træde i kraft. + DE Logitech Media Server muss neu gestartet werden, damit die Änderungen in Kraft treten. + EN Please restart Logitech Media Server for the changes to take effect. + ES Reinicie Logitech Media Server para que los cambios entren en vigor. + FI Käynnistä Logitech Media Server uudelleen, jotta muutokset tulevat voimaan. + FR Redémarrez le Logitech Media Server pour appliquer les modifications. + IT Per applicare le modifiche, è necessario riavviare Logitech Media Server. + NL Start Logitech Media Server opnieuw om de wijzigingen door te voeren. + NO Du må starte Logitech Media Server på nytt for at endringene skal tre i kraft. + PL Aby wprowadzić zmiany, należy ponownie uruchomić program Logitech Media Server. + RU Перезапустите Logitech Media Server, чтобы изменения вступили в силу. + SV Ändringarna träder i kraft när du startar om Logitech Media Server. CLEANUP_PLEASE_STOP_SC - CS Před spuštěním čištění prosím zastavte Squeezebox Server. - DA Du skal stoppe Squeezebox Server før du foretager oprydningen. - DE Vor der Bereinigung muss Squeezebox Server beendet werden. - EN Please Stop Squeezebox Server before running the cleanup. - ES Detenga Squeezebox Server antes de ejecutar la limpieza. - FI Sulje Squeezebox Server ennen puhdistuksen suorittamista. - FR Arrêtez le Squeezebox Server avant de lancer le nettoyage. - IT Prima di eseguire la pulizia, arrestare Squeezebox Server. - NL Stop Squeezebox Server voordat je de opschoning uitvoert. - NO Stopp Squeezebox Server før du kjører oppryddingen. - PL Przed rozpoczęciem czyszczenia zatrzymaj program Squeezebox Server. - RU Перед очисткой остановите работу Squeezebox Server. - SV Stoppa Squeezebox Server innan du börjar med rensningen. + CS Před spuštěním čištění prosím zastavte Logitech Media Server. + DA Du skal stoppe Logitech Media Server før du foretager oprydningen. + DE Vor der Bereinigung muss Logitech Media Server beendet werden. + EN Please Stop Logitech Media Server before running the cleanup. + ES Detenga Logitech Media Server antes de ejecutar la limpieza. + FI Sulje Logitech Media Server ennen puhdistuksen suorittamista. + FR Arrêtez le Logitech Media Server avant de lancer le nettoyage. + IT Prima di eseguire la pulizia, arrestare Logitech Media Server. + NL Stop Logitech Media Server voordat je de opschoning uitvoert. + NO Stopp Logitech Media Server før du kjører oppryddingen. + PL Przed rozpoczęciem czyszczenia zatrzymaj program Logitech Media Server. + RU Перед очисткой остановите работу Logitech Media Server. + SV Stoppa Logitech Media Server innan du börjar med rensningen. CLEANUP_WANT_TO_STOP_SC - CS Před zahájením čištění musí být Squeezebox Server zastaven. Chcete ho zastavit nyní? - DA Squeezebox Server skal stoppes før der kan foretages en oprydning. Vil du stoppe den nu? - DE Squeezebox Server muss vor der Ausführung der Bereinigung angehalten werden. Soll der Server jetzt angehalten werden? - EN Squeezebox Server has to be stopped before running the cleanup. Do you want to stop it now? - ES Antes de ejecutar la limpieza, se debe detener Squeezebox Server. ¿Desea detenerlo ahora? - FI Squeezebox Server täytyy pysäyttää ennen puhdistuksen suorittamista. Haluatko pysäyttää sen nyt? - FR Le Squeezebox Server doit être arrêté avant le lancement du nettoyage. Souhaitez-vous l'arrêter maintenant? - IT Prima di eseguire la pulizia è necessario arrestare Squeezebox Server. Arrestarlo adesso? - NL Squeezebox Server moet worden stopgezet, voordat de opschoning wordt uitgevoerd. Wil je de server nu stoppen? - NO Squeezebox Server må stoppes før oppryddingen kan kjøres. Vil du stoppe den nå? - PL Przed uruchomieniem czyszczenia należy zatrzymać program Squeezebox Server. Czy chcesz go zatrzymać teraz? - RU Перед выполнением очистки Squeezebox Server нужно остановить. Остановить сейчас? - SV Squeezebox Server måste stoppas innan du kör rensningen. Vill du stoppa den nu? + CS Před zahájením čištění musí být Logitech Media Server zastaven. Chcete ho zastavit nyní? + DA Logitech Media Server skal stoppes før der kan foretages en oprydning. Vil du stoppe den nu? + DE Logitech Media Server muss vor der Ausführung der Bereinigung angehalten werden. Soll der Server jetzt angehalten werden? + EN Logitech Media Server has to be stopped before running the cleanup. Do you want to stop it now? + ES Antes de ejecutar la limpieza, se debe detener Logitech Media Server. ¿Desea detenerlo ahora? + FI Logitech Media Server täytyy pysäyttää ennen puhdistuksen suorittamista. Haluatko pysäyttää sen nyt? + FR Le Logitech Media Server doit être arrêté avant le lancement du nettoyage. Souhaitez-vous l'arrêter maintenant? + IT Prima di eseguire la pulizia è necessario arrestare Logitech Media Server. Arrestarlo adesso? + NL Logitech Media Server moet worden stopgezet, voordat de opschoning wordt uitgevoerd. Wil je de server nu stoppen? + NO Logitech Media Server må stoppes før oppryddingen kan kjøres. Vil du stoppe den nå? + PL Przed uruchomieniem czyszczenia należy zatrzymać program Logitech Media Server. Czy chcesz go zatrzymać teraz? + RU Перед выполнением очистки Logitech Media Server нужно остановить. Остановить сейчас? + SV Logitech Media Server måste stoppas innan du kör rensningen. Vill du stoppa den nu? CLEANUP_USAGE CS Použití @@ -22874,7 +22882,7 @@ CLEANUP_MYSQL CS Smazat data MySQL (databáze informací o hudbě) DA Slet MySQL-data (database med oplysninger om musikken) DE MySQL-Daten löschen (Musikdatenbank) - EN Delete MySQL data (music information database) + EN Delete MySQL data (media information database) ES Eliminar datos de MySQL (base de datos de información de música) FI Poista MySQL-tiedot (musiikkitietokanta) FR Supprimer les données MySQL (base de données musicale) @@ -22934,7 +22942,7 @@ CLEANUP_CACHE CS Smazat odkládací složku, včetně databáze hudby, vyrovnávací paměti obalů alb atd. DA Ryd op i cachemappen, herunder musikdatabasen, cachelagrede coverbilleder osv. DE Zwischenspeicher-Ordner mit Musikdatenbank, Plattenhüllen usw. bereinigen. - EN Clean cache folder, including music database, artwork cache etc. + EN Clean cache folder, including media library database, artwork cache etc. ES Limpiar carpeta de caché, incluidos base de datos de música, caché de carátulas, etc. FI Tyhjennä välimuistikansio, mukaan luettuna musiikkitietokanta, kansitaiteen välimuisti jne. FR Nettoyer le dossier cache, y compris la base de données musicale, les pochettes, etc. @@ -22976,19 +22984,19 @@ CLEANUP_DELETING SV Raderar CONTROLPANEL_NO_STATUS - CS Nejsou dostupné žádné informace o statusu. Vezměte na vědomí, že pro zobrazení informací o statusu musí být Squeezebox Server aktivní a v provozu. - DA Der er ingen statusoplysninger. Husk at Squeezebox Server skal køre for at du kan se statusoplysninger. - DE Keine Statusinformationen verfügbar. Squeezebox Server muss eingerichtet und ausgeführt werden, damit die Statusinformationen angezeigt werden können. - EN No status information available. Please note that Squeezebox Server has to be up and running in order to display its status information. - ES No hay información de estado disponible. Tenga en cuenta que Squeezebox Server debe estar en ejecución para mostrar su información de estado. - FI Tilatietoja ei ole saatavilla. Huomaa, että Squeezebox Serverin on oltava käynnissä, jotta sen tilatiedot voitaisiin näyttää. - FR Aucune information sur l'état n'est disponible. Notez que le Squeezebox Server doit être en cours d'utilisation pour afficher ces informations. - IT Non sono disponibili informazioni sullo stato. Per visualizzare le informazioni sullo stato è necessario che Squeezebox Server sia in esecuzione. - NL Er is geen statusinformatie beschikbaar. Squeezebox Server moet actief zijn om statusinformatie te kunnen weergeven. - NO Ingen statusinformasjon er tilgjengelig. Squeezebox Server må kjøre for at den skal kunne vise statusinformasjon. - PL Brak dostępnych informacji o stanie. Aby możliwe było wyświetlenie informacji o stanie programu Squeezebox Server, musi on być uruchomiony. - RU Сведения о состоянии недоступны. Сведения о состоянии выводятся только в том случае, если Squeezebox Server выполняется. - SV Det finns ingen statusinformation. Tänk på att statusinformationen inte kan visas när Squeezebox Server inte körs. + CS Nejsou dostupné žádné informace o statusu. Vezměte na vědomí, že pro zobrazení informací o statusu musí být Logitech Media Server aktivní a v provozu. + DA Der er ingen statusoplysninger. Husk at Logitech Media Server skal køre for at du kan se statusoplysninger. + DE Keine Statusinformationen verfügbar. Logitech Media Server muss eingerichtet und ausgeführt werden, damit die Statusinformationen angezeigt werden können. + EN No status information available. Please note that Logitech Media Server has to be up and running in order to display its status information. + ES No hay información de estado disponible. Tenga en cuenta que Logitech Media Server debe estar en ejecución para mostrar su información de estado. + FI Tilatietoja ei ole saatavilla. Huomaa, että Logitech Media Serverin on oltava käynnissä, jotta sen tilatiedot voitaisiin näyttää. + FR Aucune information sur l'état n'est disponible. Notez que le Logitech Media Server doit être en cours d'utilisation pour afficher ces informations. + IT Non sono disponibili informazioni sullo stato. Per visualizzare le informazioni sullo stato è necessario che Logitech Media Server sia in esecuzione. + NL Er is geen statusinformatie beschikbaar. Logitech Media Server moet actief zijn om statusinformatie te kunnen weergeven. + NO Ingen statusinformasjon er tilgjengelig. Logitech Media Server må kjøre for at den skal kunne vise statusinformasjon. + PL Brak dostępnych informacji o stanie. Aby możliwe było wyświetlenie informacji o stanie programu Logitech Media Server, musi on być uruchomiony. + RU Сведения о состоянии недоступны. Сведения о состоянии выводятся только в том случае, если Logitech Media Server выполняется. + SV Det finns ingen statusinformation. Tänk på att statusinformationen inte kan visas när Logitech Media Server inte körs. CONTROLPANEL_NEED_ADMINISTRATOR CS Některé volby jsou zakázány, protože nejste administrátor. Abyste mohli tyto volby používat, spusťte \ntento nástroj jako administrátor. @@ -23066,34 +23074,34 @@ RUN_NEVER SV Starta inte automatiskt START_SQUEEZEBOX_SERVER - CS Spustit Squeezebox Server - DA Start Squeezebox Server - DE Squeezebox Server starten - EN Start Squeezebox Server - ES Iniciar Squeezebox Server - FI Käynnistä Squeezebox Server - FR Démarrer Squeezebox Server - IT Avvia Squeezebox Server - NL Squeezebox Server starten - NO Start Squeezebox Server - PL Uruchom program Squeezebox Server - RU Запустить Squeezebox Server - SV Starta Squeezebox Server + CS Spustit Logitech Media Server + DA Start Logitech Media Server + DE Logitech Media Server starten + EN Start Logitech Media Server + ES Iniciar Logitech Media Server + FI Käynnistä Logitech Media Server + FR Démarrer Logitech Media Server + IT Avvia Logitech Media Server + NL Logitech Media Server starten + NO Start Logitech Media Server + PL Uruchom program Logitech Media Server + RU Запустить Logitech Media Server + SV Starta Logitech Media Server STOP_SQUEEZEBOX_SERVER - CS Zastavit Squeezebox Server - DA Stop Squeezebox Server - DE Anhalten von Squeezebox Server - EN Stop Squeezebox Server - ES Detener Squeezebox Server - FI Pysäytä Squeezebox Server - FR Arrêter le Squeezebox Server - IT Arresta Squeezebox Server - NL Squeezebox Server stoppen - NO Stopp Squeezebox Server - PL Zatrzymaj program Squeezebox Server - RU Остановить Squeezebox Server - SV Stoppa Squeezebox Server + CS Zastavit Logitech Media Server + DA Stop Logitech Media Server + DE Anhalten von Logitech Media Server + EN Stop Logitech Media Server + ES Detener Logitech Media Server + FI Pysäytä Logitech Media Server + FR Arrêter le Logitech Media Server + IT Arresta Logitech Media Server + NL Logitech Media Server stoppen + NO Stopp Logitech Media Server + PL Zatrzymaj program Logitech Media Server + RU Остановить Logitech Media Server + SV Stoppa Logitech Media Server SIGNUP_LISTEN CS Poslouchejte hudbu! @@ -23336,19 +23344,19 @@ WHATS_NEXT SV Jag är klar. Vad gör jag nu? CONTINUE_TO_SQUEEZEBOX_SERVER - CS Pokračovat na Squeezebox Server pro správu nastavení k přehrávání vaší osobní sbírky hudby. - DA Fortsæt til Squeezebox Server hvor du kan konfigurere indstillinger og afspille dine musikfiler. - DE Weiter zu Squeezebox Server zum Verwalten der Einstellungen zur Wiedergabe Ihrer persönlichen Musiksammlung. - EN Continue to Squeezebox Server to manage settings for playing your personal music collection. - ES Continuar a Squeezebox Server para administrar la configuración de reproducción de su colección de música personal. - FI Jatka Squeezebox Serveriin. Siellä voit määrittää henkilökohtaisen musiikkikokoelmasi soittoasetukset. - FR Continuez vers le Squeezebox Server pour gérer les réglages de lecture de votre collection musicale. - IT Passare a Squeezebox Server per gestire le impostazioni per la riproduzione della raccolta di musica personale. - NL Ga door naar Squeezebox Server om instellingen te beheren voor het afspelen van je persoonlijke muziekcollectie. - NO Gå til Squeezebox Server for å angi innstillinger for avspilling av musikken din. - PL Przejdź do programu Squeezebox Server, aby zarządzać ustawieniami odtwarzania osobistej kolekcji muzyki. - RU Перейти в Squeezebox Server для управления настройками воспроизведения личной музыкальной коллекции. - SV Fortsätt till Squeezebox Server för att hantera inställningarna för uppspelning av din personliga musiksamling. + CS Pokračovat na Logitech Media Server pro správu nastavení k přehrávání vaší osobní sbírky hudby. + DA Fortsæt til Logitech Media Server hvor du kan konfigurere indstillinger og afspille dine musikfiler. + DE Weiter zu Logitech Media Server zum Verwalten der Einstellungen zur Wiedergabe Ihrer persönlichen Musiksammlung. + EN Continue to Logitech Media Server to manage settings for accessing your personal media library. + ES Continuar a Logitech Media Server para administrar la configuración de reproducción de su colección de música personal. + FI Jatka Logitech Media Serveriin. Siellä voit määrittää henkilökohtaisen musiikkikokoelmasi soittoasetukset. + FR Continuez vers le Logitech Media Server pour gérer les réglages de lecture de votre collection musicale. + IT Passare a Logitech Media Server per gestire le impostazioni per la riproduzione della raccolta di musica personale. + NL Ga door naar Logitech Media Server om instellingen te beheren voor het afspelen van je persoonlijke muziekcollectie. + NO Gå til Logitech Media Server for å angi innstillinger for avspilling av musikken din. + PL Przejdź do programu Logitech Media Server, aby zarządzać ustawieniami odtwarzania osobistej kolekcji muzyki. + RU Перейти в Logitech Media Server для управления настройками воспроизведения личной музыкальной коллекции. + SV Fortsätt till Logitech Media Server för att hantera inställningarna för uppspelning av din personliga musiksamling. REDUCED_TO_PREVENT_CLIPPING CS %s pro zabránění ořezávání @@ -23506,7 +23514,7 @@ NO_LIBRARY CS Není nakonfigurována žádná hudební knihovna DA Der er ikke konfigureret et musikbibliotek DE Es ist keine Musiksammlung konfiguriert - EN No music library configured + EN No media library configured ES No hay ninguna biblioteca de música configurada FI Musiikkikirjastoa ei ole määritetty FR Aucune collection musicale n'a été configurée diff --git a/types.conf b/types.conf index c581b9745f0..14e05587519 100644 --- a/types.conf +++ b/types.conf @@ -1,8 +1,8 @@ -# content types supported by the Squeezebox Server +# content types supported by the Logitech Media Server # first column is unique three letter identifier or URL scheme # second column is file suffixes or URL # third column are MIME content-types -# fourth column is a Squeezebox Server file type +# fourth column is a Logitech Media Server file type # blank lines, non-three column lines and content after a # is ignored. #########################################################################