svn path=/trunk/daap-sharp/; revision=51369
This commit is contained in:
James Willcox 2005-10-06 21:23:56 +00:00
Коммит 0352856423
58 изменённых файлов: 6052 добавлений и 0 удалений

2
AUTHORS Normal file
Просмотреть файл

@ -0,0 +1,2 @@
James Willcox <snorp@snorp.net>
Jon Lech Johansen <jon@nanocrew.net>

510
COPYING Normal file
Просмотреть файл

@ -0,0 +1,510 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

0
ChangeLog Normal file
Просмотреть файл

4
Makefile.am Normal file
Просмотреть файл

@ -0,0 +1,4 @@
SUBDIRS = src sample
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = daap-sharp.pc

0
NEWS Normal file
Просмотреть файл

2
README Normal file
Просмотреть файл

@ -0,0 +1,2 @@
daap-sharp is a DAAP (Digial Audio Access Protocol) implementation

85
autogen.sh Executable file
Просмотреть файл

@ -0,0 +1,85 @@
#! /bin/sh
# Ok, simple script to do this.
: ${AUTOCONF=autoconf}
: ${AUTOHEADER=autoheader}
: ${AUTOMAKE=automake}
: ${LIBTOOLIZE=libtoolize}
: ${ACLOCAL=aclocal}
: ${LIBTOOL=libtool}
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
PROJECT=daap-sharp
TEST_TYPE=-f
FILE=src/Client.cs
CONFIGURE=configure.in
aclocalinclude="-I . $ACLOCAL_FLAGS"
DIE=0
($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to compile $PROJECT."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $PROJECT."
echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
(grep "^AM_PROG_LIBTOOL" configure.in >/dev/null) && {
($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`libtool' installed to compile $PROJECT."
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
if test "$DIE" -eq 1; then
exit 1
fi
test $TEST_TYPE $FILE || {
echo "You must run this script in the top-level $PROJECT directory"
exit 1
}
if test -z "$*"; then
echo "I am going to run ./configure with no arguments - if you wish "
echo "to pass any to it, please specify them on the $0 command line."
fi
case $CC in
*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
esac
(grep "^AM_PROG_LIBTOOL" configure.in >/dev/null) && {
echo "Running $LIBTOOLIZE ..."
$LIBTOOLIZE --force --copy
}
echo "Running $ACLOCAL $aclocalinclude ..."
$ACLOCAL $aclocalinclude
echo "Running $AUTOMAKE --gnu $am_opt ..."
$AUTOMAKE --add-missing --gnu $am_opt
echo "Running $AUTOCONF ..."
$AUTOCONF
echo Running $srcdir/configure $conf_flags "$@" ...
$srcdir/configure --enable-maintainer-mode $conf_flags "$@" \

65
configure.in Normal file
Просмотреть файл

@ -0,0 +1,65 @@
AC_INIT(README)
AC_CANONICAL_SYSTEM
MAJOR_VERSION=0
MINOR_VERSION=1
MICRO_VERSION=0
VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION
AM_INIT_AUTOMAKE(daap-sharp, $VERSION)
AC_SUBST(MAJOR_VERSION)
AC_SUBST(MINOR_VERSION)
AC_SUBST(MICRO_VERSION)
AC_DEFINE_UNQUOTED(MAJOR_VERSION, $MAJOR_VERSION, [Major Version Number])
AC_DEFINE_UNQUOTED(MINOR_VERSION, $MINOR_VERSION, [Minor Version Number])
AC_DEFINE_UNQUOTED(MICRO_VERSION, $MICRO_VERSION, [Micro Version Number])
AM_MAINTAINER_MODE
dnl Mono
AC_PATH_PROG(MONO, mono)
if test "x$MONO" = "x" ; then
AC_MSG_ERROR([Can not find "mono" in your PATH])
fi
dnl mcs
AC_PATH_PROG(MCS, mcs)
if test "x$MCS" = "x" ; then
AC_MSG_ERROR([Can not find "mcs" in your PATH])
fi
PKG_CHECK_MODULES(AVAHI, avahi-sharp >= 0.5)
PKG_CHECK_MODULES(ENTAGGED, entagged-sharp, have_entagged=yes, have_entagged=no)
AM_CONDITIONAL(HAVE_ENTAGGED, test "x$have_entagged" = "xyes")
PKG_CHECK_MODULES(MONODOC, monodoc >= 1.1.9, have_monodoc=yes, have_monodoc=no)
if test "x$have_monodoc" = "xyes"; then
AC_PATH_PROG(MONODOCER, monodocer)
AC_PATH_PROG(MDASSEMBLER, mdassembler)
MONODOC_DIR=`$PKG_CONFIG --variable=sourcesdir monodoc`
AC_SUBST(MONODOC_DIR)
fi
AM_CONDITIONAL(HAVE_MONODOC, test "x$have_monodoc" = "xyes")
AC_PATH_PROG(GACUTIL, gacutil, no)
if test "x$GACUTIL" = "xno"; then
AC_MSG_ERROR([You need to install gacutil])
fi
AC_OUTPUT([
Makefile
daap-sharp.pc
src/Makefile
sample/Makefile
])
echo
echo "daap-sharp prefix: $prefix"
echo "build documentation: $have_monodoc"
echo

12
daap-sharp.pc.in Normal file
Просмотреть файл

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Libraries=@libdir@/daap-sharp/daap-sharp.dll
Name: daap-sharp
Description: daap-sharp
Version: @VERSION@
Requires:
Libs: -r:${Libraries}

32
sample/Makefile.am Normal file
Просмотреть файл

@ -0,0 +1,32 @@
all: $(ASSEMBLIES)
ASSEMBLIES = client.exe mirror.exe update-test.exe
CLIENTSOURCES = $(srcdir)/SampleClient.cs
SERVERSOURCES = $(srcdir)/SampleServer.cs
MIRRORSOURCES = $(srcdir)/Mirror.cs
UPDATETESTSOURCES = $(srcdir)/UpdateTest.cs
if HAVE_ENTAGGED
ASSEMBLIES += server.exe
endif
client.exe: $(CLIENTSOURCES) $(top_builddir)/src/daap-sharp.dll
$(MCS) -out:$@ $(CLIENTSOURCES) -r:$(top_builddir)/src/daap-sharp.dll
entagged-sharp.dll:
cp `pkg-config --variable=Libraries entagged-sharp` .
server.exe: $(SERVERSOURCES) $(top_builddir)/src/daap-sharp.dll entagged-sharp.dll
$(MCS) -out:$@ $(SERVERSOURCES) -r:$(top_builddir)/src/daap-sharp.dll -r:entagged-sharp.dll
mirror.exe: $(MIRRORSOURCES) $(top_builddir)/src/daap-sharp.dll
$(MCS) -out:$@ $(MIRRORSOURCES) -r:$(top_builddir)/src/daap-sharp.dll
update-test.exe: $(UPDATETESTSOURCES) $(top_builddir)/src/daap-sharp.dll
$(MCS) -out:$@ $(UPDATETESTSOURCES) -r:$(top_builddir)/src/daap-sharp.dll
EXTRA_DIST = $(CLIENTSOURCES) $(SERVERSOURCES) $(MIRRORSOURCES) $(UPDATETESTSOURCES)
CLEANFILES = $(ASSEMBLIES) entagged-sharp.dll

97
sample/Mirror.cs Normal file
Просмотреть файл

@ -0,0 +1,97 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections;
namespace DAAP.Tools {
public class Mirror {
private static Server server;
private static ArrayList clients = new ArrayList ();
public static void Main (string[] args) {
string name = "Foobar Mirror";
ushort port = 3690;
if (args.Length > 0)
name = args[0];
if (args.Length > 1)
port = UInt16.Parse (args[1]);
server = new Server (name);
server.Port = port;
server.Start ();
ServiceLocator locator = new ServiceLocator ();
locator.Found += OnServiceFound;
locator.Removed += OnServiceRemoved;
Console.WriteLine ("Press enter to quit");
Console.ReadLine ();
foreach (Client client in clients) {
client.Logout ();
}
}
private static void OnServiceFound (object o, Service service) {
if (service.Name == server.Name)
return;
Console.WriteLine ("Found: " + service.Name);
if (service.IsProtected) {
Console.WriteLine ("Password is required, skipping");
return;
}
Client client = new Client (service);
client.Login ();
client.Updated += OnClientUpdated;
foreach (Database db in client.Databases) {
server.AddDatabase (db);
Console.WriteLine ("Added database: " + db.Name);
}
server.Commit ();
clients.Add (client);
}
private static void OnServiceRemoved (object o, Service service) {
Console.WriteLine ("Removed: " + service.Name);
foreach (Client client in clients) {
if (client.Name == service.Name) {
foreach (Database db in client.Databases) {
server.RemoveDatabase (db);
}
clients.Remove (client);
break;
}
}
}
private static void OnClientUpdated (object o, EventArgs args) {
server.Commit ();
}
}
}

72
sample/SampleClient.cs Normal file
Просмотреть файл

@ -0,0 +1,72 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
namespace DAAP.Tools {
public class SampleClient {
public static int Main (string[] args) {
if (args.Length == 0 || args[0] == "--help") {
Console.WriteLine ("Usage: sample-client <host> [<song_id> <song_id> ...]");
return 1;
}
Client client = new Client (args[0], 3689);
client.Login ();
try {
Console.WriteLine ("Server: " + client.Name);
if (args.Length > 1) {
for (int i = 1; i < args.Length; i++) {
foreach (Database db in client.Databases) {
int id = Int32.Parse (args[i]);
Song song = db.LookupSongById (id);
if (song == null) {
Console.WriteLine ("WARNING: no song with id '{0}' was found.", id);
continue;
}
Console.WriteLine ("Downloading: " + song.Title);
db.DownloadSong (song,
String.Format ("./{0} - {1}.{2}", song.Artist, song.Title, song.Format));
}
}
} else {
foreach (Database db in client.Databases) {
Console.WriteLine ("Database: " + db.Name);
foreach (Song song in db.Songs)
Console.WriteLine (song);
}
}
} finally {
client.Logout ();
}
return 0;
}
}
}

89
sample/SampleServer.cs Normal file
Просмотреть файл

@ -0,0 +1,89 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.IO;
using DAAP;
using Entagged;
public class SampleServer
{
private static Server server;
public static void Main (string[] args) {
server = new Server ("snorp's Music");
server.Collision += OnCollision;
server.Port = 3689;
Database db = new Database ("Test Music");
foreach (string arg in args)
AddDirectory (db, arg);
Playlist pl = new Playlist ("foo playlist");
foreach (Song song in db.Songs) {
pl.AddSong (song);
}
db.AddPlaylist (pl);
Console.WriteLine ("Done adding files");
server.AddDatabase (db);
server.Commit ();
server.Start ();
Console.ReadLine ();
}
private static void OnCollision (object o, EventArgs args) {
server.Name = server.Name + " foo";
}
private static void AddDirectory (Database db, string dir) {
Console.WriteLine ("Adding files in: " + dir);
foreach (string file in Directory.GetFiles (dir)) {
AudioFileWrapper afw = null;
try {
afw = new AudioFileWrapper (file);
} catch (Exception e) {
continue;
}
Song song = new Song ();
song.Artist = afw.Artist;
song.Album = afw.Album;
song.Title = afw.Title;
song.Year = afw.Year;
song.Format = Path.GetExtension (file).Substring (1);
song.Duration = TimeSpan.FromSeconds (afw.Duration);
song.Genre = afw.Genre;
song.TrackNumber = afw.TrackNumber;
song.TrackCount = afw.TrackCount;
song.DateAdded = DateTime.Now;
song.DateModified = DateTime.Now;
song.FileName = file;
song.Size = (int) new FileInfo (song.FileName).Length;
db.AddSong (song);
}
foreach (string subdir in Directory.GetDirectories (dir)) {
AddDirectory (db, subdir);
}
}
}

133
sample/UpdateTest.cs Normal file
Просмотреть файл

@ -0,0 +1,133 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections;
namespace DAAP.Tools {
public class UpdateTest {
private static ArrayList clients = new ArrayList ();
public static void Main (string[] args) {
if (args.Length == 0) {
ServiceLocator locator = new ServiceLocator ();
locator.Found += OnServiceFound;
locator.Removed += OnServiceRemoved;
} else {
string host = args[0];
ushort port = 3689;
if (args.Length > 1)
port = UInt16.Parse (args[1]);
Client client = new Client (host, port);
client.Login ();
AddClient (client);
}
Console.WriteLine ("Press enter to quit");
Console.ReadLine ();
foreach (Client client in clients) {
client.Logout ();
}
}
private static void OnServiceFound (object o, Service service) {
Console.WriteLine ("Found: " + service.Name);
Client client = new Client (service);
client.Login ();
AddClient (client);
}
private static void AddClient (Client client) {
foreach (Database db in client.Databases) {
db.SongAdded += OnSongAdded;
db.SongRemoved += OnSongRemoved;
db.PlaylistAdded += OnPlaylistAdded;
db.PlaylistRemoved += OnPlaylistRemoved;
foreach (Playlist pl in db.Playlists) {
pl.SongAdded += OnPlaylistSongAdded;
pl.SongRemoved += OnPlaylistSongRemoved;
pl.NameChanged += OnPlaylistNameChanged;
}
foreach (Song song in db.Songs) {
song.Updated += OnSongUpdated;
}
Console.WriteLine ("Added database: " + db.Name);
}
clients.Add (client);
}
private static void OnServiceRemoved (object o, Service service) {
Console.WriteLine ("Removed: " + service.Name);
foreach (Client client in clients) {
if (client.Name == service.Name) {
clients.Remove (client);
break;
}
}
}
private static void OnSongUpdated (object o, EventArgs args) {
Console.WriteLine ("Song '{0}' was updated.", (o as Song).Title);
}
private static void OnSongAdded (object o, Song song) {
Console.WriteLine ("Song '{0}' added to '{1}'", song.Title, (o as Database).Name);
}
private static void OnSongRemoved (object o, Song song) {
Console.WriteLine ("Song '{0}' removed from '{1}'", song.Title, (o as Database).Name);
}
private static void OnPlaylistAdded (object o, Playlist pl) {
Console.WriteLine ("Playlist '{0}' added to '{1}'", pl.Name, (o as Database).Name);
pl.SongAdded += OnPlaylistSongAdded;
pl.SongRemoved += OnPlaylistSongRemoved;
}
private static void OnPlaylistRemoved (object o, Playlist pl) {
Console.WriteLine ("Playlist '{0}' removed from '{1}'", pl.Name, (o as Database).Name);
}
private static void OnPlaylistNameChanged (object o, EventArgs args) {
Console.WriteLine ("Playlist name changed to '{0}'", (o as Playlist).Name);
}
private static void OnPlaylistSongAdded (object o, int index, Song song) {
Console.WriteLine ("Song '{0}' added to '{1}' at {2}", song.Title, (o as Playlist).Name,
index);
}
private static void OnPlaylistSongRemoved (object o, int index, Song song) {
Console.WriteLine ("Song '{0}' removed from '{1}' at {2}", song.Title, (o as Playlist).Name,
index);
}
}
}

45
src/AssemblyInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,45 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("daap-sharp")]
[assembly: AssemblyDescription("daap-sharp")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCopyright("(C) 2005 James Willcox <snorp@snorp.net>")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0")]

519
src/BrokenMD5.cs Normal file
Просмотреть файл

@ -0,0 +1,519 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// BrokenMD5 Class implementation
//
// Authors:
// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
// Sebastien Pouliot (sebastien@ximian.com)
// Jon Lech Johansen (jon@nanocrew.net)
//
// Copyright 2001 by Matthew S. Ford.
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace DAAP {
internal class BrokenMD5 : MD5 {
private const int BLOCK_SIZE_BYTES = 64;
private const int HASH_SIZE_BYTES = 16;
private uint[] _H;
private uint[] buff;
private ulong count;
private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
private int _version;
public BrokenMD5 ( int version )
{
_H = new uint[4];
buff = new uint[16];
_ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
_version = version;
Initialize();
}
~BrokenMD5 ()
{
Dispose (false);
}
protected override void Dispose (bool disposing)
{
if (_ProcessingBuffer != null) {
Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
_ProcessingBuffer = null;
}
if (_H != null) {
Array.Clear (_H, 0, _H.Length);
_H = null;
}
if (buff != null) {
Array.Clear (buff, 0, buff.Length);
buff = null;
}
}
protected override void HashCore (byte[] rgb, int start, int size)
{
int i;
State = 1;
if (_ProcessingBufferCount != 0) {
if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
_ProcessingBufferCount += size;
return;
}
else {
i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
ProcessBlock (_ProcessingBuffer, 0);
_ProcessingBufferCount = 0;
start += i;
size -= i;
}
}
for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
ProcessBlock (rgb, start+i);
}
if (size%BLOCK_SIZE_BYTES != 0) {
System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
_ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
}
}
protected override byte[] HashFinal ()
{
byte[] hash = new byte[16];
int i, j;
ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
hash[i*4+j] = (byte)(_H[i] >> j*8);
}
}
return hash;
}
public override void Initialize ()
{
count = 0;
_ProcessingBufferCount = 0;
_H[0] = 0x67452301;
_H[1] = 0xefcdab89;
_H[2] = 0x98badcfe;
_H[3] = 0x10325476;
}
private void ProcessBlock (byte[] inputBuffer, int inputOffset)
{
uint a, b, c, d;
int i;
count += BLOCK_SIZE_BYTES;
for (i=0; i<16; i++) {
buff[i] = (uint)(inputBuffer[inputOffset+4*i])
| (((uint)(inputBuffer[inputOffset+4*i+1])) << 8)
| (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
| (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
}
a = _H[0];
b = _H[1];
c = _H[2];
d = _H[3];
// This function was unrolled because it seems to be doubling our performance with current compiler/VM.
// Possibly roll up if this changes.
// ---- Round 1 --------
a += (((c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
a = (a << 7) | (a >> 25);
a += b;
d += (((b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
d = (d << 12) | (d >> 20);
d += a;
c += (((a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
c = (c << 17) | (c >> 15);
c += d;
b += (((d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
b = (b << 22) | (b >> 10);
b += c;
a += (((c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
a = (a << 7) | (a >> 25);
a += b;
d += (((b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
d = (d << 12) | (d >> 20);
d += a;
c += (((a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
c = (c << 17) | (c >> 15);
c += d;
b += (((d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
b = (b << 22) | (b >> 10);
b += c;
a += (((c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
a = (a << 7) | (a >> 25);
a += b;
d += (((b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
d = (d << 12) | (d >> 20);
d += a;
c += (((a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
c = (c << 17) | (c >> 15);
c += d;
b += (((d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
b = (b << 22) | (b >> 10);
b += c;
a += (((c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
a = (a << 7) | (a >> 25);
a += b;
d += (((b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
d = (d << 12) | (d >> 20);
d += a;
c += (((a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
c = (c << 17) | (c >> 15);
c += d;
b += (((d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
b = (b << 22) | (b >> 10);
b += c;
// ---- Round 2 --------
a += (((b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
a = (a << 5) | (a >> 27);
a += b;
d += (((a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
d = (d << 9) | (d >> 23);
d += a;
c += (((d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
c = (c << 14) | (c >> 18);
c += d;
b += (((c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
b = (b << 20) | (b >> 12);
b += c;
a += (((b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
a = (a << 5) | (a >> 27);
a += b;
d += (((a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
d = (d << 9) | (d >> 23);
d += a;
c += (((d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
c = (c << 14) | (c >> 18);
c += d;
b += (((c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
b = (b << 20) | (b >> 12);
b += c;
a += (((b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
a = (a << 5) | (a >> 27);
a += b;
d += (((a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
d = (d << 9) | (d >> 23);
d += a;
c += (((d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
c = (c << 14) | (c >> 18);
c += d;
if( _version == 1 )
{
b += (((c ^ d) & a) ^ d) + (uint) 0x445a14ed + buff [8];
b = (b << 20) | (b >> 12);
b += c;
}
else
{
b += (((c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
b = (b << 20) | (b >> 12);
b += c;
}
a += (((b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
a = (a << 5) | (a >> 27);
a += b;
d += (((a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
d = (d << 9) | (d >> 23);
d += a;
c += (((d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
c = (c << 14) | (c >> 18);
c += d;
b += (((c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
b = (b << 20) | (b >> 12);
b += c;
// ---- Round 3 --------
a += (b ^ c ^ d) + (uint) K [32] + buff [5];
a = (a << 4) | (a >> 28);
a += b;
d += (a ^ b ^ c) + (uint) K [33] + buff [8];
d = (d << 11) | (d >> 21);
d += a;
c += (d ^ a ^ b) + (uint) K [34] + buff [11];
c = (c << 16) | (c >> 16);
c += d;
b += (c ^ d ^ a) + (uint) K [35] + buff [14];
b = (b << 23) | (b >> 9);
b += c;
a += (b ^ c ^ d) + (uint) K [36] + buff [1];
a = (a << 4) | (a >> 28);
a += b;
d += (a ^ b ^ c) + (uint) K [37] + buff [4];
d = (d << 11) | (d >> 21);
d += a;
c += (d ^ a ^ b) + (uint) K [38] + buff [7];
c = (c << 16) | (c >> 16);
c += d;
b += (c ^ d ^ a) + (uint) K [39] + buff [10];
b = (b << 23) | (b >> 9);
b += c;
a += (b ^ c ^ d) + (uint) K [40] + buff [13];
a = (a << 4) | (a >> 28);
a += b;
d += (a ^ b ^ c) + (uint) K [41] + buff [0];
d = (d << 11) | (d >> 21);
d += a;
c += (d ^ a ^ b) + (uint) K [42] + buff [3];
c = (c << 16) | (c >> 16);
c += d;
b += (c ^ d ^ a) + (uint) K [43] + buff [6];
b = (b << 23) | (b >> 9);
b += c;
a += (b ^ c ^ d) + (uint) K [44] + buff [9];
a = (a << 4) | (a >> 28);
a += b;
d += (a ^ b ^ c) + (uint) K [45] + buff [12];
d = (d << 11) | (d >> 21);
d += a;
c += (d ^ a ^ b) + (uint) K [46] + buff [15];
c = (c << 16) | (c >> 16);
c += d;
b += (c ^ d ^ a) + (uint) K [47] + buff [2];
b = (b << 23) | (b >> 9);
b += c;
// ---- Round 4 --------
a += (((~d) | b) ^ c) + (uint) K [48] + buff [0];
a = (a << 6) | (a >> 26);
a += b;
d += (((~c) | a) ^ b) + (uint) K [49] + buff [7];
d = (d << 10) | (d >> 22);
d += a;
c += (((~b) | d) ^ a) + (uint) K [50] + buff [14];
c = (c << 15) | (c >> 17);
c += d;
b += (((~a) | c) ^ d) + (uint) K [51] + buff [5];
b = (b << 21) | (b >> 11);
b += c;
a += (((~d) | b) ^ c) + (uint) K [52] + buff [12];
a = (a << 6) | (a >> 26);
a += b;
d += (((~c) | a) ^ b) + (uint) K [53] + buff [3];
d = (d << 10) | (d >> 22);
d += a;
c += (((~b) | d) ^ a) + (uint) K [54] + buff [10];
c = (c << 15) | (c >> 17);
c += d;
b += (((~a) | c) ^ d) + (uint) K [55] + buff [1];
b = (b << 21) | (b >> 11);
b += c;
a += (((~d) | b) ^ c) + (uint) K [56] + buff [8];
a = (a << 6) | (a >> 26);
a += b;
d += (((~c) | a) ^ b) + (uint) K [57] + buff [15];
d = (d << 10) | (d >> 22);
d += a;
c += (((~b) | d) ^ a) + (uint) K [58] + buff [6];
c = (c << 15) | (c >> 17);
c += d;
b += (((~a) | c) ^ d) + (uint) K [59] + buff [13];
b = (b << 21) | (b >> 11);
b += c;
a += (((~d) | b) ^ c) + (uint) K [60] + buff [4];
a = (a << 6) | (a >> 26);
a += b;
d += (((~c) | a) ^ b) + (uint) K [61] + buff [11];
d = (d << 10) | (d >> 22);
d += a;
c += (((~b) | d) ^ a) + (uint) K [62] + buff [2];
c = (c << 15) | (c >> 17);
c += d;
b += (((~a) | c) ^ d) + (uint) K [63] + buff [9];
b = (b << 21) | (b >> 11);
b += c;
_H [0] += a;
_H [1] += b;
_H [2] += c;
_H [3] += d;
}
private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
{
ulong total = count + (ulong)inputCount;
int paddingSize = (int)(56 - total % BLOCK_SIZE_BYTES);
if (paddingSize < 1)
paddingSize += BLOCK_SIZE_BYTES;
byte[] fooBuffer = new byte [inputCount+paddingSize+8];
for (int i=0; i<inputCount; i++) {
fooBuffer[i] = inputBuffer[i+inputOffset];
}
fooBuffer[inputCount] = 0x80;
for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
fooBuffer[i] = 0x00;
}
// I deal in bytes. The algorithm deals in bits.
ulong size = total << 3;
AddLength (size, fooBuffer, inputCount+paddingSize);
ProcessBlock (fooBuffer, 0);
if (inputCount+paddingSize+8 == 128) {
ProcessBlock(fooBuffer, 64);
}
}
internal void AddLength (ulong length, byte[] buffer, int position)
{
buffer [position++] = (byte)(length);
buffer [position++] = (byte)(length >> 8);
buffer [position++] = (byte)(length >> 16);
buffer [position++] = (byte)(length >> 24);
buffer [position++] = (byte)(length >> 32);
buffer [position++] = (byte)(length >> 40);
buffer [position++] = (byte)(length >> 48);
buffer [position] = (byte)(length >> 56);
}
private readonly static uint[] K = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
}
}

217
src/Client.cs Normal file
Просмотреть файл

@ -0,0 +1,217 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Web;
using System.Net;
using System.Text;
using System.Collections;
namespace DAAP {
public class Client : IDisposable {
private const int UpdateSleepInterval = 2 * 60 * 1000; // 2 minutes
private IPAddress address;
private UInt16 port;
private ContentCodeBag bag;
private ServerInfo serverInfo;
private ArrayList databases = new ArrayList ();
private ContentFetcher fetcher;
private int revision;
private bool updateRunning;
public event EventHandler Updated;
internal int Revision {
get { return revision; }
}
public string Name {
get { return serverInfo.Name; }
}
public IPAddress Address {
get { return address; }
}
public ushort Port {
get { return port; }
}
public AuthenticationMethod AuthenticationMethod {
get { return serverInfo.AuthenticationMethod; }
}
public Database[] Databases {
get { return (Database[]) databases.ToArray (typeof (Database)); }
}
internal ContentCodeBag Bag {
get { return bag; }
}
internal ContentFetcher Fetcher {
get { return fetcher; }
}
public Client (Service service) : this (service.Address, service.Port) {
}
public Client (string host, UInt16 port) : this (Dns.Resolve (host).AddressList[0], port) {
}
public Client (IPAddress address, UInt16 port) {
this.address = address;
this.port = port;
fetcher = new ContentFetcher (address, port);
ContentNode node = ContentParser.Parse (ContentCodeBag.Default, fetcher.Fetch ("/server-info"));
serverInfo = ServerInfo.FromNode (node);
}
~Client () {
Dispose ();
}
public void Dispose () {
updateRunning = false;
if (fetcher != null) {
fetcher.Dispose ();
fetcher = null;
}
}
private void ParseSessionId (ContentNode node) {
fetcher.SessionId = (int) node.GetChild ("dmap.sessionid").Value;
}
public void Login () {
Login (null, null);
}
public void Login (string password) {
Login (null, password);
}
public void Login (string username, string password) {
fetcher.Username = username;
fetcher.Password = password;
bag = ContentCodeBag.ParseCodes (fetcher.Fetch ("/content-codes"));
ContentNode node = ContentParser.Parse (bag, fetcher.Fetch ("/login"));
ParseSessionId (node);
FetchDatabases ();
Refresh ();
if (serverInfo.SupportsUpdate) {
updateRunning = true;
Thread thread = new Thread (UpdateLoop);
thread.IsBackground = true;
thread.Start ();
}
}
public void Logout () {
fetcher.Fetch ("/logout");
fetcher.SessionId = 0;
updateRunning = false;
}
private void FetchDatabases () {
ContentNode dbnode = ContentParser.Parse (bag, fetcher.Fetch ("/databases"));
foreach (ContentNode child in (ContentNode[]) dbnode.Value) {
if (child.Name != "dmap.listing")
continue;
foreach (ContentNode item in (ContentNode[]) child.Value) {
Database db = new Database (this, item);
databases.Add (db);
}
}
}
private int GetCurrentRevision () {
ContentNode revNode = ContentParser.Parse (bag, fetcher.Fetch ("/update"), "dmap.serverrevision");
return (int) revNode.Value;
}
private int WaitForRevision (int currentRevision) {
ContentNode revNode = ContentParser.Parse (bag, fetcher.Fetch ("/update",
"revision-number=" + currentRevision));
return (int) revNode.GetChild ("dmap.serverrevision").Value;
}
private void Refresh () {
int newrev = revision;
if (serverInfo.SupportsUpdate) {
if (revision == 0)
newrev = GetCurrentRevision ();
else
newrev = WaitForRevision (revision);
if (newrev == revision)
return;
}
// Console.WriteLine ("Got new revision: " + newrev);
foreach (Database db in databases) {
db.Refresh (newrev);
}
revision = newrev;
if (Updated != null)
Updated (this, new EventArgs ());
}
private void UpdateLoop () {
while (true) {
try {
if (!updateRunning)
break;
Refresh ();
} catch (WebException e) {
if (!updateRunning)
break;
// chill out for a while, maybe the server went down
// temporarily or something.
Thread.Sleep (UpdateSleepInterval);
} catch (Exception e) {
if (!updateRunning)
break;
Console.Error.WriteLine ("Exception in update loop: " + e);
Thread.Sleep (UpdateSleepInterval);
}
}
}
}
}

169
src/ContentCodeBag.cs Normal file
Просмотреть файл

@ -0,0 +1,169 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Text;
using System.Net;
namespace DAAP {
internal enum ContentType : short {
Char = 1,
SignedLong = 2,
Short = 3,
Long = 5,
LongLong = 7,
String = 9,
Date = 10,
Version = 11,
Container = 12
}
internal struct ContentCode {
public int Number;
public string Name;
public ContentType Type;
public static ContentCode Zero = new ContentCode ();
}
internal class ContentCodeBag {
private const int ChunkLength = 8192;
private static ContentCodeBag defaultBag;
private Hashtable codes = new Hashtable ();
public static ContentCodeBag Default {
get {
if (defaultBag == null) {
using (BinaryReader reader = new BinaryReader (Assembly.GetExecutingAssembly ().GetManifestResourceStream ("content-codes"))) {
MemoryStream buf = new MemoryStream ();
byte[] bytes = null;
do {
bytes = reader.ReadBytes (ChunkLength);
buf.Write (bytes, 0, bytes.Length);
} while (bytes.Length == ChunkLength);
defaultBag = ContentCodeBag.ParseCodes (buf.GetBuffer ());
}
}
return defaultBag;
}
}
private ContentCodeBag () {
}
public ContentCode Lookup (int number) {
if (codes.ContainsKey (number))
return (ContentCode) codes[number];
else
return ContentCode.Zero;
}
public ContentCode Lookup (string name) {
foreach (ContentCode code in codes.Values) {
if (code.Name == name)
return code;
}
return ContentCode.Zero;
}
private static int GetIntFormat (string code) {
return IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (Encoding.ASCII.GetBytes (code), 0));
}
private void AddCode (string num, string name, ContentType type) {
ContentCode code = new ContentCode ();
code.Number = GetIntFormat (num);
code.Name = name;
code.Type = type;
codes[code.Number] = code;
}
internal ContentNode ToNode () {
ArrayList nodes = new ArrayList ();
foreach (int number in codes.Keys) {
ContentCode code = (ContentCode) codes[number];
ArrayList contents = new ArrayList ();
contents.Add (new ContentNode ("dmap.contentcodesnumber", code.Number));
contents.Add (new ContentNode ("dmap.contentcodesname", code.Name));
contents.Add (new ContentNode ("dmap.contentcodestype", code.Type));
ContentNode dict = new ContentNode ("dmap.dictionary", contents);
nodes.Add (dict);
}
ContentNode status = new ContentNode ("dmap.status", 200);
return new ContentNode ("dmap.contentcodesresponse", status, nodes);
}
public static ContentCodeBag ParseCodes (byte[] buffer) {
ContentCodeBag bag = new ContentCodeBag ();
// add some codes to bootstrap us
bag.AddCode ("mccr", "dmap.contentcodesresponse", ContentType.Container);
bag.AddCode ("mdcl", "dmap.dictionary", ContentType.Container);
bag.AddCode ("mcnm", "dmap.contentcodesnumber", ContentType.Long);
bag.AddCode ("mcna", "dmap.contentcodesname", ContentType.String);
bag.AddCode ("mcty", "dmap.contentcodestype", ContentType.Short);
bag.AddCode ("mstt", "dmap.status", ContentType.Long);
ContentNode node = ContentParser.Parse (bag, buffer);
foreach (ContentNode dictNode in (node.Value as ContentNode[])) {
if (dictNode.Name != "dmap.dictionary") {
continue;
}
ContentCode code = new ContentCode ();
foreach (ContentNode item in (dictNode.Value as ContentNode[])) {
switch (item.Name) {
case "dmap.contentcodesnumber":
code.Number = (int) item.Value;
break;
case "dmap.contentcodesname":
code.Name = (string) item.Value;
break;
case "dmap.contentcodestype":
code.Type = (ContentType) Enum.ToObject (typeof (ContentType), (short) item.Value);
break;
}
}
bag.codes[code.Number] = code;
}
return bag;
}
}
}

166
src/ContentFetcher.cs Normal file
Просмотреть файл

@ -0,0 +1,166 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections;
using System.IO;
using System.Web;
using System.Text;
using System.Net;
using System.Runtime.InteropServices;
namespace DAAP {
internal class ContentFetcher : IDisposable {
private IPAddress address;
private UInt16 port;
private int sessionId;
private int requestId = 10;
private ArrayList responses = new ArrayList ();
private DAAPCredentials creds = new DAAPCredentials ();
public string Username {
get { return creds.Username; }
set { creds.Username = value; }
}
public string Password {
get { return creds.Password; }
set { creds.Password = value; }
}
public int SessionId {
get { return sessionId; }
set { sessionId = value; }
}
public ContentFetcher (IPAddress address, UInt16 port) {
this.address = address;
this.port = port;
}
~ContentFetcher () {
Dispose ();
}
public void Dispose () {
try {
foreach (HttpWebResponse response in (ArrayList) responses.Clone ()) {
responses.Remove (response);
response.Close ();
}
} catch {}
}
public byte[] Fetch (string path) {
return Fetch (path, null, null, 0);
}
public byte[] Fetch (string path, string query) {
return Fetch (path, query, null, 0);
}
public byte[] Fetch (string path, string query, WebHeaderCollection extraHeaders,
int requestId) {
HttpWebResponse response = FetchResponse (path, query, extraHeaders, requestId, false);
responses.Add (response);
BinaryReader reader = new BinaryReader (response.GetResponseStream ());
try {
if (response.ContentLength < 0)
return null;
return reader.ReadBytes ((int) response.ContentLength);
} finally {
reader.Close ();
responses.Remove (response);
}
}
public HttpWebResponse FetchResponse (string path, string query, WebHeaderCollection headers) {
return FetchResponse (path, query, headers, ++requestId, false);
}
public HttpWebResponse FetchFile (string path) {
return FetchResponse (path, null, null, ++requestId, true);
}
public HttpWebResponse FetchResponse (string path, string query,
WebHeaderCollection extraHeaders,
int requestId, bool disableKeepalive) {
UriBuilder builder = new UriBuilder ("http", address.ToString ());
builder.Port = port;
builder.Path = path;
if (sessionId != 0)
query = String.Format ("session-id={0}&", sessionId) + query;
if (query != null)
builder.Query += query;
HttpWebRequest request = (HttpWebRequest) WebRequest.Create (builder.Uri);
request.Timeout = System.Threading.Timeout.Infinite;
if (extraHeaders != null)
request.Headers = extraHeaders;
request.Accept = "*/*";
if (disableKeepalive)
request.KeepAlive = false;
string hash = Hasher.GenerateHash (3, builder.Uri.PathAndQuery, 2, requestId);
request.UserAgent = "iTunes/4.6 (Windows; N)";
request.Headers.Set ("Client-DAAP-Version", "3.0");
request.Headers.Set ("Client-DAAP-Validation", hash);
request.Headers.Set ("Client-DAAP-Access-Index", "2");
if (requestId >= 0)
request.Headers.Set ("Client-DAAP-Request-ID", requestId.ToString ());
request.Credentials = creds;
request.PreAuthenticate = true;
return (HttpWebResponse) request.GetResponse ();
}
private class DAAPCredentials : ICredentials {
private string username;
private string password;
public string Username {
get { return username; }
set { username = value; }
}
public string Password {
get { return password; }
set { password = value; }
}
public NetworkCredential GetCredential (Uri uri, string type) {
return new NetworkCredential (username, password);
}
}
}
}

182
src/ContentParser.cs Normal file
Просмотреть файл

@ -0,0 +1,182 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Text;
using System.Net;
using System.Collections;
using Mono.Unix;
namespace DAAP {
public class ContentException : ApplicationException {
public ContentException (string msg) : base (msg) {
}
}
internal class ContentNode {
public string Name;
public object Value;
public ContentNode () {
}
public ContentNode (string name, params object[] values) {
this.Name = name;
ArrayList vals = new ArrayList ();
foreach (object v in values) {
if (v is ICollection) {
vals.AddRange ((ICollection) v);
} else {
vals.Add (v);
}
}
if (vals.Count == 1 && vals[0].GetType () != typeof (ContentNode))
this.Value = vals[0];
else
this.Value = (object) vals.ToArray (typeof (ContentNode));
}
public void Dump () {
Dump (0);
}
private void Dump (int level) {
Console.WriteLine ("{0}Name: {1}", String.Empty.PadRight (level * 4), Name);
if (Value is ContentNode[]) {
foreach (ContentNode child in (Value as ContentNode[])) {
child.Dump (level + 1);
}
} else {
Console.WriteLine ("{0}Value ({1}): {2}", String.Empty.PadRight (level * 4),
Value.GetType (), Value);
Console.WriteLine ();
}
}
public ContentNode GetChild (string name) {
if (name == this.Name)
return this;
ContentNode[] children = Value as ContentNode[];
if (children == null)
return null;
foreach (ContentNode child in children) {
ContentNode needle = child.GetChild (name);
if (needle != null)
return needle;
}
return null;
}
}
internal class ContentParser {
private static ContentNode[] ParseChildren (ContentCodeBag bag, byte[] buffer,
int offset, int length) {
ArrayList children = new ArrayList ();
int position = offset;
while (position < offset + length) {
children.Add (Parse (bag, buffer, null, ref position));
}
return (ContentNode[]) children.ToArray (typeof (ContentNode));
}
public static ContentNode Parse (ContentCodeBag bag, byte[] buffer, string root,
ref int offset) {
ContentNode node = new ContentNode ();
int num = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset));
ContentCode code = bag.Lookup (num);
if (code.Equals (ContentCode.Zero)) {
throw new ContentException ("Failed to find content code for: " + num);
}
int length = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset + 4));
node.Name = code.Name;
switch (code.Type) {
case ContentType.Char:
node.Value = (byte) buffer[offset + 8];
break;
case ContentType.Short:
node.Value = IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (buffer, offset + 8));
break;
case ContentType.SignedLong:
case ContentType.Long:
node.Value = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset + 8));
break;
case ContentType.LongLong:
node.Value = IPAddress.NetworkToHostOrder (BitConverter.ToInt64 (buffer, offset + 8));
break;
case ContentType.String:
node.Value = Encoding.UTF8.GetString (buffer, offset + 8, length);
break;
case ContentType.Date:
node.Value = UnixConvert.ToDateTime (IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset + 8)));
break;
case ContentType.Version:
int major = IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (buffer, offset + 8));
int minor = (int) buffer[offset + 10];
int micro = (int) buffer[offset + 11];
node.Value = new Version (major, minor, micro);
break;
case ContentType.Container:
node.Value = ParseChildren (bag, buffer, offset + 8, length);
break;
default:
throw new ContentException (String.Format ("Unknown content type '{0}' for '{1}'",
code.Type, code.Name));
}
offset += length + 8;
if (root != null) {
ContentNode rootNode = node.GetChild (root);
if (rootNode == null)
throw new ContentException (String.Format ("Could not find root node '{0}'", root));
return rootNode;
} else {
return node;
}
}
public static ContentNode Parse (ContentCodeBag bag, byte[] buffer, string root) {
int offset = 0;
return Parse (bag, buffer, root, ref offset);
}
public static ContentNode Parse (ContentCodeBag bag, byte[] buffer) {
return Parse (bag, buffer, null);
}
}
}

111
src/ContentWriter.cs Normal file
Просмотреть файл

@ -0,0 +1,111 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Text;
using System.Net;
using System.IO;
using Mono.Unix;
namespace DAAP {
internal class ContentWriter {
private static void Write (ContentCodeBag bag, ContentNode node, BinaryWriter writer) {
ContentCode code = bag.Lookup (node.Name);
if (code.Equals (ContentCode.Zero)) {
throw new ContentException ("Failed to get content code for: " + node.Name);
}
writer.Write (IPAddress.HostToNetworkOrder (code.Number));
switch (code.Type) {
case ContentType.Char:
writer.Write (IPAddress.HostToNetworkOrder (1));
writer.Write ((byte) node.Value);
break;
case ContentType.Short:
writer.Write (IPAddress.HostToNetworkOrder (2));
writer.Write (IPAddress.HostToNetworkOrder ((short) node.Value));
break;
case ContentType.SignedLong:
case ContentType.Long:
writer.Write (IPAddress.HostToNetworkOrder (4));
writer.Write (IPAddress.HostToNetworkOrder ((int) node.Value));
break;
case ContentType.LongLong:
writer.Write (IPAddress.HostToNetworkOrder (8));
writer.Write (IPAddress.HostToNetworkOrder ((long) node.Value));
break;
case ContentType.String:
byte[] data = Encoding.UTF8.GetBytes ((string) node.Value);
writer.Write (IPAddress.HostToNetworkOrder (data.Length));
writer.Write (data);
break;
case ContentType.Date:
writer.Write (IPAddress.HostToNetworkOrder (4));
writer.Write (IPAddress.HostToNetworkOrder ((int) UnixConvert.FromDateTime ((DateTime) node.Value)));
break;
case ContentType.Version:
Version version = (Version) node.Value;
writer.Write (IPAddress.HostToNetworkOrder (4));
writer.Write ((short) IPAddress.HostToNetworkOrder ((short) version.Major));
writer.Write ((byte) version.Minor);
writer.Write ((byte) version.Build);
break;
case ContentType.Container:
MemoryStream childStream = new MemoryStream ();
BinaryWriter childWriter = new BinaryWriter (childStream);
foreach (ContentNode child in (ContentNode[]) node.Value) {
Write (bag, child, childWriter);
}
childWriter.Flush ();
byte[] bytes = childStream.GetBuffer ();
int len = (int) childStream.Length;
writer.Write (IPAddress.HostToNetworkOrder (len));
writer.Write (bytes, 0, len);
childWriter.Close ();
break;
default:
Console.Error.WriteLine ("Cannot write node of type: " + code.Type);
break;
}
}
public static byte[] Write (ContentCodeBag bag, ContentNode node) {
MemoryStream stream = new MemoryStream ();
BinaryWriter writer = new BinaryWriter (stream);
Write (bag, node, writer);
writer.Flush ();
byte[] buf = stream.GetBuffer ();
long len = stream.Length;
writer.Close ();
byte[] ret = new byte[len];
Array.Copy (buf, ret, len);
return ret;
}
}
}

445
src/Database.cs Normal file
Просмотреть файл

@ -0,0 +1,445 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Net;
using System.IO;
using System.Collections;
using System.Threading;
namespace DAAP {
public delegate void SongHandler (object o, Song song);
public delegate void PlaylistHandler (object o, Playlist pl);
public class Database : ICloneable {
private const int ChunkLength = 8192;
private const string SongQuery = "meta=dmap.itemid,dmap.itemname,dmap.itemkind,dmap.persistentid," +
"daap.songalbum,daap.songgrouping,daap.songartist,daap.songbitrate," +
"daap.songbeatsperminute,daap.songcomment,daap.songcodectype," +
"daap.songcodecsubtype,daap.songcompilation,daap.songcomposer," +
"daap.songdateadded,daap.songdatemodified,daap.songdisccount," +
"daap.songdiscnumber,daap.songdisabled,daap.songeqpreset," +
"daap.songformat,daap.songgenre,daap.songdescription," +
"daap.songsamplerate,daap.songsize,daap.songstarttime," +
"daap.songstoptime,daap.songtime,daap.songtrackcount," +
"daap.songtracknumber,daap.songuserrating,daap.songyear," +
"daap.songdatakind,daap.songdataurl,com.apple.itunes.norm-volume," +
"com.apple.itunes.itms-songid,com.apple.itunes.itms-artistid," +
"com.apple.itunes.itms-playlistid,com.apple.itunes.itms-composerid," +
"com.apple.itunes.itms-genreid";
private static int nextid = 0;
private Client client;
private int id;
private long persistentId;
private string name;
private ArrayList songs = new ArrayList ();
private ArrayList playlists = new ArrayList ();
private Playlist basePlaylist = new Playlist ();
public event SongHandler SongAdded;
public event SongHandler SongRemoved;
public event PlaylistHandler PlaylistAdded;
public event PlaylistHandler PlaylistRemoved;
public int Id {
get { return id; }
}
public string Name {
get { return name; }
set {
name = value;
basePlaylist.Name = value;
}
}
public Song[] Songs {
get { return (Song[]) songs.ToArray (typeof (Song)); }
}
public Playlist[] Playlists {
get { return (Playlist[]) playlists.ToArray (typeof (Playlist)); }
}
internal Client Client {
get { return client; }
}
private Database () {
basePlaylist.Id = 0;
this.id = nextid++;
}
public Database (string name) : this () {
this.Name = name;
}
internal Database (Client client, ContentNode dbNode) : this () {
this.client = client;
Parse (dbNode);
}
private void Parse (ContentNode dbNode) {
foreach (ContentNode item in (ContentNode[]) dbNode.Value) {
switch (item.Name) {
case "dmap.itemid":
id = (int) item.Value;
break;
case "dmap.persistentid":
persistentId = (long) item.Value;
break;
case "dmap.itemname":
name = (string) item.Value;
break;
default:
break;
}
}
}
public Song LookupSongById (int id) {
foreach (Song song in songs) {
if (song.Id == id)
return song;
}
return null;
}
public Playlist LookupPlaylistById (int id) {
if (id == 0)
return basePlaylist;
foreach (Playlist pl in playlists) {
if (pl.Id == id)
return pl;
}
return null;
}
internal ContentNode ToSongsNode (string[] fields, int[] deletedIds) {
ArrayList songNodes = new ArrayList ();
foreach (Song song in songs) {
songNodes.Add (song.ToNode (fields));
}
ArrayList deletedNodes = null;
if (deletedIds.Length > 0) {
deletedNodes = new ArrayList ();
foreach (int id in deletedIds) {
deletedNodes.Add (new ContentNode ("dmap.itemid", id));
}
}
ArrayList children = new ArrayList ();
children.Add (new ContentNode ("dmap.status", 200));
children.Add (new ContentNode ("dmap.updatetype", deletedNodes == null ? (byte) 0 : (byte) 1));
children.Add (new ContentNode ("dmap.specifiedtotalcount", songs.Count));
children.Add (new ContentNode ("dmap.returnedcount", songs.Count));
children.Add (new ContentNode ("dmap.listing", songNodes));
if (deletedNodes != null) {
children.Add (new ContentNode ("dmap.deletedidlisting", deletedNodes));
}
return new ContentNode ("daap.databasesongs", children);
}
internal ContentNode ToPlaylistsNode () {
ArrayList nodes = new ArrayList ();
nodes.Add (basePlaylist.ToNode (true));
foreach (Playlist pl in playlists) {
nodes.Add (pl.ToNode (false));
}
return new ContentNode ("daap.databaseplaylists",
new ContentNode ("dmap.status", 200),
new ContentNode ("dmap.updatetype", (byte) 0),
new ContentNode ("dmap.specifiedtotalcount", playlists.Count),
new ContentNode ("dmap.returnedcount", playlists.Count),
new ContentNode ("dmap.listing", nodes));
}
internal ContentNode ToDatabaseNode () {
return new ContentNode ("dmap.listingitem",
new ContentNode ("dmap.itemid", id),
new ContentNode ("dmap.itemname", name),
new ContentNode ("dmap.itemcount", songs.Count),
new ContentNode ("dmap.containercount", playlists.Count + 1));
}
public void Clear () {
if (client != null)
throw new InvalidOperationException ("cannot clear client databases");
ClearPlaylists ();
ClearSongs ();
}
private void ClearPlaylists () {
foreach (Playlist pl in (ArrayList) playlists.Clone ()) {
RemovePlaylist (pl);
}
}
private void ClearSongs () {
foreach (Song song in (ArrayList) songs.Clone ()) {
RemoveSong (song);
}
}
private bool IsUpdateResponse (ContentNode node) {
return node.Name == "dmap.updateresponse";
}
private void RefreshPlaylists (string revquery) {
byte[] playlistsData = client.Fetcher.Fetch (String.Format ("/databases/{0}/containers", id, revquery));
ContentNode playlistsNode = ContentParser.Parse (client.Bag, playlistsData);
if (IsUpdateResponse (playlistsNode))
return;
// handle playlist additions/changes
ArrayList plids = new ArrayList ();
foreach (ContentNode playlistNode in (ContentNode[]) playlistsNode.GetChild ("dmap.listing").Value) {
Playlist pl = Playlist.FromNode (playlistNode);
if (pl != null) {
plids.Add (pl.Id);
Playlist existing = LookupPlaylistById (pl.Id);
if (existing == null) {
AddPlaylist (pl);
} else {
existing.Update (pl);
}
}
}
// delete playlists that no longer exist
foreach (Playlist pl in (ArrayList) playlists.Clone ()) {
if (!plids.Contains (pl.Id)) {
RemovePlaylist (pl);
}
}
plids = null;
// add/remove songs in the playlists
foreach (Playlist pl in playlists) {
byte[] playlistSongsData = client.Fetcher.Fetch (String.Format ("/databases/{0}/containers/{1}/items",
id, pl.Id), revquery);
ContentNode playlistSongsNode = ContentParser.Parse (client.Bag, playlistSongsData);
if (IsUpdateResponse (playlistSongsNode))
return;
if ((byte) playlistSongsNode.GetChild ("dmap.updatetype").Value == 1) {
// handle playlist song deletions
ContentNode deleteList = playlistSongsNode.GetChild ("dmap.deletedidlisting");
if (deleteList != null) {
foreach (ContentNode deleted in (ContentNode[]) deleteList.Value) {
int index = pl.LookupIndexByContainerId ((int) deleted.Value);
if (index < 0)
continue;
pl.RemoveAt (index);
}
}
}
// add new songs, or reorder existing ones
int plindex = 0;
foreach (ContentNode plSongNode in (ContentNode[]) playlistSongsNode.GetChild ("dmap.listing").Value) {
Song plsong = null;
int containerId = 0;
Song.FromPlaylistNode (this, plSongNode, out plsong, out containerId);
if (pl[plindex] != null && pl.GetContainerId (plindex) != containerId) {
pl.RemoveAt (plindex);
pl.InsertSong (plindex, plsong, containerId);
} else if (pl[plindex] == null) {
pl.InsertSong (plindex, plsong, containerId);
}
plindex++;
}
}
}
private void RefreshSongs (string revquery) {
byte[] songsData = client.Fetcher.Fetch (String.Format ("/databases/{0}/items", id),
SongQuery + "&" + revquery);
ContentNode songsNode = ContentParser.Parse (client.Bag, songsData);
if (IsUpdateResponse (songsNode))
return;
// handle song additions/changes
foreach (ContentNode songNode in (ContentNode[]) songsNode.GetChild ("dmap.listing").Value) {
Song song = Song.FromNode (songNode);
Song existing = LookupSongById (song.Id);
if (existing == null)
AddSong (song);
else
existing.Update (song);
}
if ((byte) songsNode.GetChild ("dmap.updatetype").Value == 1) {
// handle song deletions
ContentNode deleteList = songsNode.GetChild ("dmap.deletedidlisting");
if (deleteList != null) {
foreach (ContentNode deleted in (ContentNode[]) deleteList.Value) {
Song song = LookupSongById ((int) deleted.Value);
if (song != null)
RemoveSong (song);
}
}
}
}
internal void Refresh (int newrev) {
if (client == null)
throw new InvalidOperationException ("cannot refresh server databases");
string revquery = null;
if (client.Revision != 0)
revquery = String.Format ("revision-number={0}&delta={1}", newrev, newrev - client.Revision);
RefreshSongs (revquery);
RefreshPlaylists (revquery);
}
private HttpWebResponse FetchSong (Song song) {
return client.Fetcher.FetchFile (String.Format ("/databases/{0}/items/{1}.{2}", id, song.Id, song.Format));
}
public Stream StreamSong (Song song, out long length) {
HttpWebResponse response = FetchSong (song);
length = response.ContentLength;
return response.GetResponseStream ();
}
public void DownloadSong (Song song, string dest) {
HttpWebResponse response = FetchSong (song);
using (BinaryWriter writer = new BinaryWriter (File.Open (dest, FileMode.Create))) {
using (BinaryReader reader = new BinaryReader (response.GetResponseStream ())) {
int count = 0;
while (count < response.ContentLength) {
byte[] buf = reader.ReadBytes ((int) Math.Min (ChunkLength,
response.ContentLength - ChunkLength));
writer.Write (buf);
count += buf.Length;
}
}
}
}
public void AddSong (Song song) {
if (song.Id == 0)
song.SetId (songs.Count + 1);
songs.Add (song);
basePlaylist.AddSong (song);
if (SongAdded != null)
SongAdded (this, song);
}
public void RemoveSong (Song song) {
songs.Remove (song);
basePlaylist.RemoveSong (song);
if (SongRemoved != null)
SongRemoved (this, song);
}
public void AddPlaylist (Playlist pl) {
playlists.Add (pl);
if (PlaylistAdded != null)
PlaylistAdded (this, pl);
}
public void RemovePlaylist (Playlist pl) {
playlists.Remove (pl);
if (PlaylistRemoved != null)
PlaylistRemoved (this, pl);
}
private Playlist ClonePlaylist (Database db, Playlist pl) {
Playlist clonePl = new Playlist (pl.Name);
clonePl.SetId (pl.Id);
Song[] plsongs = pl.Songs;
for (int i = 0; i < plsongs.Length; i++) {
clonePl.AddSong (db.LookupSongById (plsongs[i].Id), pl.GetContainerId (i));
}
return clonePl;
}
public object Clone () {
Database db = new Database (this.name);
db.id = id;
db.persistentId = persistentId;
ArrayList cloneSongs = new ArrayList ();
foreach (Song song in songs) {
cloneSongs.Add (song.Clone ());
}
db.songs = cloneSongs;
ArrayList clonePlaylists = new ArrayList ();
foreach (Playlist pl in playlists) {
clonePlaylists.Add (ClonePlaylist (db, pl));
}
db.playlists = clonePlaylists;
db.basePlaylist = ClonePlaylist (db, basePlaylist);
return db;
}
}
}

219
src/Hasher.cs Normal file
Просмотреть файл

@ -0,0 +1,219 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Copyright (C) 2004 David Hammerton <david@crazney.net>
* Copyright (C) 2005 Jon Lech Johansen <jon@nanocrew.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Text;
namespace DAAP {
internal class Hasher
{
private static byte [] _hasht42 = null;
private static byte [] _hasht45 = null;
private static byte [] _hexchars =
Encoding.ASCII.GetBytes( "0123456789ABCDEF" );
private static byte [] _copyright = Convert.FromBase64String(
"Q29weXJpZ2h0IDIwMDMgQXBwbGUgQ29tcHV0ZXIsIEluYy4=" );
private static void HashToString( byte [] hash, byte [] str, int offset )
{
for( int i = 0; i < hash.Length; i++ )
{
byte tmp = hash[ i ];
str[ i * 2 + 1 + offset ] = _hexchars[ tmp & 0xF ];
str[ i * 2 + 0 + offset ] = _hexchars[ (tmp >> 4) & 0xF ];
}
}
private static void TransformString( BrokenMD5 md5, string str, bool final )
{
byte [] tmp = Encoding.ASCII.GetBytes( str );
if( final )
md5.TransformFinalBlock( tmp, 0, tmp.Length );
else
md5.TransformBlock( tmp, 0, tmp.Length, tmp, 0 );
}
private static void GenerateTable42()
{
int i;
_hasht42 = new byte[ 256 * 32 ];
for( i = 0; i < 256; i++ )
{
BrokenMD5 md5 = new BrokenMD5( 0 );
if( ( i & 0x80 ) != 0 )
TransformString( md5, "Accept-Language", false );
else
TransformString( md5, "user-agent", false );
if( ( i & 0x40 ) != 0 )
TransformString( md5, "max-age", false );
else
TransformString( md5, "Authorization", false );
if( ( i & 0x20 ) != 0 )
TransformString( md5, "Client-DAAP-Version", false );
else
TransformString( md5, "Accept-Encoding", false );
if( ( i & 0x10 ) != 0 )
TransformString( md5, "daap.protocolversion", false );
else
TransformString( md5, "daap.songartist", false );
if( ( i & 0x08 ) != 0 )
TransformString( md5, "daap.songcomposer", false );
else
TransformString( md5, "daap.songdatemodified", false );
if( ( i & 0x04 ) != 0 )
TransformString( md5, "daap.songdiscnumber", false );
else
TransformString( md5, "daap.songdisabled", false );
if( ( i & 0x02 ) != 0 )
TransformString( md5, "playlist-item-spec", false );
else
TransformString( md5, "revision-number", false );
if( ( i & 0x01 ) != 0 )
TransformString( md5, "session-id", true );
else
TransformString( md5, "content-codes", true );
HashToString( md5.Hash, _hasht42, i * 32 );
}
}
private static void GenerateTable45()
{
int i;
_hasht45 = new byte[ 256 * 32 ];
for( i = 0; i < 256; i++ )
{
BrokenMD5 md5 = new BrokenMD5( 1 );
if( ( i & 0x40 ) != 0 )
TransformString( md5, "eqwsdxcqwesdc", false );
else
TransformString( md5, "op[;lm,piojkmn", false );
if( ( i & 0x20 ) != 0 )
TransformString( md5, "876trfvb 34rtgbvc", false );
else
TransformString( md5, "=-0ol.,m3ewrdfv", false );
if( ( i & 0x10 ) != 0 )
TransformString( md5, "87654323e4rgbv ", false );
else
TransformString( md5, "1535753690868867974342659792", false );
if( ( i & 0x08 ) != 0 )
TransformString( md5, "Song Name", false );
else
TransformString( md5, "DAAP-CLIENT-ID:", false );
if( ( i & 0x04 ) != 0 )
TransformString( md5, "111222333444555", false );
else
TransformString( md5, "4089961010", false );
if( ( i & 0x02 ) != 0 )
TransformString( md5, "playlist-item-spec", false );
else
TransformString( md5, "revision-number", false );
if( ( i & 0x01 ) != 0 )
TransformString( md5, "session-id", false );
else
TransformString( md5, "content-codes", false );
if( ( i & 0x80 ) != 0 )
TransformString( md5, "IUYHGFDCXWEDFGHN", true );
else
TransformString( md5, "iuytgfdxwerfghjm", true );
HashToString( md5.Hash, _hasht45, i * 32 );
}
}
public static string GenerateHash(int version_major, string url,
int hash_select, int request_id )
{
if( _hasht42 == null )
GenerateTable42();
if( _hasht45 == null )
GenerateTable45();
byte [] hashtable = (version_major == 3) ? _hasht45 : _hasht42;
BrokenMD5 md5 = new BrokenMD5( (version_major == 3) ? 1 : 0 );
byte [] hash = new byte[ 32 ];
byte [] tmp = Encoding.ASCII.GetBytes( url );
md5.TransformBlock( tmp, 0, tmp.Length, tmp, 0 );
md5.TransformBlock( _copyright, 0, _copyright.Length, _copyright, 0 );
if( request_id > 0 && version_major == 3 )
{
md5.TransformBlock( hashtable, hash_select * 32, 32,
hashtable, hash_select * 32 );
tmp = Encoding.ASCII.GetBytes( request_id.ToString() );
md5.TransformFinalBlock( tmp, 0, tmp.Length );
}
else
{
md5.TransformFinalBlock( hashtable, hash_select * 32, 32 );
}
HashToString( md5.Hash, hash, 0 );
return Encoding.ASCII.GetString( hash );
}
}
}

51
src/Makefile.am Normal file
Просмотреть файл

@ -0,0 +1,51 @@
DAAP_ASSEMBLY = daap-sharp.dll
ASSEMBLIES = $(DAAP_ASSEMBLY)
daapdir = $(libdir)/daap-sharp
daap_DATA = $(ASSEMBLIES)
DAAPSOURCES = \
$(srcdir)/BrokenMD5.cs \
$(srcdir)/ContentParser.cs \
$(srcdir)/ContentCodeBag.cs \
$(srcdir)/ContentFetcher.cs \
$(srcdir)/ContentWriter.cs \
$(srcdir)/Client.cs \
$(srcdir)/Database.cs \
$(srcdir)/Hasher.cs \
$(srcdir)/Playlist.cs \
$(srcdir)/Server.cs \
$(srcdir)/ServerInfo.cs \
$(srcdir)/ServerLocator.cs \
$(srcdir)/Song.cs
if HAVE_MONODOC
docdir = $(MONODOC_DIR)
doc_DATA = daap-sharp-docs.zip daap-sharp-docs.tree daap-sharp-docs.source
endif
docs2html:
monodocs2html -source:en -dest:html
update-docs: $(DAAP_ASSEMBLY)
$(MONODOCER) -assembly:$(DAAP_ASSEMBLY) -path:en
daap-sharp-docs.zip: $(srcdir)/en/*/*
$(MDASSEMBLER) --out daap-sharp-docs --ecma $(srcdir)/en
all: $(ASSEMBLIES)
$(DAAP_ASSEMBLY): $(DAAPSOURCES)
$(MCS) $(MCS_FLAGS) -keyfile:$(srcdir)/daap-sharp.snk -target:library -out:$@ $(DAAPSOURCES) -resource:$(srcdir)/content-codes,content-codes -r:Mono.Posix -pkg:avahi-sharp -r:System.Web
EXTRA_DIST = \
$(DAAPSOURCES) \
daap-sharp.snk \
content-codes \
daap-sharp-docs.source \
$(srcdir)/en/*.xml \
$(srcdir)/en/*/*.xml
CLEANFILES = $(ASSEMBLIES)

214
src/Playlist.cs Normal file
Просмотреть файл

@ -0,0 +1,214 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections;
namespace DAAP {
public delegate void PlaylistSongHandler (object o, int index, Song song);
public class Playlist {
private static int nextid = 1;
private int id;
private string name = String.Empty;
private ArrayList songs = new ArrayList ();
private ArrayList containerIds = new ArrayList ();
public event PlaylistSongHandler SongAdded;
public event PlaylistSongHandler SongRemoved;
public event EventHandler NameChanged;
public Song this[int index] {
get {
if (songs.Count > index)
return (Song) songs[index];
else
return null;
}
set { songs[index] = value; }
}
public Song[] Songs {
get { return (Song[]) songs.ToArray (typeof (Song)); }
}
internal int Id {
get { return id; }
set { id = value; }
}
public string Name {
get { return name; }
set {
name = value;
if (NameChanged != null)
NameChanged (this, new EventArgs ());
}
}
internal Playlist () {
id = nextid++;
}
public Playlist (string name) : this () {
this.name = name;
}
public void InsertSong (int index, Song song) {
InsertSong (index, song, songs.Count + 1);
}
internal void InsertSong (int index, Song song, int id) {
songs.Insert (index, song);
containerIds.Insert (index, id);
if (SongAdded != null)
SongAdded (this, index, song);
}
public void Clear () {
songs.Clear ();
}
public void AddSong (Song song) {
AddSong (song, songs.Count + 1);
}
internal void AddSong (Song song, int id) {
songs.Add (song);
containerIds.Add (id);
if (SongAdded != null)
SongAdded (this, songs.Count - 1, song);
}
public void RemoveAt (int index) {
Song song = (Song) songs[index];
songs.RemoveAt (index);
containerIds.RemoveAt (index);
if (SongRemoved != null)
SongRemoved (this, index, song);
}
public bool RemoveSong (Song song) {
int index;
bool ret = false;
while ((index = IndexOf (song)) >= 0) {
ret = true;
RemoveAt (index);
}
return ret;
}
public int IndexOf (Song song) {
return songs.IndexOf (song);
}
internal int GetContainerId (int index) {
return (int) containerIds[index];
}
internal ContentNode ToSongsNode (int[] deletedIds) {
ArrayList songNodes = new ArrayList ();
for (int i = 0; i < songs.Count; i++) {
Song song = songs[i] as Song;
songNodes.Add (song.ToPlaylistNode ((int) containerIds[i]));
}
ArrayList deletedNodes = null;
if (deletedIds.Length > 0) {
deletedNodes = new ArrayList ();
foreach (int id in deletedIds) {
deletedNodes.Add (new ContentNode ("dmap.itemid", id));
}
}
ArrayList children = new ArrayList ();
children.Add (new ContentNode ("dmap.status", 200));
children.Add (new ContentNode ("dmap.updatetype", deletedNodes == null ? (byte) 0 : (byte) 1));
children.Add (new ContentNode ("dmap.specifiedtotalcount", songs.Count));
children.Add (new ContentNode ("dmap.returnedcount", songs.Count));
children.Add (new ContentNode ("dmap.listing", songNodes));
if (deletedNodes != null)
children.Add (new ContentNode ("dmap.deletedidlisting", deletedNodes));
return new ContentNode ("daap.playlistsongs", children);
}
internal ContentNode ToNode (bool basePlaylist) {
ArrayList nodes = new ArrayList ();
nodes.Add (new ContentNode ("dmap.itemid", id));
nodes.Add (new ContentNode ("dmap.itemname", name));
nodes.Add (new ContentNode ("dmap.itemcount", songs.Count));
if (basePlaylist)
nodes.Add (new ContentNode ("daap.baseplaylist", (byte) 1));
return new ContentNode ("dmap.listingitem", nodes);
}
internal static Playlist FromNode (ContentNode node) {
Playlist pl = new Playlist ();
foreach (ContentNode child in (ContentNode[]) node.Value) {
switch (child.Name) {
case "daap.baseplaylist":
return null;
case "dmap.itemid":
pl.Id = (int) child.Value;
break;
case "dmap.itemname":
pl.Name = (string) child.Value;
break;
default:
break;
}
}
return pl;
}
internal void Update (Playlist pl) {
if (pl.Name == name)
return;
Name = pl.Name;
}
internal int LookupIndexByContainerId (int id) {
return containerIds.IndexOf (id);
}
internal void SetId (int id) {
this.id = id;
}
}
}

84
src/SampleServer.cs Normal file
Просмотреть файл

@ -0,0 +1,84 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.IO;
using DAAP;
using Entagged;
public class SampleServer
{
private static int nextId = 10;
public static void Main (string[] args) {
Server server = new Server ("Test Music");
server.Port = 3891;
Database db = new Database ("Test Music");
foreach (string arg in args)
AddDirectory (db, arg);
Playlist pl = new Playlist ("foo playlist");
foreach (Song song in db.Songs) {
pl.AddSong (song);
}
db.AddPlaylist (pl);
Console.WriteLine ("Done adding files");
server.AddDatabase (db);
server.Start ();
Console.ReadLine ();
}
private static void AddDirectory (Database db, string dir) {
Console.WriteLine ("Adding files in: " + dir);
foreach (string file in Directory.GetFiles (dir)) {
AudioFileWrapper afw = null;
try {
afw = new AudioFileWrapper (file);
} catch (Exception e) {
continue;
}
Song song = new Song ();
song.Artist = afw.Artist;
song.Album = afw.Album;
song.Title = afw.Title;
song.Year = afw.Year;
song.Format = Path.GetExtension (file).Substring (1);
song.Duration = TimeSpan.FromSeconds (afw.Duration);
song.Id = nextId++;
song.Genre = afw.Genre;
song.TrackNumber = afw.TrackNumber;
song.TrackCount = afw.TrackCount;
song.DateAdded = DateTime.Now;
song.DateModified = DateTime.Now;
song.FileName = file;
song.Size = (int) new FileInfo (song.FileName).Length;
db.AddSong (song);
}
foreach (string subdir in Directory.GetDirectories (dir)) {
AddDirectory (db, subdir);
}
}
}

602
src/Server.cs Normal file
Просмотреть файл

@ -0,0 +1,602 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Specialized;
using System.Net;
using System.Net.Sockets;
using System.Web;
using Avahi;
namespace DAAP {
internal delegate bool WebHandler (Socket client, string path, NameValueCollection query);
internal class WebServer {
private const int ChunkLength = 8192;
private UInt16 port;
private Socket server;
private WebHandler handler;
private bool running;
private ArrayList clients = new ArrayList ();
public UInt16 Port {
get { return port; }
set { port = value; }
}
public WebServer (UInt16 port, WebHandler handler) {
this.port = port;
this.handler = handler;
}
public void Start () {
server = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
server.Bind (new IPEndPoint (IPAddress.Any, port));
server.Listen (10);
running = true;
Thread thread = new Thread (ServerLoop);
thread.IsBackground = true;
thread.Start ();
}
public void Stop () {
running = false;
if (server != null) {
server.Close ();
server = null;
}
foreach (Socket client in (ArrayList) clients.Clone ()) {
// do not pass go, do not collect $200...
client.Close ();
}
}
public void WriteResponse (Socket client, ContentNode node) {
WriteResponse (client, HttpStatusCode.OK,
ContentWriter.Write (ContentCodeBag.Default, node));
}
public void WriteResponse (Socket client, HttpStatusCode code, string body) {
WriteResponse (client, code, Encoding.UTF8.GetBytes (body));
}
public void WriteResponse (Socket client, HttpStatusCode code, byte[] body) {
using (BinaryWriter writer = new BinaryWriter (new NetworkStream (client, false))) {
writer.Write (Encoding.UTF8.GetBytes (String.Format ("HTTP/1.1 {0} {1}\r\n", (int) code, code.ToString ())));
writer.Write (Encoding.UTF8.GetBytes ("DAAP-Server: daap-sharp\r\n"));
writer.Write (Encoding.UTF8.GetBytes ("Content-Type: application/x-dmap-tagged\r\n"));
writer.Write (Encoding.UTF8.GetBytes (String.Format ("Content-Length: {0}\r\n", body.Length)));
writer.Write (Encoding.UTF8.GetBytes ("\r\n"));
writer.Write (body);
}
}
public void WriteResponseFile (Socket client, string file) {
FileInfo info = new FileInfo (file);
WriteResponseStream (client, info.Open (FileMode.Open, FileAccess.Read), info.Length);
}
public void WriteResponseStream (Socket client, Stream response, long len) {
using (BinaryWriter writer = new BinaryWriter (new NetworkStream (client, false))) {
writer.Write (Encoding.UTF8.GetBytes ("HTTP/1.1 200 OK\r\n"));
writer.Write (Encoding.UTF8.GetBytes (String.Format ("Content-Length: {0}\r\n", len)));
writer.Write (Encoding.UTF8.GetBytes ("\r\n"));
using (BinaryReader reader = new BinaryReader (response)) {
long count = 0;
while (count < len) {
byte[] buf = reader.ReadBytes (Math.Min (ChunkLength, (int) len - (int) count));
writer.Write (buf);
count += buf.Length;
}
}
}
}
private bool HandleRequest (Socket client) {
if (!client.Connected)
return false;
bool ret = true;
using (StreamReader reader = new StreamReader (new NetworkStream (client, false))) {
string request = reader.ReadLine ();
if (request == null)
return false;
string line = null;
// read the rest of the request
do {
line = reader.ReadLine ();
if (line == "Connection: close") {
ret = false;
}
} while (line != String.Empty && line != null);
string[] splitRequest = request.Split ();
if (splitRequest.Length < 3) {
WriteResponse (client, HttpStatusCode.BadRequest, "Bad Request");
} else {
try {
string path = splitRequest[1];
if (!path.StartsWith ("daap://")) {
path = String.Format ("daap://localhost:{0}/{1}", port, path);
}
Uri uri = new Uri (path);
NameValueCollection query = new NameValueCollection ();
if (uri.Query != null && uri.Query != String.Empty) {
string[] splitquery = uri.Query.Substring (1).Split ('&');
foreach (string queryItem in splitquery) {
if (queryItem == String.Empty)
continue;
string[] splitQueryItem = queryItem.Split ('=');
query[splitQueryItem[0]] = splitQueryItem[1];
}
}
return handler (client, uri.AbsolutePath, query);
} catch (IOException e) {
ret = false;
} catch (Exception e) {
ret = false;
Console.Error.WriteLine ("Trouble handling request {0}: {1}", splitRequest[1], e);
}
}
}
return ret;
}
private void HandleConnection (object o) {
Socket client = (Socket) o;
try {
while (HandleRequest (client)) { }
} catch (IOException e) {
// ignore
} catch (Exception e) {
Console.Error.WriteLine ("Error handling request: " + e);
} finally {
clients.Remove (client);
client.Close ();
}
}
private void ServerLoop () {
while (true) {
try {
if (!running)
break;
Socket client = server.Accept ();
clients.Add (client);
ThreadPool.QueueUserWorkItem (HandleConnection, client);
} catch (SocketException e) {
break;
}
}
}
}
internal class RevisionManager {
private Hashtable revisions = new Hashtable ();
private int current = 1;
public int Current {
get { return current; }
}
public void AddRevision (Database[] databases) {
revisions[++current] = databases;
}
public void RemoveRevision (int rev) {
revisions.Remove (rev);
}
public Database[] GetRevision (int rev) {
if (rev == 0)
return (Database[]) revisions[current];
else
return (Database[]) revisions[rev];
}
public Database GetDatabase (int rev, int id) {
Database[] dbs = GetRevision (rev);
if (dbs == null)
return null;
foreach (Database db in dbs) {
if (db.Id == id)
return db;
}
return null;
}
}
public class Server {
internal const int DefaultTimeout = 1800;
private static Regex dbItemsRegex = new Regex ("/databases/([0-9]*?)/items$");
private static Regex dbSongRegex = new Regex ("/databases/([0-9]*?)/items/([0-9]*).*");
private static Regex dbContainersRegex = new Regex ("/databases/([0-9]*?)/containers$");
private static Regex dbContainerItemsRegex = new Regex ("/databases/([0-9]*?)/containers/([0-9]*?)/items$");
private WebServer ws;
private ArrayList databases = new ArrayList ();
private ArrayList sessions = new ArrayList ();
private Random random = new Random ();
private UInt16 port = 3689;
private ServerInfo serverInfo = new ServerInfo ();
private bool publish;
private bool running;
private Avahi.Client client;
private EntryGroup eg;
private object eglock = new object ();
private RevisionManager revmgr = new RevisionManager ();
public event EventHandler Collision;
public string Name {
get { return serverInfo.Name; }
set {
serverInfo.Name = value;
if (publish)
RegisterService ();
}
}
public UInt16 Port {
get { return port; }
set {
port = value;
ws.Port = value;
}
}
public bool IsPublished {
get { return publish; }
set {
publish = value;
if (running && publish)
RegisterService ();
else if (running && !publish)
UnregisterService ();
}
}
public Server (string name) {
serverInfo.Name = name;
ws = new WebServer (port, OnHandleRequest);
client = new Avahi.Client ();
}
public void Start () {
running = true;
ws.Start ();
client.StateChanged += OnClientStateChanged;
if (publish)
RegisterService ();
}
public void Stop () {
running = false;
ws.Stop ();
UnregisterService ();
// get that thread to wake up and exit
lock (revmgr) {
Monitor.Pulse (revmgr);
}
}
public void AddDatabase (Database db) {
databases.Add (db);
}
public void RemoveDatabase (Database db) {
databases.Remove (db);
}
public void Commit () {
ArrayList clones = new ArrayList ();
foreach (Database db in databases) {
clones.Add (db.Clone ());
}
lock (revmgr) {
revmgr.AddRevision ((Database[]) clones.ToArray (typeof (Database)));
Monitor.Pulse (revmgr);
}
}
private void OnClientStateChanged (object o, ClientState state) {
if (publish && state == ClientState.Running) {
RegisterService ();
}
}
private void RegisterService () {
lock (eglock) {
if (eg != null) {
eg.Reset ();
} else {
eg = new EntryGroup (client);
eg.StateChanged += OnEntryGroupStateChanged;
}
eg.AddService (serverInfo.Name, "_daap._tcp", "", port,
new string[] { "Password=false", "Machine Name=" + serverInfo.Name, "txtvers=1" });
eg.Commit ();
}
}
private void UnregisterService () {
lock (eglock) {
if (eg == null)
return;
eg.Dispose ();
eg = null;
}
}
private void OnEntryGroupStateChanged (object o, EntryGroupState state) {
if (state == EntryGroupState.Collision && Collision != null) {
Collision (this, new EventArgs ());
}
}
internal bool OnHandleRequest (Socket client, string path, NameValueCollection query) {
int session = 0;
if (query["session-id"] != null) {
session = Int32.Parse (query["session-id"]);
}
int clientRev = 0;
if (query["revision-number"] != null) {
clientRev = Int32.Parse (query["revision-number"]);
}
int delta = 0;
if (query["delta"] != null) {
delta = Int32.Parse (query["delta"]);
}
if (path == "/server-info") {
ws.WriteResponse (client, GetServerInfoNode ());
} else if (path == "/content-codes") {
ws.WriteResponse (client, ContentCodeBag.Default.ToNode ());
} else if (path == "/login") {
session = random.Next ();
sessions.Add (session);
ws.WriteResponse (client, GetLoginNode (session));
} else if (path == "/logout") {
sessions.Remove (session);
ws.WriteResponse (client, HttpStatusCode.OK, new byte[0]);
return false;
} else if (path == "/databases") {
if (session == 0) {
ws.WriteResponse (client, HttpStatusCode.Forbidden, "invalid session id");
} else {
ws.WriteResponse (client, GetDatabasesNode ());
}
} else if (dbItemsRegex.IsMatch (path)) {
int dbid = Int32.Parse (dbItemsRegex.Match (path).Groups[1].Value);
Database curdb = revmgr.GetDatabase (clientRev, dbid);
if (curdb == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
ArrayList deletedIds = new ArrayList ();
if (delta > 0) {
Database olddb = revmgr.GetDatabase (clientRev - delta, dbid);
if (olddb != null) {
foreach (Song song in olddb.Songs) {
if (curdb.LookupSongById (song.Id) == null)
deletedIds.Add (song.Id);
}
}
}
ContentNode node = curdb.ToSongsNode (query["meta"].Split (','),
(int[]) deletedIds.ToArray (typeof (int)));
ws.WriteResponse (client, node);
} else if (dbSongRegex.IsMatch (path)) {
Match match = dbSongRegex.Match (path);
int dbid = Int32.Parse (match.Groups[1].Value);
int songid = Int32.Parse (match.Groups[2].Value);
Database db = revmgr.GetDatabase (clientRev, dbid);
if (db == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
Song song = db.LookupSongById (songid);
if (song == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid song id");
return true;
}
try {
if (song.FileName != null) {
ws.WriteResponseFile (client, song.FileName);
} else if (db.Client != null) {
long songLength = 0;
Stream songStream = db.StreamSong (song, out songLength);
try {
ws.WriteResponseStream (client, songStream, songLength);
} catch (IOException e) {
}
} else {
ws.WriteResponse (client, HttpStatusCode.InternalServerError, "no file");
}
} finally {
client.Close ();
}
} else if (dbContainersRegex.IsMatch (path)) {
int dbid = Int32.Parse (dbContainersRegex.Match (path).Groups[1].Value);
Database db = revmgr.GetDatabase (clientRev, dbid);
if (db == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
ws.WriteResponse (client, db.ToPlaylistsNode ());
} else if (dbContainerItemsRegex.IsMatch (path)) {
Match match = dbContainerItemsRegex.Match (path);
int dbid = Int32.Parse (match.Groups[1].Value);
int plid = Int32.Parse (match.Groups[2].Value);
Database curdb = revmgr.GetDatabase (clientRev, dbid);
if (curdb == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
Playlist curpl = curdb.LookupPlaylistById (plid);
if (curdb == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid playlist id");
return true;
}
ArrayList deletedIds = new ArrayList ();
if (delta > 0) {
Database olddb = revmgr.GetDatabase (clientRev - delta, dbid);
if (olddb != null) {
Playlist oldpl = olddb.LookupPlaylistById (plid);
if (oldpl != null) {
Song[] oldplSongs = oldpl.Songs;
for (int i = 0; i < oldplSongs.Length; i++) {
int id = oldpl.GetContainerId (i);
if (curpl.LookupIndexByContainerId (id) < 0) {
deletedIds.Add (id);
}
}
}
}
}
ws.WriteResponse (client, curpl.ToSongsNode ((int[]) deletedIds.ToArray (typeof (int))));
} else if (path == "/update") {
int retrev;
lock (revmgr) {
// if they have the current revision, wait for a change
if (clientRev == revmgr.Current) {
Monitor.Wait (revmgr);
}
retrev = revmgr.Current;
}
if (!running) {
ws.WriteResponse (client, HttpStatusCode.NotFound, "server has been stopped");
} else {
ws.WriteResponse (client, GetUpdateNode (retrev));
}
} else {
ws.WriteResponse (client, HttpStatusCode.Forbidden, "GO AWAY");
}
return true;
}
private ContentNode GetLoginNode (int id) {
return new ContentNode ("dmap.loginresponse",
new ContentNode ("dmap.status", 200),
new ContentNode ("dmap.sessionid", id));
}
private ContentNode GetServerInfoNode () {
return serverInfo.ToNode (databases.Count);
}
private ContentNode GetDatabasesNode () {
ArrayList databaseNodes = new ArrayList ();
Database[] dbs = revmgr.GetRevision (revmgr.Current);
if (dbs != null) {
foreach (Database db in revmgr.GetRevision (revmgr.Current)) {
databaseNodes.Add (db.ToDatabaseNode ());
}
}
ContentNode node = new ContentNode ("daap.serverdatabases",
new ContentNode ("dmap.status", 200),
new ContentNode ("dmap.updatetype", (byte) 0),
new ContentNode ("dmap.specifiedtotalcount", databases.Count),
new ContentNode ("dmap.returnedcount", databases.Count),
new ContentNode ("dmap.listing", databaseNodes));
return node;
}
private ContentNode GetUpdateNode (int revision) {
return new ContentNode ("dmap.updateresponse",
new ContentNode ("dmap.status", 200),
new ContentNode ("dmap.serverrevision", revision));
}
}
}

97
src/ServerInfo.cs Normal file
Просмотреть файл

@ -0,0 +1,97 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Text;
using System.Net;
namespace DAAP {
public enum AuthenticationMethod : byte {
None,
UserAndPassword,
Password,
}
internal class ServerInfo {
private string name;
private AuthenticationMethod authMethod;
private bool supportsUpdate;
public string Name {
get { return name; }
set { name = value; }
}
public AuthenticationMethod AuthenticationMethod {
get { return authMethod; }
set { authMethod = value; }
}
public bool SupportsUpdate {
get { return supportsUpdate; }
set { supportsUpdate = value; }
}
internal static ServerInfo FromNode (ContentNode node) {
ServerInfo info = new ServerInfo ();
if (node.Name != "dmap.serverinforesponse")
return null;
foreach (ContentNode child in (node.Value as ContentNode[])) {
switch (child.Name) {
case "dmap.itemname":
info.Name = (string) child.Value;
break;
case "dmap.authenticationmethod":
info.AuthenticationMethod = (AuthenticationMethod) child.Value;
break;
case "dmap.supportsupdate":
info.SupportsUpdate = (byte) child.Value == 1;
break;
}
}
return info;
}
internal ContentNode ToNode (int dbCount) {
return new ContentNode ("dmap.serverinforesponse",
new ContentNode ("dmap.status", 200),
new ContentNode ("dmap.protocolversion", new Version (2, 0, 2)),
new ContentNode ("daap.protocolversion", new Version (3, 0, 2)),
new ContentNode ("dmap.itemname", name),
new ContentNode ("dmap.loginrequired", (byte) 1),
new ContentNode ("dmap.authenticationmethod", (byte) authMethod),
new ContentNode ("dmap.timeoutinterval", Server.DefaultTimeout),
new ContentNode ("dmap.supportsautologout", (byte) 1),
new ContentNode ("dmap.supportsupdate", (byte) 1),
new ContentNode ("dmap.supportspersistentids", (byte) 1),
new ContentNode ("dmap.supportsextensions", (byte) 1),
new ContentNode ("dmap.supportsbrowse", (byte) 1),
new ContentNode ("dmap.supportsquery", (byte) 1),
new ContentNode ("dmap.supportsindex", (byte) 1),
new ContentNode ("dmap.supportsresolve", (byte) 0),
new ContentNode ("dmap.databasescount", dbCount));
}
}
}

139
src/ServerLocator.cs Normal file
Просмотреть файл

@ -0,0 +1,139 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Net;
using System.Text;
using System.Collections;
using Avahi;
namespace DAAP {
public delegate void ServiceHandler (object o, Service service);
public struct Service {
public IPAddress Address;
public ushort Port;
public string Name;
public bool IsProtected;
public static Service Zero = new Service ();
}
public class ServiceLocator {
private Avahi.Client client;
private ServiceBrowser browser;
private Hashtable services = new Hashtable ();
private ArrayList resolvers = new ArrayList ();
private bool showLocals = false;
public event ServiceHandler Found;
public event ServiceHandler Removed;
public bool ShowLocalServices {
get { return showLocals; }
set { showLocals = value; }
}
public Service[] Services {
get {
ArrayList list = new ArrayList ();
foreach (Service service in services.Values) {
list.Add (service);
}
return (Service[]) list.ToArray (typeof (Service));
}
}
public ServiceLocator () {
client = new Avahi.Client ();
browser = new ServiceBrowser (client, "_daap._tcp");
browser.ServiceAdded += OnServiceAdded;
browser.ServiceRemoved += OnServiceRemoved;
}
private void OnServiceAdded (object o, ServiceInfo service) {
if (!showLocals && client.IsServiceLocal (service)) {
return;
}
ServiceResolver resolver = new ServiceResolver (client, service);
resolvers.Add (resolver);
resolver.Found += OnServiceResolved;
resolver.Timeout += OnServiceTimeout;
}
private void OnServiceResolved (object o, ServiceInfo service) {
resolvers.Remove (o);
(o as ServiceResolver).Dispose ();
string name = service.Name;
bool pwRequired = false;
// iTunes tacks this on to indicate a passsword protected share. Ugh.
if (service.Name.EndsWith ("_PW")) {
name = service.Name.Substring (0, service.Name.Length - 3);
pwRequired = true;
}
foreach (byte[] txt in service.Text) {
string txtstr = Encoding.UTF8.GetString (txt);
string[] splitstr = txtstr.Split('=');
if (splitstr.Length < 2)
continue;
if (splitstr[0].ToLower () == "password")
pwRequired = splitstr[1].ToLower () == "true";
else if (splitstr[0].ToLower () == "machine name")
name = splitstr[1];
}
Service svc;
svc.Address = service.Address;
svc.Port = service.Port;
svc.Name = name;
svc.IsProtected = pwRequired;
services[svc.Name] = svc;
if (Found != null)
Found (this, svc);
}
private void OnServiceTimeout (object o, EventArgs args) {
Console.Error.WriteLine ("Failed to resolve");
}
private void OnServiceRemoved (object o, ServiceInfo service) {
Service svc = (Service) services[service.Name];
if (!svc.Equals (Service.Zero)) {
services.Remove (svc);
if (Removed != null)
Removed (this, svc);
}
}
}
}

409
src/Song.cs Normal file
Просмотреть файл

@ -0,0 +1,409 @@
/*
* daap-sharp
* Copyright (C) 2005 James Willcox <snorp@snorp.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections;
using Mono.Unix;
namespace DAAP {
public class Song : ICloneable {
private string artist;
private string album;
private string title;
private int year;
private string format;
private TimeSpan duration;
private int id;
private int size;
private string genre;
private int trackNumber;
private int trackCount;
private string fileName;
private DateTime dateAdded;
private DateTime dateModified;
public event EventHandler Updated;
public string Artist {
get { return artist; }
set {
artist = value;
EmitUpdated ();
}
}
public string Album {
get { return album; }
set {
album = value;
EmitUpdated ();
}
}
public string Title {
get { return title; }
set {
title = value;
EmitUpdated ();
}
}
public int Year {
get { return year; }
set {
year = value;
EmitUpdated ();
}
}
public string Format {
get { return format; }
set {
format = value;
EmitUpdated ();
}
}
public TimeSpan Duration {
get { return duration; }
set {
duration = value;
EmitUpdated ();
}
}
public int Id {
get { return id; }
}
public int Size {
get { return size; }
set {
size = value;
EmitUpdated ();
}
}
public string Genre {
get { return genre; }
set {
genre = value;
EmitUpdated ();
}
}
public int TrackNumber {
get { return trackNumber; }
set {
trackNumber = value;
EmitUpdated ();
}
}
public int TrackCount {
get { return trackCount; }
set {
trackCount = value;
EmitUpdated ();
}
}
public string FileName {
get { return fileName; }
set {
fileName = value;
EmitUpdated ();
}
}
public DateTime DateAdded {
get { return dateAdded; }
set {
dateAdded = value;
EmitUpdated ();
}
}
public DateTime DateModified {
get { return dateModified; }
set {
dateModified = value;
EmitUpdated ();
}
}
public object Clone () {
Song song = new Song ();
song.artist = artist;
song.album = album;
song.title = title;
song.year = year;
song.format = format;
song.duration = duration;
song.id = id;
song.size = size;
song.genre = genre;
song.trackNumber = trackNumber;
song.trackCount = trackCount;
song.fileName = fileName;
song.dateAdded = dateAdded;
song.dateModified = dateModified;
return song;
}
public override string ToString () {
return String.Format ("{0} - {1}.{2} ({3}): {4}", artist, title, format, duration, id);
}
internal void SetId (int id) {
this.id = id;
}
internal ContentNode ToNode (string[] fields) {
ArrayList nodes = new ArrayList ();
foreach (string field in fields) {
object val = null;
switch (field) {
case "dmap.itemid":
val = id;
break;
case "dmap.itemname":
val = title;
break;
case "dmap.itemkind":
val = (byte) 2;
break;
case "dmap.persistentid":
val = (long) id;
break;
case "daap.songalbum":
val = album;
break;
case "daap.songgrouping":
val = String.Empty;
break;
case "daap.songartist":
val = artist;
break;
case "daap.songbitrate":
val = (short) 0;
break;
case "daap.songbeatsperminute":
val = (short) 0;
break;
case "daap.songcomment":
val = String.Empty;
break;
case "daap.songcompilation":
val = (byte) 0;
break;
case "daap.songcomposer":
val = String.Empty;
break;
case "daap.songdateadded":
val = dateAdded;
break;
case "daap.songdatemodified":
val = dateModified;
break;
case "daap.songdisccount":
val = (short) 0;
break;
case "daap.songdiscnumber":
val = (short) 0;
break;
case "daap.songdisabled":
val = (byte) 0;
break;
case "daap.songeqpreset":
val = String.Empty;
break;
case "daap.songformat":
val = format;
break;
case "daap.songgenre":
val = genre;
break;
case "daap.songdescription":
val = String.Empty;
break;
case "daap.songrelativevolume":
val = (int) 0;
break;
case "daap.songsamplerate":
val = 0;
break;
case "daap.songsize":
val = size;
break;
case "daap.songstarttime":
val = 0;
break;
case "daap.songstoptime":
val = 0;
break;
case "daap.songtime":
val = (int) duration.TotalMilliseconds;
break;
case "daap.songtrackcount":
val = (short) trackCount;
break;
case "daap.songtracknumber":
val = (short) trackNumber;
break;
case "daap.songuserrating":
val = (byte) 0;
break;
case "daap.songyear":
val = (short) year;
break;
case "daap.songdatakind":
val = (byte) 0;
break;
case "daap.songdataurl":
val = String.Empty;
break;
default:
break;
}
if (val != null)
nodes.Add (new ContentNode (field, val));
}
return new ContentNode ("dmap.listingitem", nodes);
}
internal static Song FromNode (ContentNode node) {
Song song = new Song ();
foreach (ContentNode field in (ContentNode[]) node.Value) {
switch (field.Name) {
case "dmap.itemid":
song.id = (int) field.Value;
break;
case "daap.songartist":
song.artist = (string) field.Value;
break;
case "dmap.itemname":
song.title = (string) field.Value;
break;
case "daap.songalbum":
song.album = (string) field.Value;
break;
case "daap.songtime":
song.duration = TimeSpan.FromMilliseconds ((int) field.Value);
break;
case "daap.songformat":
song.format = (string) field.Value;
break;
case "daap.songgenre":
song.genre = (string) field.Value;
break;
case "daap.songsize":
song.size = (int) field.Value;
break;
case "daap.songtrackcount":
song.trackCount = (short) field.Value;
break;
case "daap.songtracknumber":
song.trackNumber = (short) field.Value;
break;
default:
break;
}
}
return song;
}
internal ContentNode ToPlaylistNode (int containerId) {
return new ContentNode ("dmap.listingitem",
new ContentNode ("dmap.itemkind", (byte) 2),
new ContentNode ("daap.songdatakind", (byte) 0),
new ContentNode ("dmap.itemid", Id),
new ContentNode ("dmap.containeritemid", containerId),
new ContentNode ("dmap.itemname", Title));
}
internal static void FromPlaylistNode (Database db, ContentNode node, out Song song, out int containerId) {
song = null;
containerId = 0;
foreach (ContentNode field in (ContentNode[]) node.Value) {
switch (field.Name) {
case "dmap.itemid":
song = db.LookupSongById ((int) field.Value);
break;
case "dmap.containeritemid":
containerId = (int) field.Value;
break;
default:
break;
}
}
}
private bool Equals (Song song) {
return artist == song.Artist &&
album == song.Album &&
title == song.Title &&
year == song.Year &&
format == song.Format &&
duration == song.Duration &&
size == song.Size &&
genre == song.Genre &&
trackNumber == song.TrackNumber &&
trackCount == song.TrackCount &&
dateAdded == song.DateAdded &&
dateModified == song.DateModified;
}
internal void Update (Song song) {
if (Equals (song))
return;
artist = song.Artist;
album = song.Album;
title = song.Title;
year = song.Year;
format = song.Format;
duration = song.Duration;
size = song.Size;
genre = song.Genre;
trackNumber = song.TrackNumber;
trackCount = song.TrackCount;
dateAdded = song.DateAdded;
dateModified = song.DateModified;
EmitUpdated ();
}
private void EmitUpdated () {
if (Updated != null)
Updated (this, new EventArgs ());
}
}
}

Двоичные данные
src/content-codes Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<monodoc>
<source provider="ecma" basefile="daap-sharp-docs" path="various"/>
</monodoc>

Двоичные данные
src/daap-sharp.snk Normal file

Двоичный файл не отображается.

5
src/en/DAAP.xml Normal file
Просмотреть файл

@ -0,0 +1,5 @@
<Namespace Name="DAAP">
<Docs>
<summary>daap-sharp is a library for publishing and accessing DAAP shares</summary>
</Docs>
</Namespace>

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:20 2005 4336.0

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:25 2005 4544.0

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:25 2005 4544.3

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:25 2005 4544.5

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:25 2005 4544.6

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Sat Oct 1 16:29:39 2005 605.0

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Sat Oct 1 16:29:39 2005 605.1

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:25 2005 4544.10

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Sat Oct 1 16:29:39 2005 605.2

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Sat Oct 1 16:31:08 2005 630.0

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Wed Sep 14 01:07:25 2005 4544.11

Просмотреть файл

@ -0,0 +1 @@
James Willcox <snorp@snorp.net> Sat Oct 1 16:29:39 2005 605.3

200
src/en/DAAP/Client.xml Normal file
Просмотреть файл

@ -0,0 +1,200 @@
<Type Name="Client" FullName="DAAP.Client">
<TypeSignature Language="C#" Value="public class Client : System.IDisposable" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces>
<Interface>
<InterfaceName>System.IDisposable</InterfaceName>
</Interface>
</Interfaces>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Client (string host, ushort port);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="host" Type="System.String" />
<Parameter Name="port" Type="System.UInt16" />
</Parameters>
<Docs>
<param name="host">the host to connect to</param>
<param name="port">the port to connect to</param>
<summary>Creates a new <see cref="T:DAAP.Client" /> and points it at the specified host and port.</summary>
<remarks />
</Docs>
</Member>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Client (System.Net.IPAddress address, ushort port);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="address" Type="System.Net.IPAddress" />
<Parameter Name="port" Type="System.UInt16" />
</Parameters>
<Docs>
<param name="address">the address to connect to</param>
<param name="port">the port to connect to</param>
<summary>Creates a new <see cref="T:DAAP.Client" /> instance, and points it at the specified address and port.</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Login">
<MemberSignature Language="C#" Value="public void Login ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Login to the server using no credentials</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Login">
<MemberSignature Language="C#" Value="public void Login (string username, string password);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="username" Type="System.String" />
<Parameter Name="password" Type="System.String" />
</Parameters>
<Docs>
<param name="username">the username</param>
<param name="password">the password</param>
<summary>Login to the server using the specified username and password</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Logout">
<MemberSignature Language="C#" Value="public void Logout ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Logout of the server</summary>
<remarks>Many DAAP servers only allow a limited number of users to be logged in at once (iTunes, for instance, only allows 5), so applications should take care to logout when they are done to allow other clients access.</remarks>
</Docs>
</Member>
<Member MemberName="Databases">
<MemberSignature Language="C#" Value="public DAAP.Database[] Databases { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.Database[]</ReturnType>
</ReturnValue>
<Docs>
<summary>The song databases currently available on the server</summary>
<value>An array of <see cref="T:DAAP.Database" /> instances</value>
<remarks />
</Docs>
</Member>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Client (DAAP.Service service);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="service" Type="DAAP.Service" />
</Parameters>
<Docs>
<param name="service">the service to connect to</param>
<summary>Creates a new <see cref="T:DAAP.Client" /> from a <see cref="T:DAAP.Service" />, usually obtained from a <see cref="T:DAAP.ServiceLocator" /> instance.</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Updated">
<MemberSignature Language="C#" Value="public event EventHandler Updated;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>System.EventHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when something has changed on the server (songs added/removed, etc).</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Name">
<MemberSignature Language="C#" Value="public string Name { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The name of the service which this client is connected to</summary>
<value>a string indicating the name of the service</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Address">
<MemberSignature Language="C#" Value="public System.Net.IPAddress Address { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Net.IPAddress</ReturnType>
</ReturnValue>
<Docs>
<summary>The address which this Client is connecting to</summary>
<value>An IP address</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Port">
<MemberSignature Language="C#" Value="public ushort Port { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.UInt16</ReturnType>
</ReturnValue>
<Docs>
<summary>The port on the server to connect to</summary>
<value>a ushort representing the port</value>
<remarks />
</Docs>
</Member>
<Member MemberName="AuthenticationMethod">
<MemberSignature Language="C#" Value="public DAAP.AuthenticationMethod AuthenticationMethod { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.AuthenticationMethod</ReturnType>
</ReturnValue>
<Docs>
<summary>The authentication method used by the server.</summary>
<value>An <see cref="T:DAAP.AuthenticationMethod" /> enum</value>
<remarks>DAAP servers can require a username and password, or just a password, or neither. The value of this property reflects that, and can be used before <see cref="T:DAAP.Client.Login" /> is called to prompt the user for this information, if necessary.</remarks>
</Docs>
</Member>
<Member MemberName="Dispose">
<MemberSignature Language="C#" Value="public void Dispose ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Disposes of the Client instance</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Login">
<MemberSignature Language="C#" Value="public void Login (string password);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="password" Type="System.String" />
</Parameters>
<Docs>
<param name="password">the password</param>
<summary>Login to the server using only a password</summary>
<remarks />
</Docs>
</Member>
</Members>
<Docs>
<summary>Used to access remote song databases</summary>
<remarks>This class is used to access song databases on remote machines.</remarks>
</Docs>
</Type>

Просмотреть файл

@ -0,0 +1,29 @@
<Type Name="ContentException" FullName="DAAP.ContentException">
<TypeSignature Language="C#" Value="public class ContentException : System.ApplicationException" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.ApplicationException</BaseTypeName>
</Base>
<Interfaces />
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public ContentException (string msg);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="msg" Type="System.String" />
</Parameters>
<Docs>
<param name="msg">To be added.</param>
<summary>To be added.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
</Members>
<Docs>
<summary>Thrown when a server returns invalid content</summary>
<remarks />
</Docs>
</Type>

277
src/en/DAAP/Database.xml Normal file
Просмотреть файл

@ -0,0 +1,277 @@
<Type Name="Database" FullName="DAAP.Database">
<TypeSignature Language="C#" Value="public class Database : System.ICloneable" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces>
<Interface>
<InterfaceName>System.ICloneable</InterfaceName>
</Interface>
</Interfaces>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Database (string name);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="name" Type="System.String" />
</Parameters>
<Docs>
<param name="name">the name of the database</param>
<summary>Creates a new database with the specified name.</summary>
<remarks>In iTunes, the name of the first database is what gets shown to the user.</remarks>
</Docs>
</Member>
<Member MemberName="LookupSongById">
<MemberSignature Language="C#" Value="public DAAP.Song LookupSongById (int id);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>DAAP.Song</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="id" Type="System.Int32" />
</Parameters>
<Docs>
<param name="id">the id of the song</param>
<summary>Finds a song, given its id</summary>
<returns>the song if found, null otherwise</returns>
<remarks />
</Docs>
</Member>
<Member MemberName="LookupPlaylistById">
<MemberSignature Language="C#" Value="public DAAP.Playlist LookupPlaylistById (int id);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>DAAP.Playlist</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="id" Type="System.Int32" />
</Parameters>
<Docs>
<param name="id">the id of the playlist</param>
<summary>Finds a playlist, given its id</summary>
<returns>the playlist if found, null otherwise</returns>
<remarks />
</Docs>
</Member>
<Member MemberName="StreamSong">
<MemberSignature Language="C#" Value="public System.IO.Stream StreamSong (DAAP.Song song, out long length);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.IO.Stream</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
<Parameter Name="length" Type="System.Int64&amp;" RefType="out" />
</Parameters>
<Docs>
<param name="song">the song to stream</param>
<param name="length">the length of the stream, in bytes</param>
<summary>Streams a song from the server</summary>
<returns>A stream containing the song data</returns>
<remarks />
</Docs>
</Member>
<Member MemberName="DownloadSong">
<MemberSignature Language="C#" Value="public void DownloadSong (DAAP.Song song, string dest);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
<Parameter Name="dest" Type="System.String" />
</Parameters>
<Docs>
<param name="song">the song to download</param>
<param name="dest">the location to put the song, e.g. "/tmp/foo.mp3"</param>
<summary>Downloads a song to the specified file</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="AddSong">
<MemberSignature Language="C#" Value="public void AddSong (DAAP.Song song);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<Docs>
<param name="song">the song to add</param>
<summary>Adds a song to the database</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="RemoveSong">
<MemberSignature Language="C#" Value="public void RemoveSong (DAAP.Song song);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<Docs>
<param name="song">the song to remove</param>
<summary>Removes a song from the database</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="AddPlaylist">
<MemberSignature Language="C#" Value="public void AddPlaylist (DAAP.Playlist pl);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="pl" Type="DAAP.Playlist" />
</Parameters>
<Docs>
<param name="pl">the playlist to add</param>
<summary>Adds a playlist to the database</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="RemovePlaylist">
<MemberSignature Language="C#" Value="public void RemovePlaylist (DAAP.Playlist pl);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="pl" Type="DAAP.Playlist" />
</Parameters>
<Docs>
<param name="pl">the playlist to remove</param>
<summary>Removes a playlist from the database</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Id">
<MemberSignature Language="C#" Value="public int Id { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Docs>
<summary>The id of the database</summary>
<value>an int</value>
<remarks>database ids should be unique within a given client/server</remarks>
</Docs>
</Member>
<Member MemberName="Name">
<MemberSignature Language="C#" Value="public string Name { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>the name of the database</summary>
<value>a string</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Songs">
<MemberSignature Language="C#" Value="public DAAP.Song[] Songs { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.Song[]</ReturnType>
</ReturnValue>
<Docs>
<summary>the songs contained in the database</summary>
<value>An array of songs</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Playlists">
<MemberSignature Language="C#" Value="public DAAP.Playlist[] Playlists { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.Playlist[]</ReturnType>
</ReturnValue>
<Docs>
<summary>the playlists contained in the database</summary>
<value>An array of playlists</value>
<remarks />
</Docs>
</Member>
<Member MemberName="SongAdded">
<MemberSignature Language="C#" Value="public event DAAP.SongHandler SongAdded;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.SongHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a song is added</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="SongRemoved">
<MemberSignature Language="C#" Value="public event DAAP.SongHandler SongRemoved;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.SongHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a song is removed</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="PlaylistAdded">
<MemberSignature Language="C#" Value="public event DAAP.PlaylistHandler PlaylistAdded;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.PlaylistHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a playlist is added</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="PlaylistRemoved">
<MemberSignature Language="C#" Value="public event DAAP.PlaylistHandler PlaylistRemoved;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.PlaylistHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a playlist is removed</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Clear">
<MemberSignature Language="C#" Value="public void Clear ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Clear the songs and playlists</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Clone">
<MemberSignature Language="C#" Value="public object Clone ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Object</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Makes a copy of this database</summary>
<returns>A copy of the database.</returns>
<remarks>The individual songs and playlists contained in the database are also copied.</remarks>
</Docs>
</Member>
</Members>
<Docs>
<summary>Holds songs and playlists</summary>
<remarks />
</Docs>
</Type>

198
src/en/DAAP/Playlist.xml Normal file
Просмотреть файл

@ -0,0 +1,198 @@
<Type Name="Playlist" FullName="DAAP.Playlist">
<TypeSignature Language="C#" Value="public class Playlist" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Playlist (string name);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="name" Type="System.String" />
</Parameters>
<Docs>
<param name="name">the name of the playlist</param>
<summary>Creates a new playlist with the specified name</summary>
<remarks>Playlist names are not required to be unique, but it is recommended, to avoid confusion.</remarks>
</Docs>
</Member>
<Member MemberName="InsertSong">
<MemberSignature Language="C#" Value="public void InsertSong (int index, DAAP.Song song);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="index" Type="System.Int32" />
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<Docs>
<param name="index">The index where the song should appear</param>
<param name="song">the song to insert</param>
<summary>Inserts a song into the playlist at the specified position</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Clear">
<MemberSignature Language="C#" Value="public void Clear ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Clears the playlist</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="AddSong">
<MemberSignature Language="C#" Value="public void AddSong (DAAP.Song song);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<Docs>
<param name="song">the song to add</param>
<summary>Appends a song to the end of the playlist</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="RemoveSong">
<MemberSignature Language="C#" Value="public bool RemoveSong (DAAP.Song song);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<Docs>
<param name="song">the song to remove</param>
<summary>Removes all instances of the specified song from the playlist</summary>
<returns>true if the song was found and removed, false otherwise</returns>
<remarks />
</Docs>
</Member>
<Member MemberName="IndexOf">
<MemberSignature Language="C#" Value="public int IndexOf (DAAP.Song song);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<Docs>
<param name="song">the song</param>
<summary>Returns the index of a song in the playlist</summary>
<returns>the first index of the specified song in the playlist, -1 if the song does not exist in the playlist</returns>
<remarks />
</Docs>
</Member>
<Member MemberName="Songs">
<MemberSignature Language="C#" Value="public DAAP.Song[] Songs { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.Song[]</ReturnType>
</ReturnValue>
<Docs>
<summary>The songs in the playlist</summary>
<value>An array of <see cref="T:DAAP.Song" /> instances. These are the same instances contained in the <see cref="T:DAAP.Database" /> class, and are not copies.</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Name">
<MemberSignature Language="C#" Value="public string Name { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The name of the playlist</summary>
<value>a string</value>
<remarks />
</Docs>
</Member>
<Member MemberName="SongAdded">
<MemberSignature Language="C#" Value="public event DAAP.PlaylistSongHandler SongAdded;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.PlaylistSongHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a song has been added to the playlist</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="SongRemoved">
<MemberSignature Language="C#" Value="public event DAAP.PlaylistSongHandler SongRemoved;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.PlaylistSongHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a song is removed from the playlist</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="NameChanged">
<MemberSignature Language="C#" Value="public event EventHandler NameChanged;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>System.EventHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when the name of the playlist has changed</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="RemoveAt">
<MemberSignature Language="C#" Value="public void RemoveAt (int index);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="index" Type="System.Int32" />
</Parameters>
<Docs>
<param name="index">the index to remove</param>
<summary>Removes the song at the given position</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Item">
<MemberSignature Language="C#" Value="public DAAP.Song Item[int index] { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.Song</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="index" Type="System.Int32" />
</Parameters>
<Docs>
<param name="index">the index of the song</param>
<summary>Accesses the songs in the playlist by index</summary>
<value>a song</value>
<remarks />
</Docs>
</Member>
</Members>
<Docs>
<summary>Contains a named list of songs</summary>
<remarks />
</Docs>
<Attributes>
<Attribute>
<AttributeName>System.Reflection.DefaultMember(MemberName="Item")</AttributeName>
</Attribute>
</Attributes>
</Type>

Просмотреть файл

@ -0,0 +1,23 @@
<Type Name="PlaylistHandler" FullName="DAAP.PlaylistHandler">
<TypeSignature Language="C#" Value="public delegate void PlaylistHandler(object o, DAAP.Playlist pl);" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Delegate</BaseTypeName>
</Base>
<Parameters>
<Parameter Name="o" Type="System.Object" />
<Parameter Name="pl" Type="DAAP.Playlist" />
</Parameters>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Docs>
<param name="o">the object from which the event originated</param>
<param name="pl">the playlist relating to the event</param>
<summary>used to handle events relating to playlists</summary>
<remarks />
</Docs>
</Type>

Просмотреть файл

@ -0,0 +1,25 @@
<Type Name="PlaylistSongHandler" FullName="DAAP.PlaylistSongHandler">
<TypeSignature Language="C#" Value="public delegate void PlaylistSongHandler(object o, int index, DAAP.Song song);" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Delegate</BaseTypeName>
</Base>
<Parameters>
<Parameter Name="o" Type="System.Object" />
<Parameter Name="index" Type="System.Int32" />
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Docs>
<param name="o">the playlist from which the event originated</param>
<param name="index">the index of the song in the playlist</param>
<param name="song">To be added.</param>
<summary>used with events relating to songs in playlists</summary>
<remarks>To be added.</remarks>
</Docs>
</Type>

142
src/en/DAAP/Server.xml Normal file
Просмотреть файл

@ -0,0 +1,142 @@
<Type Name="Server" FullName="DAAP.Server">
<TypeSignature Language="C#" Value="public class Server" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Server (string name);" />
<MemberType>Constructor</MemberType>
<Parameters>
<Parameter Name="name" Type="System.String" />
</Parameters>
<Docs>
<param name="name">the name</param>
<summary>Creates a new server with the specified name</summary>
<remarks>The server name is used when announcing the server's presence over mDNS/DNS-SD. It is the string that will most likely show up in client user interfaces, etc.</remarks>
</Docs>
</Member>
<Member MemberName="Collision">
<MemberSignature Language="C#" Value="public event EventHandler Collision;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>System.EventHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when there is a collision with the service name</summary>
<remarks>When the server's presence is announced over mDNS/DNS-SD, it's possible that another service may exist with the same name. Applications should connect to this event to be notified when that occurs, and set the Name property to something unique.</remarks>
</Docs>
</Member>
<Member MemberName="Start">
<MemberSignature Language="C#" Value="public void Start ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Starts the server</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="AddDatabase">
<MemberSignature Language="C#" Value="public void AddDatabase (DAAP.Database db);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="db" Type="DAAP.Database" />
</Parameters>
<Docs>
<param name="db">the database to add</param>
<summary>Adds a database of songs to the server.</summary>
<remarks>Most servers only have one database, as some clients only display the first one anyway (iTunes).</remarks>
</Docs>
</Member>
<Member MemberName="RemoveDatabase">
<MemberSignature Language="C#" Value="public void RemoveDatabase (DAAP.Database db);" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="db" Type="DAAP.Database" />
</Parameters>
<Docs>
<param name="db">the database to remove</param>
<summary>Removes a database from the server</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Name">
<MemberSignature Language="C#" Value="public string Name { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>the name of the server</summary>
<value>a string representing the name of the server</value>
<remarks>See the constructor for an explanation of how the server name is used</remarks>
</Docs>
</Member>
<Member MemberName="Port">
<MemberSignature Language="C#" Value="public ushort Port { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.UInt16</ReturnType>
</ReturnValue>
<Docs>
<summary>The port to listen on</summary>
<value>a ushort representing the TCP port to listen on</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Commit">
<MemberSignature Language="C#" Value="public void Commit ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Commits the most recent database changes, and makes them available to clients.</summary>
<remarks>Server song databases are versioned such that changes are managed in a way that easily allows clients to merge those changes locally. Any changes done to a server's databases (add/remove songs or playlists, etc) are stored and not applied until this method is called, after which they are immediately made available to clients.</remarks>
</Docs>
</Member>
<Member MemberName="Stop">
<MemberSignature Language="C#" Value="public void Stop ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Stops the server</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="IsPublished">
<MemberSignature Language="C#" Value="public bool IsPublished { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Whether or not to publish the server's presence over mDNS/DNS-SD</summary>
<value>a boolean</value>
<remarks>defaults to true</remarks>
</Docs>
</Member>
</Members>
<Docs>
<summary>Allows publishing songs for other machines to access</summary>
<remarks />
</Docs>
</Type>

Просмотреть файл

@ -0,0 +1,23 @@
<Type Name="ServiceHandler" FullName="DAAP.ServiceHandler">
<TypeSignature Language="C#" Value="public delegate void ServiceHandler(object o, DAAP.Service service);" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Delegate</BaseTypeName>
</Base>
<Parameters>
<Parameter Name="o" Type="System.Object" />
<Parameter Name="service" Type="DAAP.Service" />
</Parameters>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Docs>
<param name="o">the object firing the event</param>
<param name="service">the service related to the event</param>
<summary>used with events relating to services</summary>
<remarks />
</Docs>
</Type>

Просмотреть файл

@ -0,0 +1,72 @@
<Type Name="ServiceLocator" FullName="DAAP.ServiceLocator">
<TypeSignature Language="C#" Value="public class ServiceLocator" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public ServiceLocator ();" />
<MemberType>Constructor</MemberType>
<Parameters />
<Docs>
<summary>Create a new ServiceLocator instance</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Found">
<MemberSignature Language="C#" Value="public event DAAP.ServiceHandler Found;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.ServiceHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a new service is found</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Removed">
<MemberSignature Language="C#" Value="public event DAAP.ServiceHandler Removed;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>DAAP.ServiceHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when a service goes away</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="ShowLocalServices">
<MemberSignature Language="C#" Value="public bool ShowLocalServices { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Whether or not to show services on the local machine</summary>
<value>a boolean</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Services">
<MemberSignature Language="C#" Value="public DAAP.Service[] Services { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>DAAP.Service[]</ReturnType>
</ReturnValue>
<Docs>
<summary>The services that have been found</summary>
<value>An array of Service structs</value>
<remarks />
</Docs>
</Member>
</Members>
<Docs>
<summary>Locates DAAP services on the network</summary>
<remarks />
</Docs>
</Type>

222
src/en/DAAP/Song.xml Normal file
Просмотреть файл

@ -0,0 +1,222 @@
<Type Name="Song" FullName="DAAP.Song">
<TypeSignature Language="C#" Value="public class Song : System.ICloneable" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces>
<Interface>
<InterfaceName>System.ICloneable</InterfaceName>
</Interface>
</Interfaces>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public Song ();" />
<MemberType>Constructor</MemberType>
<Parameters />
<Docs>
<summary>Creates a new song</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Updated">
<MemberSignature Language="C#" Value="public event EventHandler Updated;" />
<MemberType>Event</MemberType>
<ReturnValue>
<ReturnType>System.EventHandler</ReturnType>
</ReturnValue>
<Docs>
<summary>fired when any member of the song has changed</summary>
<remarks />
</Docs>
</Member>
<Member MemberName="Clone">
<MemberSignature Language="C#" Value="public object Clone ();" />
<MemberType>Method</MemberType>
<ReturnValue>
<ReturnType>System.Object</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>makes a copy of the song</summary>
<returns>a copy of the song</returns>
<remarks />
</Docs>
</Member>
<Member MemberName="Artist">
<MemberSignature Language="C#" Value="public string Artist { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The artist performing the song</summary>
<value>a string</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Album">
<MemberSignature Language="C#" Value="public string Album { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The album the song belongs to</summary>
<value>a string</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Title">
<MemberSignature Language="C#" Value="public string Title { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The title of the song</summary>
<value>a string</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Year">
<MemberSignature Language="C#" Value="public int Year { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Docs>
<summary>Year in which the song was made</summary>
<value>an int</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Format">
<MemberSignature Language="C#" Value="public string Format { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The encoding format of the song, e.g. "mp3", "aac", "wav"</summary>
<value />
<remarks />
</Docs>
</Member>
<Member MemberName="Duration">
<MemberSignature Language="C#" Value="public TimeSpan Duration { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.TimeSpan</ReturnType>
</ReturnValue>
<Docs>
<summary>duration of the song</summary>
<value>a TimeSpan</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Id">
<MemberSignature Language="C#" Value="public int Id { get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Docs>
<summary>The id of the song</summary>
<value>an int</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Size">
<MemberSignature Language="C#" Value="public int Size { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Docs>
<summary>Size of the song data, in bytes</summary>
<value>an int</value>
<remarks />
</Docs>
</Member>
<Member MemberName="Genre">
<MemberSignature Language="C#" Value="public string Genre { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>the genre of the song</summary>
<value>a string</value>
<remarks />
</Docs>
</Member>
<Member MemberName="TrackNumber">
<MemberSignature Language="C#" Value="public int TrackNumber { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Docs>
<summary>Track number for the song</summary>
<value>an int</value>
<remarks />
</Docs>
</Member>
<Member MemberName="TrackCount">
<MemberSignature Language="C#" Value="public int TrackCount { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.Int32</ReturnType>
</ReturnValue>
<Docs>
<summary>Number of tracks in the album the song belongs to</summary>
<value>an int</value>
<remarks />
</Docs>
</Member>
<Member MemberName="FileName">
<MemberSignature Language="C#" Value="public string FileName { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The file name where the song resides on the filesystem</summary>
<value>a string</value>
<remarks>This will be null for songs originating from a client database.</remarks>
</Docs>
</Member>
<Member MemberName="DateAdded">
<MemberSignature Language="C#" Value="public DateTime DateAdded { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.DateTime</ReturnType>
</ReturnValue>
<Docs>
<summary>Date when the song was added to the database or playlist</summary>
<value>a DateTime</value>
<remarks />
</Docs>
</Member>
<Member MemberName="DateModified">
<MemberSignature Language="C#" Value="public DateTime DateModified { set; get; };" />
<MemberType>Property</MemberType>
<ReturnValue>
<ReturnType>System.DateTime</ReturnType>
</ReturnValue>
<Docs>
<summary>Date when the song was last changed</summary>
<value>a DateTime</value>
<remarks />
</Docs>
</Member>
</Members>
<Docs>
<summary>Represents a song</summary>
<remarks />
</Docs>
</Type>

Просмотреть файл

@ -0,0 +1,23 @@
<Type Name="SongHandler" FullName="DAAP.SongHandler">
<TypeSignature Language="C#" Value="public delegate void SongHandler(object o, DAAP.Song song);" />
<AssemblyInfo>
<AssemblyName>daap-sharp</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Delegate</BaseTypeName>
</Base>
<Parameters>
<Parameter Name="o" Type="System.Object" />
<Parameter Name="song" Type="DAAP.Song" />
</Parameters>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Docs>
<param name="o">the object firing the event</param>
<param name="song">the song related to the event</param>
<summary>used with events relating to songs</summary>
<remarks />
</Docs>
</Type>

25
src/en/index.xml Normal file
Просмотреть файл

@ -0,0 +1,25 @@
<Overview>
<Assemblies>
<Assembly Name="daap-sharp" Version="0.0.0.0" />
</Assemblies>
<Remarks></Remarks>
<Copyright>2005 James Willcox <snorp@snorp.net></Copyright>
<Types>
<Namespace Name="DAAP">
<Type Name="ContentException" />
<Type Name="Client" />
<Type Name="Database" />
<Type Name="Playlist" />
<Type Name="Server" />
<Type Name="Song" />
<Type Name="Service" />
<Type Name="ServiceLocator" />
<Type Name="SongHandler" />
<Type Name="PlaylistHandler" />
<Type Name="PlaylistSongHandler" />
<Type Name="ServiceHandler" />
<Type Name="AuthenticationMethod" />
</Namespace>
</Types>
<Title>daap-sharp</Title>
</Overview>