diff options
author | Daniel Mack <daniel@caiaq.de> | 2009-10-08 14:19:47 +0800 |
---|---|---|
committer | Daniel Mack <daniel@caiaq.de> | 2009-10-08 14:19:47 +0800 |
commit | 0b388bff522f689fdb4d98529a39f3701db57c08 (patch) | |
tree | 837b4fb0993078a708dfddb5801220e44a711d32 | |
parent | 94aa9097f4ded68623160d754a4bf2632b8efc79 (diff) | |
parent | 8ec304d2d1e956cc3f5f35437ac4fe580b36f004 (diff) |
Merge branch 'master' of git://0pointer.de/pulseaudio
102 files changed, 24579 insertions, 2268 deletions
diff --git a/configure.ac b/configure.ac index e75378e2..77ec8846 100644 --- a/configure.ac +++ b/configure.ac @@ -22,8 +22,7 @@ AC_PREREQ(2.63) -AC_INIT([pulseaudio], m4_esyscmd([./git-version-gen .tarball-version]), - [mzchyfrnhqvb (at) 0pointer (dot) net]) +AC_INIT([pulseaudio],[m4_esyscmd(./git-version-gen .tarball-version)],[mzchyfrnhqvb (at) 0pointer (dot) net]) AC_CONFIG_SRCDIR([src/daemon/main.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) @@ -45,7 +44,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 16) # The stable ABI for client applications, for the version info x:y:z # always will hold y=z -AC_SUBST(LIBPULSE_VERSION_INFO, [11:0:11]) +AC_SUBST(LIBPULSE_VERSION_INFO, [12:0:12]) # A simplified, synchronous, ABI-stable interface for client # applications, for the version info x:y:z always will hold y=z @@ -1199,6 +1198,7 @@ if test "x${dbus}" != xno || test "x${bluez}" != xno || test "x${hal}" != xno ; HAVE_DBUS=1 saved_LIBS="$LIBS" LIBS="$LIBS $DBUS_LIBS" + CFLAGS="$CFLAGS $DBUS_CFLAGS" AC_CHECK_FUNCS(dbus_watch_get_unix_fd) LIBS="$saved_LIBS" AC_DEFINE([HAVE_DBUS], 1, [Have D-Bus.]) @@ -1273,6 +1273,16 @@ AC_SUBST(OPENSSL_LIBS) AC_SUBST(HAVE_OPENSSL) AM_CONDITIONAL([HAVE_OPENSSL], [test "x$HAVE_OPENSSL" = x1]) +#### FFTW (optional) #### +AC_ARG_WITH( + [fftw], + AS_HELP_STRING([--without-fftw], [Omit FFTW-using modules (equalizer)])) + +if test "x${with_fftw}" != "xno"; then + PKG_CHECK_MODULES([FFTW], [fftw3f], [HAVE_FFTW=1], [HAVE_FFTW=0]) +fi +AM_CONDITIONAL([HAVE_FFTW], [test "x$HAVE_FFTW" = "x1"]) + ### Build and Install man pages ### AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages],[Disable building and installation of man pages]), diff --git a/po/POTFILES.in b/po/POTFILES.in index a6172442..0bf70873 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -192,3 +192,5 @@ src/modules/alsa/alsa-source.c src/modules/alsa/module-alsa-card.c src/modules/bluetooth/module-bluetooth-device.c src/modules/reserve-wrap.c +src/modules/module-rygel-media-server.c +src/modules/alsa/alsa-mixer.c @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.as\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-08 21:04+0530\n" "Last-Translator: Amitakhya Phukan <aphukan@fedoraproject.org>\n" "Language-Team: Assamese\n" @@ -179,181 +179,181 @@ msgstr "এই স্থাপত্যত প্ৰণালী ব্যাপ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) বিফল: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "আদেশ শাৰী বিশ্লেষণ কৰিবলৈ বিফল ।" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ডেমন নাই চলা" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "PID %u ৰূপে ডেমন চলিছে" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ডেমন kill কৰিবলৈ ব্যৰ্থ: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "" "root পৰিচয়ে এই প্ৰোগ্ৰাম সঞ্চালিত হোৱা উচিত নহয় (ন'হ'লে --system উল্লিখিত হয়) ।" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Root-ৰ অধিকাৰ আৱশ্যক ।" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "প্ৰণালী চানেকিৰ ক্ষেত্ৰত --start সমৰ্থিত নহয় ।" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "প্ৰণালী মোডত চলিছে, কিন্তু --disallow-exit নিৰ্ধাৰিত নহয়!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "প্ৰণালী মোডত চলিছে, কিন্তু --disallow-module-loading নিৰ্ধাৰিত নহয়!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "প্ৰণালী মোডত চলিছে, SHM মোড বলপূৰ্বক নিষ্ক্ৰিয় কৰা হৈছে!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "প্ৰণালী মোডত চলিছে, কাম নকৰা সময়ৰ পৰা প্ৰস্থান কৰা বলপূৰ্বক নিষ্ক্ৰিয় কৰা হৈছে!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio প্ৰাপ্ত কৰিবলৈ ব্যৰ্থ ।" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe বিফল: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() বিফল: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() বিফল: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ডেমন আৰম্ভ কৰিবলৈ বিফল ।" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "সফলতাৰে ডেমন আৰম্ভ কৰা হৈছে ।" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "এইটো PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "সঙ্কলনৰ গৃহস্থ: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "সঙ্কলনৰ CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "গৃহস্থত চলোৱা হৈছে: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPU পোৱা গৈছে ।" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "পেজৰ মাপ %lu bytes" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind সমৰ্থনৰ সৈতে সঙ্কলন কৰা হৈছে: হয়" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind সমৰ্থনৰ সৈতে সঙ্কলন কৰা হৈছে: নহয়" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind মোডত চলিছে: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimized build: হয়" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimized build: নহয়" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG ব্যাখ্যা কৰা হৈছে, সকলো asserts নিষ্ক্ৰিয় কৰা হৈছে ।" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH ব্যাখ্যা কৰা হৈছে, অকল fast path asserts নিষ্ক্ৰিয় কৰা হৈছে ।" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "সকলো asserts সক্ৰিয় কৰা হৈছে ।" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "যন্ত্ৰ ID প্ৰাপ্ত কৰিবলৈ ব্যৰ্থ" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "যন্ত্ৰ ID হ'ল %s ।" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "সেশান ID হল %s।" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "ৰান-টাইম পঞ্জিকা %s ব্যৱহাৰ কৰা হৈছে ।" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "অৱস্থাসূচক পঞ্জিকা %s ব্যৱহাৰ কৰা হৈছে ।" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "মডিউল ডিরেক্টরি %s ব্যবহার করা হচ্ছে।" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "প্ৰণালী মোডত চলিছে: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -367,15 +367,15 @@ msgstr "" "সিস্টেম মোডে ব্যবহারের সমস্যা সম্পর্কে জানতে হলে http://pulseaudio.org/wiki/" "WhatIsWrongWithSystemMode দেখুন।" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() ব্যৰ্থ ।" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "নতুন high-resolution timers পোৱা হয়! অভিনন্দন!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -383,28 +383,28 @@ msgstr "" "শ্ৰীমান, আপোনাৰ কাৰ্ণেল পূৰণি! high-resolution timer সক্ৰিয় থকা Linux ক আজি " "উপদেশ দিয়া হয়!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() ব্যৰ্থ ।" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ডেমন আৰম্ভ কৰিবলৈ ব্যৰ্থ ।" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "তুলি লোৱা মডিউল নোহোৱাকে ডেমন আৰম্ভ কৰা হৈছে, কোনো কাম সঞ্চালন কৰা সম্ভৱ নহয় ।" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ডেমন আৰম্ভ কৰা সম্পূৰ্ণ ।" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ডেমন বন্ধ কৰাৰ প্ৰক্ৰিয়া আৰম্ভ কৰা হৈছে ।" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ডেমন বন্ধ কৰা হৈছে ।" @@ -2333,6 +2333,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "বন্ধ" @@ -2351,3 +2352,220 @@ msgstr "Telephony Duplex (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio ধ্বনি সেৱক" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "আভ্যন্তৰীণ অ'ডিঅ'" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +msgid "Analog Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "স্টিৰিও" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "ছাৰাউণ্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "ছাৰাউণ্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "ছাৰাউণ্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "ছাৰাউণ্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "ছাৰাউণ্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "ছাৰাউণ্ড ৫.০" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "ছাৰাউণ্ড ৫.১" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "ছাৰাউণ্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "ছাৰাউণ্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "ছাৰাউণ্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "ছাৰাউণ্ড ৭.১" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" diff --git a/po/bn_IN.po b/po/bn_IN.po index 22ddfb9f..45adef16 100644 --- a/po/bn_IN.po +++ b/po/bn_IN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.bn_IN\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-10 17:08+0530\n" "Last-Translator: Runa Bhattacharjee <runab@redhat.com>\n" "Language-Team: Bengali INDIA <anubad@lists.ankur.org.in>\n" @@ -182,183 +182,183 @@ msgstr "এই প্ল্যাটফর্মে, সিস্টেমব্ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) বিফল: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "কমান্ড-লাইন পার্স করতে ব্যর্থ।" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ডেমন চলছে না" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "PID %u রূপে ডেমন চলছে" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ডেমন kill করতে ব্যর্থ: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "" "root পরিচয়ে এই প্রোগ্রামটি সঞ্চালিত হওয়া উচিত নয় (যদি না --system উল্লিখিত হয়)।" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Root-র অধিকার আবশ্যক।" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "সিস্টেম ইনস্ট্যান্সের ক্ষেত্রে --start সমর্থিত নয়।" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "সিস্টেম মোডে চলছে, কিন্তু --disallow-exit নির্ধারিত হয়নি!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "সিস্টেম মোডে চলছে, কিন্তু --disallow-module-loading নির্ধারিত হয়নি!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "সিস্টেম মোডে চলছে, SHM মোড বলপূর্বক নিষ্ক্রিয় করা হচ্ছে!" # http://linux.die.net/man/1/pulseaudio এখানে রেফারেন্স পাওয়া যাবে -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "সিস্টেম মোডে চলছে, কর্মহীন অবস্থার জন্য ধার্য সময়সীমা পূর্তী পরে প্রস্থানের ব্যবস্থা " "বলপূর্বক নিষ্ক্রিয় করা হচ্ছে!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio প্রাপ্ত করতে ব্যর্থ।" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "পাইপ বিফল: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() বিফল: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() বিফল: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ডেমন আরম্ভ করতে বিফল।" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "সাফল্যের সাথে ডেমন আরম্ভ করা হয়েছে।" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "এটি PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "কম্পাইলেশনের হোস্ট: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "কম্পাইলশনের CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "চিহ্নিত হোস্টে চলছে: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPU পাওয়া গিয়েছে।" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "পেজের মাপ %lu বাইট" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind সমর্থন সহ কম্পাইল করা হয়েছে: হ্যাঁ" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind সমর্থন সহ কম্পাইল করা হয়েছে: না" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind মোডে চলছে: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "সর্বাপেক্ষ উত্তম বিল্ড: হ্যাঁ" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "সর্বাপেক্ষ উত্তম বিল্ড: না" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG ব্যাখ্যা করা হয়েছে, সকল অ্যাসার্ট নিষ্ক্রিয় করা হয়েছে।" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH ব্যাখ্যা করা হয়েছে, শুধুমাত্র ফাস্ট পাথ অ্যাসার্ট নিষ্ক্রিয় করা হয়েছে।" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "সকল অ্যাসার্ট সক্রিয় করা হয়েছে।" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "মেশিন ID প্রাপ্ত করতে ব্যর্থ" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "মেশিন ID হল %s।" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "সেশান ID হল %s।" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "রান-টাইম ডিরেক্টরি %s ব্যবহার করা হচ্ছে।" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "অবস্থাসূচক ডিরেক্টরি %s ব্যবহার করা হচ্ছে।" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "মডিউল ডিরেক্টরি %s ব্যবহার করা হচ্ছে।" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "সিস্টেম মোডে চলছে: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -372,42 +372,42 @@ msgstr "" "সিস্টেম মোডে ব্যবহারের সমস্যা সম্পর্কে জানতে হলে http://pulseaudio.org/wiki/" "WhatIsWrongWithSystemMode দেখুন।" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() ব্যর্থ।" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "উচ্চ-রেসোলিউশনের নতুন টাইমার উপলব্ধ রয়েছে! পরীক্ষা করে দেখুন!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "উচ্চ-রেসোলিউশনের নতুন টাইমার সহ Linux সক্রিয় করা বাঞ্ছনীয়!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() ব্যর্থ।" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ডেমন আরম্ভ করতে ব্যর্থ।" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "লোড করা মডিউল বিনা ডেমন আরম্ভ করা হয়েছে এবং কোনো কর্ম সঞ্চালন করা সম্ভব নয়।" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ডেমন আরম্ভ করা হয়েছে।" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ডেমন বন্ধ করার প্রক্রিয়া আরম্ভ করা হয়েছে।" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ডেমন বন্ধ করা হয়েছে।" @@ -2355,6 +2355,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "বন্ধ" @@ -2373,3 +2374,221 @@ msgstr "টেলিফোনি ডুপ্লে (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio শব্দের সার্ভার" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "অভ্যন্তরীণ অডিও" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Null ফলাফল" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "স্টিরিও" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "সারাউন্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "সারাউন্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "সারাউন্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "সারাউন্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "সারাউন্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "সারাউন্ড ৫.০" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "সারাউন্ড ৫.১" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "সারাউন্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "সারাউন্ড ৪.১" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "সারাউন্ড ৪.০" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "সারাউন্ড ৭.১" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -24,7 +24,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-12 11:40+0100\n" "Last-Translator: Josep Torné Llavall <josep.torne@gmail.com>\n" "Language-Team: Catalan <fedora@softcatala.net>\n" @@ -197,25 +197,25 @@ msgstr "El mode de sistema global no és compatible amb aquesta plataforma." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "S'ha produït un error en setrlimit(%s, (%u, %u)): %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "No s'ha pogut interpretar la línia d'ordres." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "El dimoni no s'està executant" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "El dimoni s'està executant amb PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "S'ha produït un error en matar el dimoni: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -223,163 +223,163 @@ msgstr "" "No és necessari executar aquesta aplicació com a root (excepte si " "s'especifica --system)" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Es requereixen privilegis de root." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "La opció --start no està suportada per a instàncies de sistema." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" "S'està executant en mode sistema, però no s'ha especificat l'opció --" "disallow-exit." -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "S'està executant en mode sistema, però no s'ha especificat l'opció --" "disallow-module-loading." -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" "S'està executant en mode sistema, es deshabilitarà el mode SHM forçosament." -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "S'està executant en mode sistema, la sortida per temps d'inactivitat es " "deshabilita." -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "S'ha produït un error en adquirir stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "Ha fallat la canonada: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "Ha fallat fork(): %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "Ha fallat read(): %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "S'ha produït un error en iniciar el dimoni." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "S'ha iniciat el dimoni." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Aquest és el PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Host de compilació: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS de compilació: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "S'està executant en el host: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "S'han trobat %u CPU's" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "La mida de pàgina és de %lu bytes." -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Compilat amb suport per a Valgrind: sí" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Compilat amb suport per a Valgrind: no" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "S'està executant amb el mode valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Construcció optimitzada: sí" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Construcció optmitzada: no" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG està definit, s'han desactivat totes les assercions." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" "FASTPATH està definit, només s'ha deshabilitat les assercions de camí ràpid." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "S'han habilitat totes les assercions." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "No s'ha pogut obtenir l'ID de la màquina" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "L'ID de la màquina és %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "L'ID de la sessió és %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "S'està utilitzant el directori d'execució %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "S'està utilitzant el directori d'estat %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "S'està utilitzant el directori dels móduls %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "S'està executant en mode sistema: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -395,15 +395,15 @@ msgstr "" "Si us plau, llegiu http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode per " "a una explicació de per què el mode sistema sol ser una mala idea." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "S'ha produït un error en pa_pid_file_create()." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Estan disponibles els temporitzadors frescos d'alta resolució." -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -411,27 +411,27 @@ msgstr "" "Es recomana la utilització d'un nucli amb els temporitzadors d'alta " "resolució habilitats." -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "S'ha produït un error en pa_core_new()." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "S'ha produït un error en inicialitzar el dimoni." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "El dimoni s'ha iniciat sense cap mòdul carregat, no funcionarà." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "S'ha completat la inicialització del dimoni." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "S'ha iniciat l'aturada del dimoni." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "S'ha aturat el dimoni." @@ -2391,6 +2391,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Inactiu" @@ -2410,6 +2411,231 @@ msgstr "Dúplex de telefonia (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Servidor de so PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Entrada %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Entrada %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Audio intern" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Estèreo analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Sortida nul·la" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Estèreo analògic" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Envolvent analògic 4.1 " + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Envolvent analògic 4.0 " + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Envolvent analògic 4.1 " + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Envolvent analògic 4.0 " + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Envolvent analògic 4.1 " + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Envolvent analògic 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Envolvent analògic 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Envolvent analògic 4.0 " + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Envolvent analògic 4.1 " + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Envolvent analògic 4.0 " + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Envolvent analògic 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Estèreo digital (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Envolvent digital 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Envolvent digital 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Envolvent digital 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Estèreo digital (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Mono analògic" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Estèreo analògic" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Estèreo digital (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Nom del client invàlid '%s'\n" @@ -2553,39 +2779,6 @@ msgstr "Servidor de so PulseAudio" #~ msgid "time_new() failed.\n" #~ msgstr "Ha fallat el time_new().\n" -#~ msgid "Analog Mono" -#~ msgstr "Mono analògic" - -#~ msgid "Analog Stereo" -#~ msgstr "Estèreo analògic" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Estèreo digital (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Estèreo digital (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Envolvent analògic 4.0 " - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Envolvent digital 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Envolvent analògic 4.1 " - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Envolvent analògic 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Envolvent analògic 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Envolvent digital 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Envolvent analògic 7.1" - #~ msgid "Stream successfully created\n" #~ msgstr "Flux creat amb èxit\n" @@ -2684,9 +2877,6 @@ msgstr "Servidor de so PulseAudio" #~ msgid "Output %s + Input %s" #~ msgstr "Sortida %s + Entrada %s" -#~ msgid "Input %s" -#~ msgstr "Entrada %s" - #~ msgid "" #~ "Called SUID root and real-time/high-priority scheduling was requested in " #~ "the configuration. However, we lack the necessary priviliges:\n" @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-09 02:43+0100\n" "Last-Translator: Petr Kovar <pknbe@volny.cz>\n" "Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n" @@ -181,25 +181,25 @@ msgstr "Režim celého systému není na této platformě podporován." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) selhalo: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Nezdařila se analýza příkazového řádku." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Démon neběží" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Démon běží jako PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Zabití démona se nezdařilo: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -207,155 +207,155 @@ msgstr "" "Tento program není určen ke spuštění pod superuživatelem (není-li zadáno --" "system)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Jsou vyžadována oprávnění superuživatele." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start nepodporováno u systémových instancí." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "Běží v systémovém režimu, ale nenastaveno --disallow-exit!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "Běží v systémovém režimu, ale nenastaveno --disallow-module-loading!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Běží v systémovém režimu, vynuceně se vypíná režim SHM!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "Běží v systémovém režimu, vynuceně se vypíná čas nečinnosti ukončení!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Nezdařilo se získání stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe selhalo: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() selhalo: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() selhalo: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Spuštění démona selhalo." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Spuštění démona bylo úspěšné." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Toto je PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Překladový počítač: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Překladové CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Běží na počítači: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Nalezen následující počet CPU: %u." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Velikost stránky je %lu bajtů" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Přeloženo s podporou Valgrind: ano" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Přeloženo s podporou Valgrind: ne" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Běží v režimu valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimalizované sestavení: ano" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimalizované sestavení: ne" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definováno, všechny výrazy zakázány." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH definováno, zakázány pouze výrazy rychlých cest." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Všechny výrazy povoleny." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Nezdařilo se získání ID počítače" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "ID počítače je %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "ID sezení je %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Používán běhový adresář %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Používán stavový adresář %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Používán adresář modulů %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Běží v systémovém režimu: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -371,16 +371,16 @@ msgstr "" "Vysvětlení, proč je systémový režim obvykle velmi špatný nápad, si můžete " "přečíst na http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() selhalo." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" "Jsou dostupné výtečné časovače o vysokém rozlišení. Tak s chutí do toho!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -388,27 +388,27 @@ msgstr "" "Sorry, vole, kernel error! Tip šéfkuchaře na dnešní den zní: Linux se " "zapnutými časovači o vysokém rozlišení." -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() selhalo." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Selhalo spuštění démona." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Spuštění démona bez jakýchkoliv nahraných modulů, běh bude odmítnut." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Spuštění démona dokončeno." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Vypínání démona spuštěno." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Démon ukončen." @@ -2335,6 +2335,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Vypnuto" @@ -2354,6 +2355,231 @@ msgstr "Duplexní telefonie (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Zvukový server PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Vstup %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Vstup %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Vnitřní zvukový systém" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Analogové stereo" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Výstup %s" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Analogové stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Analogový Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Analogový Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Analogový Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Analogový Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Analogový Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Analogový Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Analogový Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Analogový Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Analogový Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Analogový Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Analogový Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Digitální stereo (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Digitální Surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Digitální Surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Digitální Surround 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Digitální stereo (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Analogové mono" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Analogové stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Digitální stereo (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Neplatný název klienta \"%s\"\n" @@ -2493,45 +2719,9 @@ msgstr "Zvukový server PulseAudio" #~ msgid "time_new() failed.\n" #~ msgstr "time_new() selhalo.\n" -#~ msgid "Analog Mono" -#~ msgstr "Analogové mono" - -#~ msgid "Analog Stereo" -#~ msgstr "Analogové stereo" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Digitální stereo (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Digitální stereo (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Analogový Surround 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Digitální Surround 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Analogový Surround 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Analogový Surround 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Analogový Surround 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Digitální Surround 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Analogový Surround 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Výstup %s + vstup %s" -#~ msgid "Input %s" -#~ msgstr "Vstup %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Proud úspěšně vytvořen\n" @@ -9,9 +9,9 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-14 10:19+0100\n" -"Last-Translator: Fabian Affolter <fab@fedoraproject.org>\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-28 16:49+0100\n" +"Last-Translator: Joerg (kital) Simon <jsimon@fedoraproject.org>\n" "Language-Team: German <fedora-trans-de@redhat.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -181,25 +181,25 @@ msgstr "System-Modus auf dieser Plattform nicht unterstützt." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) fehlgeschlagen: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Parsen der Kommandzeile fehlgeschlagen." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Daemon läuft nicht" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Daemon läuft als PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Konnte Prozess nicht abbrechen: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -207,155 +207,155 @@ msgstr "" "Dieses Programm sollte ohne die Option --system nicht als Administrator " "ausgeführt werden." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Root-Berechtigungen benötigt." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start nicht unterstützt für System-Instanzen." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "System-Modus aktiv, jeodch --disallow-exit nicht gesetzt!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "System-Modus aktiv, jedoch --disallow-module-loading nicht gesetzt!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "System-Modus aktiv, SHM-Modus gezwungenermaßen deaktiviert!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "System-Modus aktiv, Exit-Idle-Time gezwungenermaßen deaktiviert!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Reservieren von STDIO fehlgeschlagen." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe fehlgeschlagen: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() fehlgeschlagen: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() fehlgeschlagen: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Start des Daemons fehlgeschlagen." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Start des Daemons erfolgreich." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Dies ist PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Kompilier-Host: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Kompilier-CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Laufe auf Host: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs gefunden." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Seitengröße ist %lu Bytes." -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Kompiliere mit Valgrind-Unterstützung: ja" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Kompiliere mit Valgrind-Unterstützung: nein" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Läuft im Valgrind-Modus: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimiertes Build: ja" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimiertes Build: nein" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definiert, alle Ansprüche deaktiviert." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH definiert, nur fast-path-Ansprüche deaktiviert." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Alle Ansprüche aktiviert." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Beziehen der Maschinen-ID fehlgeschlagen" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "System- ID ist %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "System- ID ist %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Nutze Laufzeit-Verzeichnis %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Nutze Zustands-Verzeichnis %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Modul-Verzeichnis %s benutzen." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Laufe im System-Modus: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -364,42 +364,47 @@ msgid "" "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an " "explanation why system mode is usually a bad idea." msgstr "" +"OK, nun wird PA im System Mode betrieben. Vorsicht, dies sollte man nicht " +"tun.\n" +"Bei Nichtbeachtung, selber Schuld wenn Dinge nicht funktionieren.\n" +"Für eine Erklärung warum System Mode eine schlechte Idee ist, bitte http://" +"pulseaudio.org/wiki/WhatIsWrongWithSystemMode lesen" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() fehlgeschlagen." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Neue hochauslösende Timer verfügbar! Guten Appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "Der Chefkoch empfiehlt: Linux mit aktivierten hochauslösenden Timern!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() fehlgeschlagen." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Konnte Daemon nicht initialisieren." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Daemon verweigert Ausführung, da keine Module geladen." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Start des Daemons abgeschlossen." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Herunterfahren des Daemon gestartet." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Daemon beendet." @@ -2298,6 +2303,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Aus" @@ -2317,6 +2323,231 @@ msgstr "Telephony Duplex (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "PulseAudio Sound Server" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Eingang %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Eingang %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Internes Audio" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Analog Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Ausgang %s" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Analog Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Analog Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Analog Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Analog Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Digital Stereo (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Digital Surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Digital Surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Digital Surround 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Digital Stereo (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Analog Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Digital Stereo (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Ungültiger Client-Name '%s'\n" @@ -2452,45 +2683,9 @@ msgstr "PulseAudio Sound Server" #~ msgid "time_new() failed.\n" #~ msgstr "time_new() fehlgeschlagen.\n" -#~ msgid "Analog Mono" -#~ msgstr "Analog Mono" - -#~ msgid "Analog Stereo" -#~ msgstr "Analog Stereo" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Digital Stereo (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Digital Stereo (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Analog Surround 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Digital Surround 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Analog Surround 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Analog Surround 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Analog Surround 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Digital Surround 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Analog Surround 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Ausgabe %s + Eingabe %s" -#~ msgid "Input %s" -#~ msgstr "Eingang %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Stream erfolgreich erzeugt\n" diff --git a/po/de_CH.po b/po/de_CH.po index bfa2c5bc..e239deb0 100644 --- a/po/de_CH.po +++ b/po/de_CH.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-14 10:22+0100\n" "Last-Translator: Fabian Affolter <fab@fedoraproject.org>\n" "Language-Team: German <fedora-trans-de@redhat.com>\n" @@ -181,25 +181,25 @@ msgstr "System-Modus auf dieser Plattform nicht unterstützt." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) fehlgeschlagen: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Parsen der Kommandzeile fehlgeschlagen." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Daemon läuft nicht" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Daemon läuft als PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Konnte Prozess nicht abbrechen: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -207,155 +207,155 @@ msgstr "" "Dieses Programm sollte ohne die Option --system nicht als Administrator " "ausgeführt werden." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Root-Berechtigungen benötigt." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start nicht unterstützt für System-Instanzen." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "System-Modus aktiv, jeodch --disallow-exit nicht gesetzt!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "System-Modus aktiv, jedoch --disallow-module-loading nicht gesetzt!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "System-Modus aktiv, SHM-Modus gezwungenermaßen deaktiviert!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "System-Modus aktiv, Exit-Idle-Time gezwungenermaßen deaktiviert!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Reservieren von STDIO fehlgeschlagen." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe fehlgeschlagen: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() fehlgeschlagen: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() fehlgeschlagen: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Start des Daemons fehlgeschlagen." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Start des Daemons erfolgreich." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Dies ist PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Kompilier-Host: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Kompilier-CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Laufe auf Host: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs gefunden." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Seitengröße ist %lu Bytes." -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Kompiliere mit Valgrind-Unterstützung: ja" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Kompiliere mit Valgrind-Unterstützung: nein" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Läuft im Valgrind-Modus: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimiertes Build: ja" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimiertes Build: nein" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definiert, alle Ansprüche deaktiviert." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH definiert, nur fast-path-Ansprüche deaktiviert." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Alle Ansprüche aktiviert." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Beziehen der Maschinen-ID fehlgeschlagen" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "System- ID ist %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "System- ID ist %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Nutze Laufzeit-Verzeichnis %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Nutze Zustands-Verzeichnis %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Modul-Verzeichnis %s benutzen." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Laufe im System-Modus: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -365,41 +365,41 @@ msgid "" "explanation why system mode is usually a bad idea." msgstr "" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() fehlgeschlagen." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Neue hochauslösende Timer verfügbar! Guten Appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "Der Chefkoch empfiehlt: Linux mit aktivierten hochauslösenden Timern!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() fehlgeschlagen." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Konnte Daemon nicht initialisieren." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Daemon verweigert Ausführung, da keine Module geladen." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Start des Daemons abgeschlossen." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Herunterfahren des Daemon gestartet." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Daemon beendet." @@ -2298,6 +2298,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Aus" @@ -2317,6 +2318,231 @@ msgstr "Telephony Duplex (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "PulseAudio Sound Server" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Eingang %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Eingang %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Internes Audio" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Analog Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Ausgang %s" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Analog Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Analog Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Analog Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Analog Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Digital Stereo (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Digital Surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Digital Surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Digital Surround 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Digital Stereo (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Analog Mono" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Analog Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Digital Stereo (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Ungültiger Client-Name '%s'\n" @@ -2452,45 +2678,9 @@ msgstr "PulseAudio Sound Server" #~ msgid "time_new() failed.\n" #~ msgstr "time_new() fehlgeschlagen.\n" -#~ msgid "Analog Mono" -#~ msgstr "Analog Mono" - -#~ msgid "Analog Stereo" -#~ msgstr "Analog Stereo" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Digital Stereo (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Digital Stereo (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Analog Surround 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Digital Surround 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Analog Surround 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Analog Surround 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Analog Surround 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Digital Surround 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Analog Surround 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Ausgabe %s + Eingabe %s" -#~ msgid "Input %s" -#~ msgstr "Eingang %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Stream erfolgreich erzeugt\n" @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: el\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2008-08-22 19:40+0300\n" "Last-Translator: Dimitris Glezos <dimitris@glezos.com>\n" "Language-Team: Greek <fedora-trans-el@redhat.com>\n" @@ -164,179 +164,179 @@ msgstr "" msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Αυτό είναι το PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -346,15 +346,15 @@ msgid "" "explanation why system mode is usually a bad idea." msgstr "" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -362,27 +362,27 @@ msgstr "" "Δικέ μου, ο πυρήνας σου είναι για τα μπάζα! Η πρόταση του σεφ σήμερα είναι " "Linux με ενεργοποιημένα τα high-resolution timers!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "" @@ -2017,6 +2017,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "" @@ -2035,3 +2036,207 @@ msgstr "" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +msgid "Internal Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +msgid "Analog Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, c-format +msgid "%s+%s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, c-format +msgid "%s / %s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +msgid "Analog Surround 2.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +msgid "Analog Surround 3.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +msgid "Analog Surround 3.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +msgid "Analog Surround 6.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +msgid "Analog Surround 6.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +msgid "Analog Surround 7.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PulseAudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-11 08:40-0300\n" "Last-Translator: Domingo Becker <domingobecker@gmail.com>\n" "Language-Team: Fedora Spanish <fedora-trans-es@redhat.com>\n" @@ -184,25 +184,25 @@ msgstr "El modo a nivel de sistema no es soportado en esta plataforma." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) falló: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Falló al analizar la línea de comando." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "El demonio no está funcionando" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "El demonio está funcionando como PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "No se ha podido detener el demonio: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -210,160 +210,160 @@ msgstr "" "Este programa no tiene por qué ser ejecutado como root (a menos que --system " "sea especificado)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Se necesitan privilegios de root." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start no está soportado para las instancias del sistema." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" "Ejecutándose en modo de sistema, ¡pero no se ha configurado --disallow-exit! " -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Ejecutándose en modo de sistema, ¡pero no se ha configurado --disallow-" "module-loading!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" "Ejecutándose en modo de sistema, ¡desactivando forzadamente el modo SHM!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Ejecutándose en modo de sistema, ¡desactivando forzadamente exit idle time!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Fallo al intentar adquirir stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "Falló el pipe: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "Falló el fork(): %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "Falló la operación read(): %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Falló el inicio del demonio. " -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "El demonio se inició exitosamente." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Esto es PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Host de compilación: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Compilación CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Ejecutándose en el host: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Se encontraron %u CPUs." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "El tamaño de la página es de %lu bytes" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Soporte para compilar con Valgrind: si" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Soporte para compilar con Valgrind: no" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Ejecutándose en modo valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Build optimizado: si" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Build optimizado: no" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definido, todos los chequeos deshabilitados." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH definido, sólo se deshabilitan los chequeos fast path." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Todos los chequeos habilitados." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Fallo al intentar obtener el ID de la máquina" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "El ID de la máquina es %s" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "El ID de la sesión es %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Utilizando directorio de tiempo de ejecución %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Utilizando directorio de estado %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Utilizando directorio de módulos %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Ejecutándose en modo de sistema: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -380,17 +380,17 @@ msgstr "" "obtener una explicación acerca de por qué es una mala idea utilizar el modo " "sistema." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "Ha fallado pa_pid_file_create()." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" "¡Existen cronómetros de alta resolución fresquitos y disponibles! ¡Bon " "appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -398,29 +398,29 @@ msgstr "" "¡Amigo, su kernel deja mucho que desear! ¡El plato que hoy recomienda el " "chef es Linux con cronómetros de alta resolución activados! " -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "Falló pa_core_new()." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Fallo al intentar iniciar el demonio." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "El demonio se ha iniciado sin ningún módulo cargado, y por ello se niega a " "funcionar." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "El demonio se inició completamente." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Comienza a apagarse el demonio." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "El demonio se ha apagado." @@ -2376,6 +2376,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Apagado" @@ -2395,6 +2396,231 @@ msgstr "Telefonía Duplex (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Servidor de Sonido PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Entrada %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Entrada %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Audio Interno" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Estéreo Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Salida Nula" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Estéreo Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Análogo Envolvente 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Análogo Envolvente 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Análogo Envolvente 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Análogo Envolvente 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Análogo Envolvente 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Análogo Envolvente 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Análogo Envolvente 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Análogo Envolvente 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Análogo Envolvente 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Análogo Envolvente 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Análogo Envolvénte 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Estéreo Digital (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Digital Envolvente 4.0 (IEC9588/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Digital Envolvente 4.0 (IEC9588/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Digital Envolvente 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Estéreo Digital (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Estéreo Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Estéreo Digital (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Nombre de cliente inválido '%s'\n" @@ -2538,45 +2764,9 @@ msgstr "Servidor de Sonido PulseAudio" #~ msgid "time_new() failed.\n" #~ msgstr "time_new() falló.\n" -#~ msgid "Analog Mono" -#~ msgstr "Mono Analógico" - -#~ msgid "Analog Stereo" -#~ msgstr "Estéreo Analógico" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Estéreo Digital (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Estéreo Digital (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Análogo Envolvente 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Digital Envolvente 4.0 (IEC9588/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Análogo Envolvente 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Análogo Envolvente 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Análogo Envolvente 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Digital Envolvente 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Análogo Envolvénte 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Salida %s + Entrada %s" -#~ msgid "Input %s" -#~ msgstr "Entrada %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Se ha creado el flujo exitosamente\n" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: git trunk\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-15 13:24+0300\n" "Last-Translator: Ville-Pekka Vainio <vpivaini@cs.helsinki.fi>\n" "Language-Team: Finnish <laatu@lokalisointi.org>\n" @@ -181,25 +181,25 @@ msgstr "Järjestelmänlaajuista tilaa ei tueta tällä alustalla." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) epäonnistui: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Komentorivin jäsentäminen epäonnistui." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Taustaprosessi ei ole käynnissä" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Taustaprosessi käynnissä prosessitunnisteella %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Taustaprosessin lopettaminen epäonnistui: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -207,161 +207,161 @@ msgstr "" "Tätä ohjelmaa ei ole tarkoitettu suoritettavaksi pääkäyttäjänä (ellei --" "system ole määritelty)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Pääkäyttäjän (root) oikeudet vaaditaan." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start-valitsinta ei tueta järjestelmätilassa." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" "Suoritetaan järjestelmätilassa, mutta --disallow-exit ei ole asetettuna!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Suoritetaan järjestelmätilassa, mutta -disallow-module-loading ei ole " "asetettuna!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" "Suoritetaan järjestelmätilassa, otetaan SHM-tila pakotetusti pois käytöstä." -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Suoritetaan järjestelmätilassa, otetaan poistumisen joutenoloaika " "pakotetusti pois käytöstä." -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio:n saaminen epäonnistui." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "putki epäonnistui: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() epäonnistui: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() epäonnistui: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Taustaprosessin käynnistys epäonnistui." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Taustaprosessin käynnistys onnistui." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Tämä on PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Käännöksen isäntäkone: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Käännösaikaiset C-liput (CFLAGS): %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Käynnissä isäntäkoneella: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Löydettiin %u CPU:ta." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Sivun koko on %lu tavua" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Käännetty Valgrind-tuella: kyllä" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Käännetty Valgrind-tuella: ei" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Käynnissä valgrind-tilassa: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimoitu rakentaminen: kyllä" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimoitu rakentaminen: ei" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG on määritelty, kaikki assertit ovat poissa käytöstä." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH on määritelty, vain fast path -assertit ovat poissa käytöstä." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Kaikki assertit ovat käytössä." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Konetunnisteen nouto epäonnistui" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "Konetunniste on %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "Istunnon tunniste on %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Käytetään ajonaikaista hakemistoa %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Käytetään tilahakemistoa %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Käytetään moduulihakemistoa %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Suoritetaan järjestelmätilassa: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -375,15 +375,15 @@ msgstr "" "Lisätietoja siitä, miksi järjestelmätilan käyttäminen on yleensä huono " "ajatus on osoitteessa http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() epäonnistui." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Korkean tarkkuuden ajastimet käytettävissä." -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -391,29 +391,29 @@ msgstr "" "Hei, ytimesi on kehno! Linux korkean tarkkuuden ajastimien tuella on hyvin " "suositeltava!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() epäonnistui." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Taustaprosessin alustus epäonnistui." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "Taustaprosessin käynnistys ilman ladattavia moduuleita, kieltäydytään " "toiminnasta." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Taustaprosessin käynnistys valmis." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Taustaprosessin sulkeminen käynnistetty." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Taustaprosessi lopetettu." @@ -2355,6 +2355,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Poissa" @@ -2374,6 +2375,231 @@ msgstr "" msgid "PulseAudio Sound Server" msgstr "PulseAudio-äänipalvelin" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Sisääntulo %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Sisääntulo %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Sisäinen äänentoisto" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Analoginen stereo" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Tyhjä ulostulo" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Analoginen stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Analoginen tilaääni 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Analoginen tilaääni 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Analoginen tilaääni 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Analoginen tilaääni 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Analoginen tilaääni 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Analoginen tilaääni 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Analoginen tilaääni 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Analoginen tilaääni 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Analoginen tilaääni 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Analoginen tilaääni 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Analoginen tilaääni 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Digitaalinen stereo (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Digitaalinen tilaääni 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Digitaalinen tilaääni 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Digitaalinen tilaääni 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Digitaalinen stereo (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Analoginen mono" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Analoginen stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Digitaalinen stereo (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Virheellinen asiakasohjelman nimi ”%s”\n" @@ -2513,45 +2739,9 @@ msgstr "PulseAudio-äänipalvelin" #~ msgid "time_new() failed.\n" #~ msgstr "time_new() epäonnistui.\n" -#~ msgid "Analog Mono" -#~ msgstr "Analoginen mono" - -#~ msgid "Analog Stereo" -#~ msgstr "Analoginen stereo" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Digitaalinen stereo (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Digitaalinen stereo (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Analoginen tilaääni 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Digitaalinen tilaääni 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Analoginen tilaääni 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Analoginen tilaääni 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Analoginen tilaääni 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Digitaalinen tilaääni 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Analoginen tilaääni 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Ulostulo %s + Sisääntulo %s" -#~ msgid "Input %s" -#~ msgstr "Sisääntulo %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Virran luonti onnistui\n" @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio trunk\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-04-26 17:22+0200\n" "Last-Translator: Corentin Perard <corentin.perard@gmail.com>\n" "Language-Team: French <fedora-trans-fr@redhat.com>\n" @@ -182,25 +182,25 @@ msgstr "Mode système étendu non pris en charge sur cette plateforme." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) a échoué : %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Échec lors de l'analyse de la ligne de commande" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Lé démon n'est pas lancé" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Le démon est lancé avec le PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Impossible de tuer le démon : %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -208,161 +208,161 @@ msgstr "" "Le programme n'est pas conçu pour être lancé en tant que root (sauf si --" "system est renseigné)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Les privilèges root sont nécessaires." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start n'est pas pris en charge pour les instances système." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" "Le démon s'exécute en mode système, mais --disallow-exit n'est pas défini." -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Le démon s'exécute en mode système, mais --disallow-module-loading n'est pas " "défini." -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Le démon s'exécute en mode système, désactivation forcée du mode SHM." -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Le démon s'exécute en mode système, désactivation forcée de la fermeture " "après délai d'inactivité." -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Échec lors de l'acquisition de stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "Échec du tube : %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "Échec de fork() : %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "Échec de read() : %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Échec lors du démarrage du démon." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Démarrage du démon réussi." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Pulseaudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Hôte de compilation : %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS de compilation : %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Exécution sur l'hôte : %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u processeurs trouvés." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "La taille de la page est de %lu octets" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Compilé avec la prise en charge Valgrind : oui" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Compilé avec la prise en charge Valgrind : non" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Exécution en mode valgrind : %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Construction optimisée : oui" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Construction optimisée : non" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG défini, tous les messages d'erreur sont désactivés." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" "FASTPATH défini, seuls les messages d'erreur fastpath ont été désactivés." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Tous les messages d'erreur sont activés." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Échec lors de l'obtention de l'ID de la machine" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "L'ID de la machine est %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, fuzzy, c-format msgid "Session ID is %s." msgstr "L'ID de la machine est %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Utilisation du répertoire d'exécution %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Utilisation du répertoire d'état %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, fuzzy, c-format msgid "Using modules directory %s." msgstr "Utilisation du répertoire d'exécution %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Exécution en mode système : %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -372,16 +372,16 @@ msgid "" "explanation why system mode is usually a bad idea." msgstr "" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "Échec de pa_pid_file_create()." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" "De nouvelles horloges à haute résolution sont disponibles ! Bon appétit !" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -389,27 +389,27 @@ msgstr "" "Eh mec, ton noyau il pue ! La recommandation d'aujourd'hui du patron est " "d'activer les horloges à haute résolution sur ton Linux." -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "Échec de pa_core_new()." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Échec lors de l'initialisation du démon" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Démarrage du démon sans aucun module chargé : refus de fonctionner." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Démarrage du démon effectué." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Fermeture du démon initiée." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Démon terminé." @@ -2416,6 +2416,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Éteint" @@ -2436,6 +2437,231 @@ msgstr "Telephonie en duplex (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Serveur de son PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Entrée %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Entrée %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Audio interne" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Stéréo analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Sortie %s" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, c-format +msgid "%s+%s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, c-format +msgid "%s / %s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Stéréo analogique" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Surround analogique 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Surround analogique 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Surround analogique 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Surround analogique 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Surround analogique 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Surround analogique 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Surround analogique 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Surround analogique 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Surround analogique 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Surround analogique 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Surround analogique 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Stéréo numérique (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Surround numérique 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Surround numérique 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Surround numérique 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Stéréo numérique (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Mono analogique" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Stéréo analogique" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Stéréo numérique (IEC958)" + #, fuzzy #~ msgid "Invalid client name '%s'\n" #~ msgstr "Plan des canaux invalide « %s »\n" @@ -2585,45 +2811,9 @@ msgstr "Serveur de son PulseAudio" #~ msgid "time_new() failed.\n" #~ msgstr "Échec de time_new().\n" -#~ msgid "Analog Mono" -#~ msgstr "Mono analogique" - -#~ msgid "Analog Stereo" -#~ msgstr "Stéréo analogique" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Stéréo numérique (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Stéréo numérique (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Surround analogique 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Surround numérique 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Surround analogique 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Surround analogique 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Surround analogique 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Surround numérique 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Surround analogique 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Sortie %s + Entrée %s" -#~ msgid "Input %s" -#~ msgstr "Entrée %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Création du flux réussie\n" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PulseAudio-up\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-11 13:02+0530\n" "Last-Translator: Sweta Kothari <swkothar@redhat.com>\n" "Language-Team: Gujarati\n" @@ -181,182 +181,182 @@ msgstr "આ પ્લેટફોર્મ પર બિનઆધારભૂત msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) નિષ્ફળ: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "આદેશ વાક્યને પદચ્છેદન કરવામાં નિષ્ફળ." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ડિમન ચાલી રહ્યુ નથી" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "PID %u તરીકે ડિમન ચાલી રહ્યુ છે" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ડિમનને મારવાનું નિષ્ફળ: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "" "આ પ્રક્રિયાને રુટ તરીકે ચલાવવા માટે વિચાર થયેલ નથી (નહિં તો --system એ સ્પષ્ટ થયેલ છે)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "રુટ અધિકારો જરૂરી છે." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start એ સિસ્ટમ ઉદાહરણો માટે આધારભૂત નથી." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "સિસ્ટમ સ્થિતિમાં ચાલી રહ્યુ છે, પરંતુ --disallow-exit સુયોજિત નથી!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "સિસ્ટમ સ્થિતિમાં ચાલી રહ્યુ છે, પરંતુ --disallow-module-loading એ સુયોજિત નથી!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "સિસ્ટમ સ્થિતિમાં ચાલી રહ્યુ છે, SHM સ્થિતિને દબાણપૂર્વક નિષ્ક્રિય કરી રહ્યા છે!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "સિસ્ટમ સ્થિતિમાં ચાલી રહ્યુ છે, બહાર નીકળવનાં નિષ્કાર્ય સમયને દબાણપૂર્વક નિષ્ક્રિય કરી " "રહ્યા છે!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio ને મેળવવામાં નિષ્ફળ." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "પાઇપ નિષ્ફળ: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() નિષ્ફળ: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() નિષ્ફળ: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ડિમન શરૂઆત નિષ્ફળ." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "ડિમન શરૂઆત કરવુ સફળ છે." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "આ PulseAudio %s છે" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "કમ્પાઇલેશન યજમાન: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "કમ્પાઇલેશન CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "યજમાન પર ચાલી રહ્યુ છે: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs શોધાયુ." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "પાનાંનુ માપ %lu બાઇટો છે" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind આધાર સાથે કમ્પાઇલ થયેલ છે: હા" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind આધાર સાથે કમ્પાઇલ થયેલ છે: ના" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind સ્થિતિમાં ચાલી રહ્યુ છે: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "શ્રેષ્ટ થયેલ બિલ્ડ: હા" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "શ્રેષ્ટ થયેલ બિલ્ડ: ના" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG વ્યાખ્યાયિત થયેલ છે, બધા હકો નિષ્ક્રિય થયેલ છે." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH વ્યાખ્યાયિત થયેલ છે, ફક્ત ઝડપી પાથનાં હકો નિષ્ક્રિય થયેલ છે." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "બધા હકો સક્રિય થયેલ છે." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "મશીન ID ને મેળવવામાં નિષ્ફળ" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "મશીન ID %s છે." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "સત્ર ID %s છે." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "રનટાઇમ ડિરેક્ટરી %s ને વાપરી રહ્યા છે." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "સ્થિતિ ડિરેક્ટરી %s ને વાપરી રહ્યા છે." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "ઇોડ્યુલોમ ડિરેક્ટરી %s ને વાપરી રહ્યા છે." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "સિસ્ટમ સ્થિતિમાં ચાલી રહ્યુ છે: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -371,15 +371,15 @@ msgstr "" "શા માટે સિસ્ટમ સ્થિતિ સામાન્ય રીતે ખરાબ વિચાર છે તે માટે વિગતવાર જાણકારી માટે મહેરબાની " "કરીને http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode આને વાંચો." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() નિષ્ફળ." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "તાજુ high-resolution ટાઇમરો ઉપલ્બધ છે! બોન એપેટાઇટ!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -387,27 +387,27 @@ msgstr "" "મિત્ર, તમારુ કર્નલમાં ગડબડ છે! રસોઇયાનું આજે ભલામણ એ સક્રિય થયેલ high-resolution " "ટાઇમરો સાથે Linux નું છે!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() નિષ્ફળ." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ડિમનને શરૂ કરવામાં નિષ્ફળ." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "કોઇપણ લોડ થયેલ મોડ્યુલો વગર ડિમનને શરૂ કરો, કામ કરવા માટે ફરી શરૂ કરી રહ્યા છે." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ડિમન પારંભ કરવાનું સમાપ્ત છે." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ડિમનને બંધ કરવાનું પ્રારંભ થયેલ છે." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ડિમનનો અંત આવેલ છે." @@ -2323,6 +2323,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "બંધ" @@ -2341,3 +2342,221 @@ msgstr "Telephony Duplex (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio સાઉન્ડ સર્વર" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "આંતરિક ઓડિયો" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "શૂન્ય આઉટપુટ" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "સ્ટેરિઓ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "સરાઉન્ડ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "સરાઉન્ડ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "સરાઉન્ડ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "સરાઉન્ડ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "સરાઉન્ડ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "સરાઉન્ડ 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "સરાઉન્ડ 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "સરાઉન્ડ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "સરાઉન્ડ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "સરાઉન્ડ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "સરાઉન્ડ 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-10 17:01+0530\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-21 16:29+0530\n" "Last-Translator: Rajesh Ranjan <rajesh672@gmail.com>\n" "Language-Team: Hindi <hindi.sf.net>\n" "MIME-Version: 1.0\n" @@ -21,6 +21,7 @@ msgstr "" "\n" "\n" "\n" +"\n" #: ../src/modules/alsa/alsa-util.c:858 ../src/pulsecore/sink.c:2629 #, c-format @@ -185,180 +186,180 @@ msgstr "इस प्लैटफॉर्म पर असमर्थित msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) विफल: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "कमांड लाइन विश्लेषण में विफल." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "डेमॉन नहीं कार्यशील" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "डेमॉन बतौर PID %u चल रहा है" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "डेमॉन हटाने में विफल: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "" "यह प्रोग्राम बतौर रूट चलाने के लिए इच्छित नहीं है (unless --system is specified)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "रूट अधिकार जरूरी." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start not supported for system instances." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "तंत्र मोड में चल रहा है, लेकिन --disallow-exit सेट नहीं!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "तंत्र मोड में चल रहा है, लेकिन --disallow-module-loading सेट नहीं!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "तंत्र मोड में चल रहा है, SHM मोड बाध्य रूप से निष्क्रिय!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "तंत्र मोड में चल रहा है, निकास निष्क्रिय समय बाध्य रूप से निष्क्रिय!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio पाने में विफल." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "पाइप विफल: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() विफल: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() विफल: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "डेमॉन आरंभ विफल." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "डेमॉन आरंभ सफल." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "यह पल्सऑडियो %s है." -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Compilation host: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Compilation CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "मेजबान पर चल रहा है: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPU पाया." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "पृष्ठ आकार %lu बाइट है." -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "वेलग्रिंड समर्थन से कंपाइल: हाँ" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "वेलग्रिंड समर्थन से कंपाइल: नहीं" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "वेलग्रिंड विधि में चल रहा है: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "अनुकूलित बिल्ड: हाँ" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "अनुकूलित बिल्ड: नहीं" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG परिभाषित, सभी निष्क्रिय." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH परिभाषित, केव तेज पथ एसर्ट निष्क्रिय." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "सभी एसर्ट सक्षम." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "मशीन ID पाने में विफल" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "मशीन ID %s है." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "सत्र ID %s है." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "रनटाइम निर्देशिका %s का प्रयोग कर रहा है." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "स्टेट निर्देशिका %s का प्रयोग कर रहा है." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "मॉड्यूल निर्देशिका %s का प्रयोग कर रहा है." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "तंत्र मोड में चल रहा है: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -372,42 +373,42 @@ msgstr "" "कृपया http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode को पढ़ें जानने के लिए " "कि क्यों तंत्र मोड एक बढ़िया विचार नहीं है." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() विफल." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "ताज़ा उच्च विभेदन टाइमर उपलब्ध! आनंद लें!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "" "आपका कर्नेल बुरी स्थिति में है! सलाह है कि उच्च विभेदन युक्त लिनक्स सक्रिय किया जाना चाहिए!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() विफल." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "डेमॉन आरंभ करने में विफल." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "बिना लोड मॉड्यूल के डेमॉन आरंभ, काम करने से अस्वीकार कर रहा है." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "डेमॉन आरंभन पूर्ण." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "डेमॉन बन्द किया जाना आरंभ." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "डेमॉन अवरोधित." @@ -1090,11 +1091,11 @@ msgstr "क्लाएंट विभाजित" #: ../src/pulse/error.c:68 msgid "Input/Output error" -msgstr "" +msgstr "इनपुट/आउटपुट त्रुटि" #: ../src/pulse/error.c:69 msgid "Device or resource busy" -msgstr "" +msgstr "युक्ति या संसाधन व्यस्त" #: ../src/pulse/sample.c:172 #, c-format @@ -2337,6 +2338,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "बंद" @@ -2355,3 +2357,221 @@ msgstr "टेलिफोनी ड्यूप्लेक्स (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "पल्सऑडियो ध्वनि सर्वर" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "आंतरिक ऑडियो" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "रिक्त आउटपुट" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "स्टीरियो" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "सर्राउंड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "सर्राउंड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "सर्राउंड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "सर्राउंड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "सर्राउंड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "सर्राउंड 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "सर्राउंड 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "सर्राउंड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "सर्राउंड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "सर्राउंड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "सर्राउंड 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-08-26 21:46+0200\n" "Last-Translator: Milo Casagrande <milo@ubuntu.com>\n" "Language-Team: Italian <tp@lists.linux.it>\n" @@ -183,25 +183,25 @@ msgstr "Modalità di sistema non supportata su questa piattaforma." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) non riuscita: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Analisi della riga di comando non riuscita." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Demone non in esecuzione" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Demone in esecuzione con PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Terminazione del demone non riuscita: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -209,163 +209,163 @@ msgstr "" "Questo programma non è pensato per essere eseguito come root (a meno di " "specificare --system)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Richiesti privilegi di root." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start non supportato per le istanze di sistema." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "In esecuzione in modalità sistema, ma --disallow-exit non impostato." -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "In esecuzione in modalità sistema, ma --disallow-module-loading non " "impostato." -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" "In esecuzione in modalità sistema, disabilitata in modo forzoso la modalità " "SHM." -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "In esecuzione in modalità sistema, disabilitato in modo forzoso il tempo di " "uscita per inattività." -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Acquisizione di STDIO non riuscita." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe non riuscita: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() non riuscita: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() non riuscita: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Avvio del demone non riuscito." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Avvio del demone riuscito." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Questo è PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Host di compilazione: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS di compilazione: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "In esecuzione sull'host: %s" # evviva il rispetto della l10n!!! -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Trovate %u CPU." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "La dimensione di pagina è %lu byte" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Compilato con supporto a Valgrind: sì" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Compilato con supporto a Valgrind: no" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "In esecuzione in modalità valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Build ottimizzata: sì" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Build ottimizzata: no" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definito, tutte le dichiarazioni sono disabilitate." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" "FASTPATH definito, solo le dichiarazioni veloci di path sono disabilitate." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Tutte le dichiarazioni sono abilitate." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Recupero dell'ID della macchina non riuscito" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "L'ID della macchina è %s" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "L'ID della sessione è %s" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "In uso directory di runtime %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "In uso directory di stato %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "In uso directory dei moduli %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "In esecuzione in modalità sistema: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -381,17 +381,17 @@ msgstr "" "Consultare http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode per maggiori " "informazioni sul perché la modalità sistema è una pessima idea." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() non riuscita." # io mi domando e dico..... mah! -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Disponibili timer high-resolution freschi freschi! Buon appetito!" # $REPEAT_PREVIOUS_COMMENT_HERE -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -399,27 +399,27 @@ msgstr "" "Hey, questo kernel è andato a male! Lo chef oggi raccomanda Linux con i " "timer high-resolution abilitati!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() non riuscita." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Inizializzazione del demone non riuscita." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Avvio del demone senza alcun modulo caricato, rifiuta di lavorare." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Completato l'avvio del demone." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Iniziato l'arresto del demone." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Demone terminato." @@ -2452,6 +2452,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Spento" @@ -2471,6 +2472,231 @@ msgstr "Doppino telefonico (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Server sonoro PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Input %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Input %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Audio interno" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Stereo analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Output %s" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Stereo analogico" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Surround analogico 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Surround analogico 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Surround analogico 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Surround analogico 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Surround analogico 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Surround analogico 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Surround analogico 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Surround analogico 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Surround analogico 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Surround analogico 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Surround analogico 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Stereo digitale (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Surround digitale 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Surround digitale 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Surround digitale 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Stereo digitale (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Mono analogico" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Stereo analogico" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Stereo digitale (IEC958)" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Nome del client \"%s\" non valido\n" @@ -2615,45 +2841,9 @@ msgstr "Server sonoro PulseAudio" #~ msgid "time_new() failed.\n" #~ msgstr "time_new() non riuscita.\n" -#~ msgid "Analog Mono" -#~ msgstr "Mono analogico" - -#~ msgid "Analog Stereo" -#~ msgstr "Stereo analogico" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Stereo digitale (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Stereo digitale (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Surround analogico 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Surround digitale 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Surround analogico 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Surround analogico 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Surround analogico 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Surround digitale 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Surround analogico 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "Output %s + Input %s" -#~ msgid "Input %s" -#~ msgstr "Input %s" - #~ msgid "Stream successfully created\n" #~ msgstr "Creazione dello stream riuscita\n" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-10 21:05+0900\n" "Last-Translator: Hyu_gabaru Ryu_ichi <hyu_gabaru@yahoo.co.jp>\n" "Language-Team: Japanese <fedora-trans-ja@redhat.com>\n" @@ -163,179 +163,179 @@ msgstr "" msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -345,41 +345,41 @@ msgid "" "explanation why system mode is usually a bad idea." msgstr "" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "" @@ -2013,6 +2013,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "オフ" @@ -2031,3 +2032,207 @@ msgstr "" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +msgid "Internal Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +msgid "Analog Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +msgid "Analog Surround 2.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +msgid "Analog Surround 3.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +msgid "Analog Surround 3.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +msgid "Analog Surround 6.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +msgid "Analog Surround 6.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +msgid "Analog Surround 7.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.kn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-08 13:49+0530\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-22 15:32+0530\n" "Last-Translator: Shankar Prasad <svenkate@redhat.com>\n" "Language-Team: Kannada <en@li.org>\n" "MIME-Version: 1.0\n" @@ -60,11 +60,11 @@ msgstr "" #: ../src/modules/module-always-sink.c:39 msgid "Always keeps at least one sink loaded even if it's a null one" -msgstr "" +msgstr "ಯಾವಾಗಲೂ ಒಂದು ಸಿಂಕ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಿರುತ್ತದೆ, ಅದು ಶೂನ್ಯವಾಗಿದ್ದರೂ ಸಹ" #: ../src/modules/module-always-sink.c:83 msgid "Dummy Output" -msgstr "" +msgstr "ಡಮ್ಮಿ ಔಟ್ಪುಟ್" #: ../src/modules/module-ladspa-sink.c:49 msgid "Virtual LADSPA sink" @@ -86,11 +86,11 @@ msgstr "" #: ../src/modules/module-null-sink.c:55 msgid "Clocked NULL sink" -msgstr "" +msgstr "ಕ್ಲಾಕ್ ಮಾಡಲಾದ NULL ಸಿಂಕ್" #: ../src/modules/module-null-sink.c:291 msgid "Null Output" -msgstr "" +msgstr "ಶೂನ್ಯ ಔಟ್ಪುಟ್" #: ../src/pulsecore/sink.c:2613 msgid "Internal Audio" @@ -179,25 +179,25 @@ msgstr "ವ್ಯವಸ್ಥೆಯಾದ್ಯಂತದ ಕ್ರಮಕ್ಕ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) ವಿಫಲಗೊಂಡಿದೆ: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "ಆಜ್ಞಾ ಸಾಲನ್ನು ಪಾರ್ಸ್ ಮಾಡುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ಡೀಮನ್ ಚಲಾಯಿತಗೊಳ್ಳುತ್ತಿದೆ" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "ಡೀಮನ್ PID %u ಯಾಗಿ ಚಲಾಯಿಗೊಳ್ಳುತ್ತಿದೆ" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ಡೀಮನ್ ಅನ್ನು ಕೊಲ್ಲಲು ವಿಫಲಗೊಂಡಿದೆ: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -205,163 +205,163 @@ msgstr "" "ಈ ಪ್ರೋಗ್ರಾಮನ್ನು ರೂಟ್ ಆಗಿ ಚಲಾಯಿಸುವ ಉದ್ಧೇಶವನ್ನು ಹೊಂದಿಲ್ಲ (--system ಅನ್ನು ಸೂಚಿಸದೆ " "ಇದ್ದಲ್ಲಿ ಮಾತ್ರ)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "ನಿರ್ವಾಹಕ ಸವಲತ್ತುಗಳ ಅಗತ್ಯವಿದೆ." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "ವ್ಯವಸ್ಥೆಯ ಸನ್ನಿವೇಶದಿಂದ --start ಬೆಂಬಲಿತವಾಗಿಲ್ಲ." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" "ವ್ಯವಸ್ಥೆಯ ಕ್ರಮದಲ್ಲಿ ಚಲಾಯಿತಗೊಳ್ಳುತ್ತಿದೆ, ಆದರೆ --disallow-exit ಅನ್ನು ಹೊಂದಿಸಲಾಗಿಲ್ಲ!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "ವ್ಯವಸ್ಥೆಯ ಕ್ರಮದಲ್ಲಿ ಚಲಾಯಿತಗೊಳ್ಳುತ್ತಿದೆ, ಆದರೆ --disallow-module-loading ಅನ್ನು " "ಹೊಂದಿಸಲಾಗಿಲ್ಲ!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" "ವ್ಯವಸ್ಥೆಯ ಕ್ರಮದಲ್ಲಿ ಚಲಾಯಿತಗೊಳ್ಳುತ್ತಿದ್ದು, SHM ಕ್ರಮವನ್ನು ಒತ್ತಾಯಪೂರ್ವಕವಾಗಿ " "ಅಶಕ್ತಗೊಳಿಸುತ್ತಿದೆ!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "ವ್ಯವಸ್ಥೆಯ ಕ್ರಮದಲ್ಲಿ ಚಲಾಯಿತಗೊಳ್ಳುತ್ತಿದ್ದು, ನಿರ್ಗಮಿಸುವ ಜಡ ಸಮಯವನ್ನು ಒತ್ತಾಯಪೂರ್ವಕವಾಗಿ " "ಅಶಕ್ತಗೊಳಿಸುತ್ತಿದೆ!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio ಅನ್ನು ಪಡೆದುಕೊಳ್ಳುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "ಪೈಪ್ ವಿಫಲಗೊಂಡಿದೆ: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() ವಿಫಲಗೊಂಡಿದೆ: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() ವಿಫಲಗೊಂಡಿದೆ: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ಡೀಮನ್ ಆರಂಭಗೊಳ್ಳುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "ಡೀಮನ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಆರಂಭಿಸಲಾಗಿದೆ." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "ಇದು PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "ಕಂಪೈಲ್ ಮಾಡುವ ಅತಿಥೇಯ: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "ಕಂಪೈಲ್ ಮಾಡುವ CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "ಅತಿಥೇಯದಲ್ಲಿ ಚಲಾಯಿತಗೊಳ್ಳುತ್ತಿದೆ: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUಗಳು ಕಂಡುಬಂದಿವೆ." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "ಪುಟದ ಗಾತ್ರವು %lu ಬೈಟ್ಗಳಾಗಿವೆ" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind ಬೆಂಬಲದೊಂದಿಗೆ ಕಂಪೈಲ್ ಮಾಡಲಾಗಿದೆ: ಹೌದು" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind ಬೆಂಬಲದೊಂದಿಗೆ ಕಂಪೈಲ್ ಮಾಡಲಾಗಿದೆ: ಇಲ್ಲ" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind ಕ್ರಮದಲ್ಲಿ ಚಲಾಯಿಸಲಾಗುತ್ತಿದೆ: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "ಪ್ರಶಸ್ತವಾದ ನಿರ್ಮಾಣ: ಹೌದು" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "ಪ್ರಶಸ್ತವಾದ ನಿರ್ಮಾಣ: ಇಲ್ಲ" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG ಅನ್ನು ಸೂಚಿಸಲಾಗಿದೆ, ಎಲ್ಲಾ ಪ್ರತಿಪಾದನೆಗಳನ್ನೂ ಅಶಕ್ತಗೊಳಿಸಲಾಗಿದೆ." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" "FASTPATH ಅನ್ನು ಸೂಚಿಸಲಾಗಿದೆ, ಕೇವಲ ವೇಗ ಮಾರ್ಗದ ಪ್ರತಿಪಾದನೆಗಳನ್ನೂ ಅಶಕ್ತಗೊಳಿಸಲಾಗಿದೆ." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "ಎಲ್ಲಾ ಪ್ರತಿಪಾದನೆಗಳನ್ನೂ ಶಕ್ತಗೊಳಿಸಲಾಗಿದೆ." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "ಮೆಶೀನ್ ID ಯನ್ನು ಪಡೆದುಕೊಳ್ಳುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "ಮೆಶೀನ್ ID ಯು %s ಆಗಿದೆ." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "ಅಧಿವೇಶನ ID ಯು %s ಆಗಿದೆ." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "ಚಲಾವಣಾಸಮಯ(ರನ್ಟೈಮ್) ಕೋಶ %s ಅನ್ನು ಬಳಸಿಕೊಂಡು." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "ಸ್ಥಿತಿ ಕೋಶ %s ಅನ್ನು ಬಳಸಿಕೊಂಡು." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "ಘಟಕಗಳ ಕೋಶ %s ಅನ್ನು ಬಳಸಿಕೊಂಡು." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "ವ್ಯವಸ್ಥೆಯ ಕ್ರಮದಲ್ಲಿ ಚಲಾಯಿಸಲಾಗುತ್ತಿದೆ: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -377,15 +377,15 @@ msgstr "" "ವ್ಯವಸ್ಥೆಯ ಕ್ರಮವು (ಸಿಸ್ಟಮ್ ಮೋಡ್) ಏಕೆ ಒಂದು ಸರಿಯಲ್ಲದ ಬಳಕೆ ಎಂದು ಅರಿಯಲು ದಯವಿಟ್ಟು http://" "pulseaudio.org/wiki/WhatIsWrongWithSystemMode ಅನ್ನು ನೋಡಿ." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() ವಿಫಲಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "ತಾಜಾ ರೆಸಲ್ಯೂಶನ್ ಟೈಮರ್ ಲಭ್ಯವಿದೆ! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -393,27 +393,27 @@ msgstr "" "ಮಹಾಶಯರೆ, ನಿಮ್ಮ ಕರ್ನಲ್ ಕೊಳೆತುಹೋಗಿದೆ! ಅತ್ಯುತ್ತಮ ರೆಸಲ್ಯೂಶನ್ ಟೈಮರ್ ಅನ್ನು ಶಕ್ತಗೊಳಿಸಲಾದ " "ಲಿನಕ್ಸನ್ನು ಬಳಸುವಂತೆ ಅಡುಗೆಯವರು ಸಲಹೆ ಮಾಡುತ್ತಿದ್ದಾರೆ!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() ವಿಫಲಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ಡೀಮನ್ ಅನ್ನು ಆರಂಭಿಸಲು ವಿಫಲಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "ಲೋಡ್ ಮಾಡಲಾದ ಯಾವುದೆ ಡೀಮನ್ ಇಲ್ಲದೆ ಆರಂಭಗೊಂಡಿದೆ, ಕೆಲಸ ಮಾಡಲು ನಿರಾಕರಿಸಿದೆ." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ಡೀಮನ್ ಆರಂಭಗೊಳಿಕೆ ಪೂರ್ಣಗೊಂಡಿದೆ." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ಡೀಮನ್ ಸ್ಥಗಿತಗೊಳಿಕೆಯನ್ನು ಆರಂಭಿಸಲಾಗಿದೆ." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ಡೀಮನ್ ಅನ್ನು ಅಂತ್ಯಗೊಳಿಸಲಾಗಿದೆ." @@ -1101,11 +1101,11 @@ msgstr "ಕ್ಲೈಂಟ್ ಅನ್ನು ಫೋರ್ಕ್ ಮಾಡಲಾ #: ../src/pulse/error.c:68 msgid "Input/Output error" -msgstr "" +msgstr "ಇನ್ಪುಟ್/ಔಟ್ಪುಟ್ ದೋಷ" #: ../src/pulse/error.c:69 msgid "Device or resource busy" -msgstr "" +msgstr "ಸಾಧನ ಅಥವ ಸಂಪನ್ಮೂಲವು ಕಾರ್ಯನಿರತವಾಗಿದೆ" #: ../src/pulse/sample.c:172 #, c-format @@ -1315,9 +1315,9 @@ msgid "Failed to get latency: %s" msgstr "ಅಗೋಚರತೆಯನ್ನು ಪಡೆದುಕೊಳ್ಳುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ: %s" #: ../src/utils/pacat.c:580 -#, fuzzy, c-format +#, c-format msgid "Time: %0.3f sec; Latency: %0.0f usec." -msgstr "ಸಮಯ: %0.3f sec; ಅಗೋಚರತೆ: %0.0f usec. \r" +msgstr "ಸಮಯ: %0.3f sec; ಅಗೋಚರತೆ: %0.0f usec." #: ../src/utils/pacat.c:599 #, c-format @@ -2348,6 +2348,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "ಜಡ" @@ -2366,3 +2367,221 @@ msgstr "ಟೆಲಿಫೋನಿ ಡ್ಯೂಪ್ಲೆಕ್ಸ್ (HSP/HF #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio ಧ್ವನಿ ಪರಿಚಾರಕ" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "ಆಂತರಿಕ ಆಡಿಯೊ" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "ಶೂನ್ಯ ಔಟ್ಪುಟ್" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "ಸ್ಟೀರಿಯೋ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "ಸರೌಂಡ್ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "ಸರೌಂಡ್ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "ಸರೌಂಡ್ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "ಸರೌಂಡ್ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "ಸರೌಂಡ್ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "ಸರೌಂಡ್ 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "ಸರೌಂಡ್ 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "ಸರೌಂಡ್ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "ಸರೌಂಡ್ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "ಸರೌಂಡ್ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "ಸರೌಂಡ್ 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.ml\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-10 11:19+0530\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-21 20:54+0530\n" "Last-Translator: \n" "Language-Team: <en@li.org>\n" "MIME-Version: 1.0\n" @@ -176,25 +176,25 @@ msgstr "ഈ പ്ലാറ്റ്ഫോമില് സിസ്റ്റ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) പരാജയപ്പെട്ടു: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "കമാന്ഡ് ലൈന് പാഴ്സ് ചെയ്യുന്നതില് പരാജയപ്പെട്ടു." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ഡെമണ് പ്രവര്ത്തനത്തിലില്ല" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "ഡെമണ് PID %u ആയി പ്രവര്ത്തിക്കുന്നു" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ഡെമണ് നശിപ്പിക്കുന്നതില് പരാജയപ്പെട്ടു: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -202,157 +202,157 @@ msgstr "" "ഈ പ്രോഗ്രാം റൂട്ടായി പ്രവര്ത്തിപ്പിക്കേണ്ടതല്ല (--system എന്നു് പറഞ്ഞിട്ടുണ്ടെങ്കില് മാത്രം റൂട്ട് " "ആവശ്യമുണ്ടു്)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "റൂട്ട് ആനുകൂല്യങ്ങള് ആവശ്യമുണ്ടു്." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "സിസ്റ്റം ഇന്സ്റ്റന്സുകള്ക്ക് --start പിന്തുണയ്ക്കുന്നില്ല." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "സിസ്റ്റം മോഡില് പ്രവര്ത്തിക്കുന്നു, പക്ഷേ --disallow-exit സജ്ജമാക്കിയിട്ടില്ല!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "സിസ്റ്റം മോഡില് പ്രവര്ത്തിക്കുന്നു, പക്ഷേ --disallow-module-loading സജ്ജമാക്കിയിട്ടില്ല!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "സിസ്റ്റം മോഡില് പ്രവര്ത്തിക്കുന്നു, നിര്ബന്ധമായും SHM മോഡ് പ്രവര്ത്ത രഹിതമാക്കുന്നു!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "സിസ്റ്റം മോഡില് പ്രവര്ത്തിക്കുന്നു, നിര്ബന്ധമായും എക്സിറ്റ് ഐഡില് സമയം പ്രവര്ത്ത രഹിതമാക്കുന്നു!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio ലഭിക്കുന്നതില് പരാജയപ്പെട്ടു." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe പരാജയപ്പെട്ടു: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() പരാജയപ്പെട്ടു: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() പരാജയപ്പെട്ടു: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ഡെമണിന്റെ തുടക്കം പരാജയപ്പെട്ടു." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "ഡെമണിന്റെ തുടക്കം വിജയിച്ചു." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "ഇതു് PulseAudio %s ആണു്" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "കംപൈലേഷന് ഹോസ്റ്റ്: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "കംപൈലേഷന് CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "ഹോസ്റ്റില് പ്രവര്ത്തിക്കുന്നു: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u സിപിയു ലഭ്യമായി." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "താളിന്റെ വ്യാപ്തി %lu ബൈറ്റുകളാണു്" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind പിന്തുണയോടെ കംപൈല് ചെയ്തിരിക്കുന്നു: ഉവ്വു്" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind പിന്തുണയോടെ കംപൈല് ചെയ്തിരിക്കുന്നു: ഇല്ല" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind മോഡില് പ്രവര്ത്തിപ്പിക്കുന്നു: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "ഒപ്ടിമൈസ്ഡ് ബിള്ഡ്: ഉവ്വു്" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "ഒപ്ടിമൈസ്ഡ് ബിള്ഡ്: ഇല്ല" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG നിഷ്കര്ഷിച്ചിരിക്കുന്നു, എല്ലാ asserts-ഉം പ്രവര്ത്ത രഹിതം." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH നിഷ്കര്ഷിച്ചിരിക്കുന്നു, fast path asserts മാത്രം പ്രവര്ത്ത രഹിതം." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "എല്ലാ asserts-ഉം പ്രവര്ത്ത സജ്ജം" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "മഷീന് ID ലഭ്യമാക്കുവാന് സാധ്യമായില്ല" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "മഷീന് ID %s ആണു്." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "സെഷന് ID %s ആണു്." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "റണ്ടൈം ഡയറക്ടറി %s ഉപയോഗിക്കുന്നു." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "സ്റ്റേറ്റ് ഡയറക്ടറി %s ഉപയോഗിക്കുന്നു." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "മൊഡ്യൂള്സ് ഡയറക്ടറി %s ഉപയോഗിക്കുന്നു." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "സിസ്റ്റം മോഡില് പ്രവര്ത്തിക്കുന്നു: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -366,15 +366,15 @@ msgstr "" "സിസ്റ്റം മോഡിലുള്ള പ്രവര്ത്തനം ഉത്തമമല്ലാത്തതിന്റെ കാരണങ്ങള്ക്കായിhttp://pulseaudio.org/" "wiki/WhatIsWrongWithSystemMode കാണുക." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() പരാജയപ്പെട്ടു." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Fresh high-resolution timers available! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -382,27 +382,27 @@ msgstr "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() പരാജയപ്പെട്ടു." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ഡെമണ് ആരംഭിക്കുന്നതില് പരാജയപ്പെട്ടു." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "ഒരു ഘടകങ്ങളും ലഭ്യമാകാതെ ഡെമണ് ആരംഭിച്ചിരിക്കുന്നു, പ്രവര്ത്തനം നിഷേധിച്ചിരിക്കുന്നു." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ഡെമണിന്റെ തുടക്കം പൂര്ണ്ണമായി." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ഡെമണ് അടച്ചുപൂട്ടുന്നതു് ആരംഭിച്ചിരിക്കുന്നു." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ഡെമണ് നിര്ത്തിയിരിക്കുന്നു." @@ -1085,11 +1085,11 @@ msgstr "ക്ലൈന്റ് ഫോര്ക്ക് ചെയ്തി #: ../src/pulse/error.c:68 msgid "Input/Output error" -msgstr "" +msgstr "ഇന്പുട്ട്/ഔട്ട്പുട്ട് പിശക്" #: ../src/pulse/error.c:69 msgid "Device or resource busy" -msgstr "" +msgstr "ഉപകരണം അല്ലെങ്കില് ഉറവിടം ഉപയോഗത്തില്" #: ../src/pulse/sample.c:172 #, c-format @@ -2330,6 +2330,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "ഓഫ്" @@ -2348,3 +2349,221 @@ msgstr "ടെലിഫോണി ഡ്യൂപ്ലെക്സ് (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "പള്സ്ഓഡിയോ സൌണ്ട് സര്വര്" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "ഇന്റേര്ണല് ഓഡിയോ" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "നള് ഔട്ട്പുട്ട്" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "സ്റ്റീരിയോ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "സറൌണ്ട് 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "സറൌണ്ട് 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "സറൌണ്ട് 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "സറൌണ്ട് 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "സറൌണ്ട് 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "സറൌണ്ട് 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "സറൌണ്ട് 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "സറൌണ്ട് 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "സറൌണ്ട് 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "സറൌണ്ട് 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "സറൌണ്ട് 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-10 15:34+0530\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-21 18:16+0530\n" "Last-Translator: Sandeep Shedmake <sshedmak@redhat.com>\n" "Language-Team: Marathi <fedora-trans-mr@redhat.com>\n" "MIME-Version: 1.0\n" @@ -180,180 +180,180 @@ msgstr "प्रणाली भर पद्धत या प्लॅटफ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) अपयशी: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "आदेश ओळ वाचण्यास अपयशी." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "डिमन कार्यरत नाही" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "डिमन PID %u नुरूप कार्यरत आहे" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "डिमन नष्ट करण्यास अपयशी: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "हा कार्यक्रम रूट नुरूप चालविण्याकरीता नाही (जोपर्यंत --system निश्चित नाही)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "रूट परवानगी आवश्यक." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "प्रणाली घटनांकरीता --start समर्थीत नाही." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "प्रणाली पद्धती अंतर्गत कार्यरत, परंतु --disallow-exit निश्चित केले नाही!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "प्रणाली पद्धती अंतर्गत कार्यरत, परंतु --disallow-module-loading निश्चित केले नाही!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "प्रणाली पद्धती अंतर्गत कार्यरत, SHM पद्धत जबरनरित्या अकार्यान्वीत करत आहे!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "प्रणाली पद्धती अंतर्गत कार्यरत, रिकामे वेळ जबरनरित्या अकार्यान्वीत करत आहे!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio प्राप्त करण्यास अपयशी." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "पाइप अपयशी: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() अपयशी: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() अपयशी: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "डिमन स्टार्टअप अपयशी." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "डिमन स्टार्टअप यशस्वी." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "हे PulseAudio %s आहे" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "कंपाइलेशन यजमान: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "कंपाइलेशन CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "यजमान वर कार्यरत: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs आढळले." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "पान आकार %lu बाईटस् आहे" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind समर्थनशी कंपाईल केले: होय" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind समर्थनशी कंपाईल केले: नाही" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind पद्धतीत कार्यरत: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "अनुकूल बिल्ड: होय" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "अनुकूल बिल्ड: नाही" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG वर्णीकृत, सर्व asserts अकार्यान्वीत." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH वर्णीकृत, फक्त जलद मार्गीय asserts अकार्यान्वीत केले." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "सर्व asserts कार्यान्वीत केले." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "मशीन ID प्राप्त करण्यास अपयशी" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "मशीन ID %s आहे." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "सत्र ID %s आहे." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "रनटाईम डिरेक्ट्री %s वापरत आहे." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "स्थिती डिरेक्ट्री %s वापरत आहे." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "घटक डिरेक्ट्री %s वापरत आहे." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "प्रणाली पद्धतीत कार्यरत: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -369,15 +369,15 @@ msgstr "" "प्रणाली मोड दोकादायक आहे यासाठी कृपया http://pulseaudio.org/wiki/" "WhatIsWrongWithSystemMode वाचा." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() अपयशी." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "नवीन उच्च-बिंदूता टाइमर उपलब्ध! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -385,27 +385,27 @@ msgstr "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() अपयशी." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "डिमन प्रारंभ करण्यास अपयशी." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "विना विभाग दाखल केल्यास डिमन प्रारंभ झाले, कार्य करण्यास नकार." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "डिमन स्टार्टअप पूर्ण झाले." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "डिमन पूर्णपणे बंद करण्यास प्रारंभ केले." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "डिमन नष्ट केले." @@ -1088,11 +1088,11 @@ msgstr "क्लाऐंट विभाजीत केले" #: ../src/pulse/error.c:68 msgid "Input/Output error" -msgstr "" +msgstr "इंपुट/आऊटपुट त्रुटी" #: ../src/pulse/error.c:69 msgid "Device or resource busy" -msgstr "" +msgstr "उपकरन किंव स्रोत व्यस्थ" #: ../src/pulse/sample.c:172 #, c-format @@ -2330,6 +2330,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "बंद करा" @@ -2348,3 +2349,221 @@ msgstr "टेलिफोनी ड्युप्लेक्स् (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio आवाज सर्वर" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "आंतरीक ऑडिओ" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Null आऊटपुट" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "स्टिरीओ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "सराऊन्ड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "सराऊन्ड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "सराऊन्ड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "सराऊन्ड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "सराऊन्ड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "सराऊन्ड 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "सराऊन्ड 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "सराऊन्ड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "सराऊन्ड 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "सराऊन्ड 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "सराऊन्ड 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-11 19:58+0200\n" "Last-Translator: Geert Warrink <geert.warrink@onsnet.nu>\n" "Language-Team: nl <nl@li.org>\n" @@ -182,25 +182,25 @@ msgstr "Systeem brede mode wordt op dit platform niet ondersteund." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) mislukte: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Analyseren van de commandoregel mislukte." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Daemon draait niet" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Daemon draait met PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Afschieten mislukt van daemon: '%s'" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -208,156 +208,156 @@ msgstr "" "Dit programma is niet bedoeld om als root gedraaid te worden (behalve als --" "system is opgegeven)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Root rechten vereisd" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start wordt niet ondersteund voor systeem instances" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "Draaiend in systeem mode, maar --disallow-exit is niet gezet!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Draaiend in systeem mode, maar --disallow-module-loading is niet gezet!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Draaiend in systeem mode, geforceerd uitzetten van SHM mode!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "Draaiend in systeem mode, geforceerd uitzetten van exit idle time!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Verkrijgen van stdio mislukte." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe mislukte: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() mislukte: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() mislukte: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Daemon opstarten mislukte." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Daemon met succes opgestart." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Dit is PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Compilatie host: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Compilatie CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Draaiend op host: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPU's gevonden." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Pagina grootte is %lu bytes" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Gecompileerd met Valgrind ondersteuning: ja" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Gecompileerd met Valgrind ondersteuning: nee" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Draaiend in valgrind mode: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimaal gebouwd: ja" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimaak gebouwd: nee" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG gedefinieerd, alle verklaringen uitgezet." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH gedefinieerd, alleen snel pad verklaringen uitgezet." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Alle verklaringen aangezet." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Machine ID verkrijgen mislukte" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "Machine ID is: %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "Sessie ID is: %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Gebruik van runtime map %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Verbruik van state map %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Gebruik van module map %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Draaiend in systeem mode: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -373,15 +373,15 @@ msgstr "" "Lees a.u.b.http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode voor een " "uitleg waarom systeem mode gewoonlijk een slecht idee is." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() mislukte." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Verse high-resolution timers beschikbaar! Smakelijk eten!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -389,27 +389,27 @@ msgstr "" "Kerel, je kernel stinkt! De aanbeveling van de chef is vandaag Linux met " "aangezette high-resolution timers!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() mislukte." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Initialiseren van de daemon mislukte." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Daemon opgestart zonder geladen modules, dat werkt niet." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Daemon opstarten is klaar." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Daemon afsluiten is begonnen." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Daemon is afgesloten." @@ -2359,6 +2359,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Uiy" @@ -2378,6 +2379,229 @@ msgstr "Telefonie Duplex (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "PulseAudio geluids server" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Intern geluid" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Analoog stereo" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Null output" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Analoog stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Analoog surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Analoog surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Analoog surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Analoog surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Analoog surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Analoog surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Analoog surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Analoog surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Analoog surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Analoog surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Analoog surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Digitaal stereo (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Digitaal surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Digitaal surround 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Digitaal surround 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Digitaal stereo (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Analoog mono" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Analoog stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Digitaal stereo (IEC958)" + #, fuzzy #~ msgid "Invalid client name '%s'\n" #~ msgstr "Ongeldige resample methode '%s'." @@ -2478,36 +2702,3 @@ msgstr "PulseAudio geluids server" #~ msgstr "" #~ "Real-time inplannen is aangezet in de configuratie maar niet toegestaan " #~ "door de richtlijnen." - -#~ msgid "Analog Mono" -#~ msgstr "Analoog mono" - -#~ msgid "Analog Stereo" -#~ msgstr "Analoog stereo" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Digitaal stereo (IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Digitaal stereo (HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "Analoog surround 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Digitaal surround 4.0 (IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "Analoog surround 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "Analoog surround 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "Analoog surround 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Digitaal surround 5.1 (IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "Analoog surround 7.1" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.or\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-11 12:56+0530\n" "Last-Translator: Manoj Kumar Giri <mgiri@redhat.com>\n" "Language-Team: Oriya <oriya-it@googlegroups.com>\n" @@ -196,25 +196,25 @@ msgstr "ତନ୍ତ୍ରମୟ ଧାରା ଏହି ପ୍ଲାଟଫର୍ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) ବିଫଳ ହୋଇଛି: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "ପାଠ୍ୟ ନିର୍ଦ୍ଦେଶକୁ ବିଶ୍ଳେଷଣ କରିବାରେ ବିଫଳ।" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ଡେମନ ଚାଲୁନାହିଁ" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "ଡେମନ PID %u ପରି ଚାଲୁଅଛି" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ଡେମନକୁ ବନ୍ଦ କରିବାରେ ବିଫଳ: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -222,155 +222,155 @@ msgstr "" "ଏହି ପ୍ରଗ୍ରାମଟି ମୂଖ୍ୟ ଚାଳକ ଭାବରେ ଚଲାଇବା ପାଇଁ ନିର୍ଦ୍ଦିଷ୍ଟ ହୋଇନାହିଁ (unless --system is " "specified)।" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "ମୂଖ୍ୟ ଚାଳକ ଅଧିକାର ଆବଶ୍ୟକ।" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start ତନ୍ତ୍ର ସ୍ଥିତି ପାଇଁ ସମର୍ଥିତ ନୁହଁ।" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "ତନ୍ତ୍ର ଧାରାରେ ଚାଲୁଅଛି, କିନ୍ତୁ --disallow-exit କୁ ସେଟ କରାଯାଇନାହିଁ!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "ତନ୍ତ୍ର ଧାରାରେ ଚାଲୁଅଛି, କିନ୍ତୁ --disallow-module-loading କୁ ସେଟ କରାଯାଇନାହିଁ!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "ତନ୍ତ୍ର ଧାରାରେ ଚାଲୁଅଛି, SHM ଧାରାକୁ ବାଧ୍ଯତାମୁଳକ ଭାବରେ ନିଷ୍କ୍ରିୟ କରିଥାଏ!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "ତନ୍ତ୍ର ଧାରାରେ ଚାଲୁଅଛି, ପ୍ରସ୍ଥାନ ସ୍ଥିର ସମୟକୁ ବାଧ୍ଯତାମୁଳକ ଭାବରେ ନିଷ୍କ୍ରିୟ କରିଥାଏ!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio କୁ ଅଧିକାର କରିବାରେ ବିଫଳ।" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "ପାଇପ ବିଫଳ ହୋଇଛି: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() ବିଫଳ ହୋଇଛି: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() ବିଫଳ ହୋଇଛି: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ଡେମନ ଆରମ୍ଭ ବିଫଳ ହୋଇଛି।" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "ଡେମନ ଆରମ୍ଭ ସଫଳ ହୋଇଛି।" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "ଏହା ହେଉଛି PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "ସଂକଳନ ଆଧାର: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "ସଂକଳନ CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "ଆଧାରରେ ଚାଲୁଅଛି: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs ମିଳିଛି।" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "ପୃଷ୍ଠା ଆକାରଟି ହେଉଛି %lu ବାଇଟ" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind ସମର୍ଥନ ସହିତ ସଂକଳନ ହୋଇଛି: yes" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind ସମର୍ଥନ ସହିତ ସଂକଳନ ହୋଇଛି: no" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind ଧାରାରେ ଚାଲୁଅଛି: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "ଉପଯୁକ୍ତ ନିର୍ମାଣ: yes" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "ଉପଯୁକ୍ତ ନିର୍ମାଣ: no" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG କୁ ବ୍ୟାଖ୍ୟା କରାଯାଇଛି, ସମସ୍ତ ନିଶ୍ଚୟକୁ ନିଷ୍କ୍ରିୟ କରାଯାଇଛି।" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH କୁ ବ୍ୟାଖ୍ୟା କରାଯାଇଛି, କେବଳ ତୀବ୍ର ପଥ ନିଶ୍ଚୟକୁ ନିଷ୍କ୍ରିୟ କରାଯାଇଛି।" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "ସମସ୍ତ ନିଶ୍ଚୟକୁ ସକ୍ରିୟ କରାଯାଇଛି।" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "ଯନ୍ତ୍ର ID ପାଇବାରେ ବିଫଳ" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "ଯନ୍ତ୍ର ID ଟି ହେଉଛି %s।" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "ଅଧିବେଶନ ID ଟି ହେଉଛି %s।" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "ପ୍ରଚଳିତ ଡିରେକ୍ଟୋରୀ %s କୁ ବ୍ୟବହାର କରୁଅଛି।" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "ସ୍ଥିତି ଡିରେକ୍ଟୋରୀ %s କୁ ବ୍ୟବହାର କରି।" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "ଏକକାଂଶ ଡିରେକ୍ଟୋରୀ %s କୁ ବ୍ୟବହାର କରି।" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "ତନ୍ତ୍ର ଧାରାରେ ଚାଲୁଅଛି: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -385,15 +385,15 @@ msgstr "" "ତନ୍ତ୍ର ଧାରାଟି ସାଧାରଣତଃ କାହିଁକି ଖରାପ ତାହା ବିଷୟରେ ଜାଣିବା ପାଇଁ ଦୟାକରି http://pulseaudio." "org/wiki/WhatIsWrongWithSystemMode କୁ ପଢ଼ନ୍ତୁ।" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() ବିଫଳ ହୋଇଛି।" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "ସତେଜ ଉଚ୍ଚ-ବିଭେଦନ ସମୟ ମାପକ ଉପଲବ୍ଧ! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -401,27 +401,27 @@ msgstr "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() ବିଫଳ ହୋଇଛି।" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ଡେମନକୁ ଆରମ୍ଭ କରିବାରେ ବିଫଳ।" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "ଧାରଣ ହୋଇଥିବା ଏକକାଂଶଗୁଡ଼ିକ ବିନା ଡେମନ ଆରମ୍ଭ ହୋଇଛି, କାର୍ଯ୍ୟ କରିବାକୁ ବାରଣ କରୁଅଛି।" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ଡେମନ ଆରମ୍ଭ ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି।" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ଡେମନ ବନ୍ଦକୁ ଆରମ୍ଭ କରାଯାଇଛି।" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ଡେମନକୁ ସମାପ୍ତ କରାଯାଇଛି।" @@ -2339,6 +2339,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "ଅଫ" @@ -2357,3 +2358,221 @@ msgstr "ଟେଲିଫୋନି ଡ୍ୟୁପ୍ଲେକ୍ସ (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio ଧ୍ୱନି ସର୍ଭର" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "ଆଭ୍ୟନ୍ତରୀଣ ଧ୍ୱନି" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "ଶୂନ୍ୟ ଫଳାଫଳ" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "ଷ୍ଟେରିଓ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "ଚତୁଃ ପାର୍ଶ୍ୱ 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.pa\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-11 12:08+0530\n" "Last-Translator: Jaswinder Singh <jsingh@redhat.com>\n" "Language-Team: Punjabi <Punjabi-users@lists.sourceforge.net>\n" @@ -178,179 +178,179 @@ msgstr "ਇਸ ਪਲੇਟਫਾਰਮ ਤੇ ਸਿਸਟਮ ਸੰਬੰਧ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) ਫੇਲ੍ਹ ਹੋਇਆ: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "ਕਮਾਂਡ ਲਾਈਨ ਪਾਰਸ ਕਰਨ ਵਿੱਚ ਫੇਲ੍ਹ।" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "ਡੈਮਨ ਚੱਲ ਨਹੀਂ ਰਿਹਾ" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "ਡੈਮਨ PID %u ਤੌਰ ਤੇ ਚੱਲ ਰਿਹਾ ਹੈ" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "ਡੈਮਨ ਖਤਮ ਕਰਨ ਵਿੱਚ ਫੇਲ੍ਹ: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "ਇਹ ਪਰੋਗਰਾਮ ਰੂਟ ਦੇ ਤੌਰ ਤੇ ਚਲਾਉਣ ਲਈ ਨਹੀਂ ਹੈ (ਜਦੋਂ ਤੱਕ --system ਦਿੱਤਾ ਨਹੀਂ ਜਾਂਦਾ)।" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "ਰੂਟ ਅਧਿਕਾਰਾਂ ਦੀ ਲੋੜ ਹੈ।" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start ਨੂੰ ਸਿਸਟਮ ਮੌਕਿਆਂ ਲਈ ਸਹਿਯੋਗ ਨਹੀਂ ਹੈ।" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "ਸਿਸਟਮ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ, ਪਰ --disallow-exit ਸੈੱਟ ਨਹੀਂ ਕੀਤਾ!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "ਸਿਸਟਮ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ, ਪਰ --disallow-module-loading ਸੈੱਟ ਨਹੀਂ ਕੀਤਾ!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "ਸਿਸਟਮ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ, ਜ਼ਬਰਦਸਤੀ SHM ਮੋਡ ਨੂੰ ਅਯੋਗ ਕਰ ਰਿਹਾ ਹੈ!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "ਸਿਸਟਮ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ, ਜ਼ਬਰਦਸਤੀ idle ਟਾਈਲ ਬੰਦ ਨੂੰ ਅਯੋਗ ਕਰ ਰਿਹਾ ਹੈ!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "ਸਟੂਡੀਓ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਫੇਲ੍ਹ।" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe ਫੇਲ੍ਹ: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() ਫੇਲ੍ਹ ਹੈ: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() ਫੇਲ੍ਹ ਹੈ: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "ਡੈਮਨ ਸ਼ੁਰੂਆਤੀ ਫੇਲ੍ਹ ਹੋਈ।" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "ਡੈਮਨ ਸ਼ੁਰੂਆਤੀ ਸਫ਼ਲ ਹੋਈ।" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "ਇਹ ਪਲਸਆਡੀਓ %s ਹੈ" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "ਕੰਪਾਈਲੇਸ਼ਨ ਹੋਸਟ: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "ਕੰਪਾਈਲੇਸ਼ਨ CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "ਹੋਸਟ ਤੇ ਚੱਲ ਰਿਹਾ ਹੈ: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs ਲੱਭੇ।" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "ਪੇਜ਼ ਸਾਈਜ਼ %lu ਬਾਈਟ ਹੈ" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind ਸਹਿਯੋਗ ਨਾਲ ਕੰਪਾਈਲ: ਹਾਂ" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind ਸਹਿਯੋਗ ਨਾਲ ਕੰਪਾਈਲ: ਨਹੀਂ" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Valgrind ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "ਓਪਟੀਮਾਈਜ਼ਡ ਬਿਲਡ: ਹਾਂ" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "ਓਪਟੀਮਾਈਜ਼ਡ ਬਿਲਡ: ਨਹੀਂ" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG ਪਰਿਭਾਸ਼ਤ, ਸਭ asserts ਅਯੋਗ ਹਨ।" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH ਪਰਿਭਾਸ਼ਤ, ਸਿਰਫ ਫਾਸਟ ਪਾਥ asserts ਅਯੋਗ ਹਨ।" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "ਸਭ asserts ਯੋਗ ਕੀਤੇ ਹਨ।" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "ਮਸ਼ੀਨ ID ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਫੇਲ੍ਹ" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "ਮਸ਼ੀਨ ID %s ਹੈ।" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "ਸ਼ੈਸ਼ਨ ID %s ਹੈ।" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "ਰਨਟਾਈਮ ਡਾਇਰੈਕਟਰੀ %s ਦੀ ਵਰਤੋਂ।" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "ਸਟੇਟ ਡਾਇਰੈਕਟਰੀ %s ਦੀ ਵਰਤੋਂ।" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "ਮੈਡਿਊਲ ਡਾਇਰੈਕਟਰੀ %s ਦੀ ਵਰਤੋਂ।" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "ਸਿਸਟਮ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -365,42 +365,42 @@ msgstr "" "ਕਿਰਪਾ ਕਰਕੇ ਸਿਸਟਮ ਮੋਡ ਦੇ ਗਲਤ ਹੋਣ ਬਾਰੇ ਵਧੇਰੇ ਜਾਣਕਾਰੀ ਲਈ http://pulseaudio.org/wiki/" "WhatIsWrongWithSystemMode ਵੇਖੋ।" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() ਫੇਲ੍ਹ ਹੈ।" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "ਤਾਜ਼ੀ ਹਾਈ-ਰੈਜ਼ੋਲੂਸ਼ਨ ਟਾਈਮਰ ਉਪਲੱਬਧ ਹੈ! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "" "ਮਿੱਤਰਾ, ਤੇਰਾ ਕਰਨਲ ਪੁਰਾਣਾ ਹੈ! ਚੀਫ ਦੀ ਅੱਜ ਦੀ ਸਿਫਾਰਸ਼ ਹਾਈ-ਰੈਜ਼ੋਲੂਸ਼ਨ ਟਾਈਮਰ ਯੋਗ ਨਾਲ ਲੀਨਕਸ ਹੈ!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() ਫੇਲ੍ਹ ਹੈ।" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "ਡੈਮਨ ਸ਼ੁਰੂ ਕਰਨ ਵਿੱਚ ਫੇਲ੍ਹ।" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "ਡੈਮਨ ਸ਼ੁਰੂਆਤੀ ਬਿਨਾਂ ਕਿਸੇ ਲੋਡ ਕੀਤੇ ਮੈਡਿਊਲ, ਕੰਮ ਕਰਨ ਤੋਂ ਰੋਕ ਰਿਹਾ ਹੈ।" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "ਡੈਮਨ ਸ਼ੁਰੂਆਤੀ ਮੁਕੰਮਲ।" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "ਡੈਮਨ ਬੰਦ ਕਰਨਾ ਸ਼ੁਰੂ ਹੋ ਗਿਆ।" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "ਡੈਮਨ ਬੰਦ ਹੋ ਗਿਆ।" @@ -2325,6 +2325,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "ਬੰਦ" @@ -2343,3 +2344,221 @@ msgstr "ਟੈਲੀਫੋਨੀ ਡੁਪਲੈਕਸ (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "ਪਲਸਆਡੀਓ ਸਾਊਂਡ ਡਰਾਇਵਰ" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "ਅੰਦਰੂਨੀ ਆਡੀਓ" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "ਜ਼ੀਰੋ (Null) ਆਉਟਪੁੱਟ" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "ਸਟੀਰੀਓ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "ਸਰਾਊਂਡਿੰਗ 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "ਸਰਾਊਂਡਿੰਗ 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "ਸਰਾਊਂਡਿੰਗ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "ਸਰਾਊਂਡਿੰਗ 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: pl\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-12 21:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-27 15:42+0200\n" "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n" "Language-Team: Polish <fedora-trans-pl@redhat.com>\n" "MIME-Version: 1.0\n" @@ -118,22 +118,22 @@ msgstr "Otrzymano sygnał %s." #: ../src/daemon/main.c:168 msgid "Exiting." -msgstr "Wyłączanie." +msgstr "Kończenie pracy." #: ../src/daemon/main.c:186 #, c-format msgid "Failed to find user '%s'." -msgstr "Znalezienie użytkownika \"%s\" nie powiodło się." +msgstr "Odnalezienie użytkownika \"%s\" nie powiodło się." #: ../src/daemon/main.c:191 #, c-format msgid "Failed to find group '%s'." -msgstr "Znalezienie grupy \"%s\" nie powiodło się." +msgstr "Odnalezienie grupy \"%s\" nie powiodło się." #: ../src/daemon/main.c:195 #, c-format msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)." -msgstr "Znaleziono użytkownika \"%s\" (UID %lu) i grupę \"%s\" (GID %lu)." +msgstr "Odnaleziono użytkownika \"%s\" (UID %lu) i grupę \"%s\" (GID %lu)." #: ../src/daemon/main.c:200 #, c-format @@ -143,7 +143,7 @@ msgstr "GID użytkownika \"%s\" i grupy \"%s\" nie zgadzają się." #: ../src/daemon/main.c:205 #, c-format msgid "Home directory of user '%s' is not '%s', ignoring." -msgstr "Folder domowy użytkownika \"%s\" nie jest \"%s\", ignorowanie." +msgstr "Katalog domowy użytkownika \"%s\" nie jest \"%s\", ignorowanie." #: ../src/daemon/main.c:208 ../src/daemon/main.c:213 #, c-format @@ -178,25 +178,25 @@ msgstr "Tryb systemowy nie jest obsługiwany na tej platformie." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) nie powiodło się: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." -msgstr "Analiza wiersza poleceń nie powiodła się." +msgstr "Przetworzenie wiersza poleceń nie powiodła się." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Demon nie jest uruchomiony" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Demon jest uruchomiony jako PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Zniszczenie demona nie powiodło się: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -204,160 +204,160 @@ msgstr "" "Ten program nie powinien być uruchomiany jako root (chyba, że podano --" "system)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Wymagane są uprawnienia roota." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start nie jest obsługiwane przy uruchamianiu systemowym." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" -"Uruchamianie w trybie systemowym, ale --disallow-exit nie jest ustawione!" +"Uruchamianie w trybie systemowym, ale --disallow-exit nie jest ustawione." -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Uruchamianie w trybie systemowym, ale --disallow-module-loading nie jest " -"ustawione!" +"ustawione." -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" -msgstr "Uruchamianie w trybie systemowym, wymuszanie wyłączenia trybu SHM!" +msgstr "Uruchamianie w trybie systemowym, wymuszanie wyłączenia trybu SHM." -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Uruchamianie w trybie systemowym, wymuszanie wyłączenia czasu oczekiwania na " -"zakończenie!" +"zakończenie." -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Uzyskanie standardowego wejścia/wyjścia nie powiodło się." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "potok nie powiódł się: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() nie powiodło się: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() nie powiodło się: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Uruchomienie demona nie powiodło się." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Pomyślnie uruchomiono demona." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "To jest PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Komputer kompilacji: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS kompilacji: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Uruchamianie na komputerze: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." -msgstr "Znaleziono %u procesorów." +msgstr "Odnaleziono %u procesorów." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Rozmiar strony to %lu bajtów" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Skompilowano z obsługą Valgrind: tak" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Skompilowano z obsługą Valgrind: nie" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Uruchamianie w trybie Valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Budowanie optymalizowane: tak" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Budowanie optymalizowane: nie" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "Podano NDEBUG, wszystkie asercje zostały wyłączone." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "Podano FASTPATH, tylko szybkie asercje ścieżek zostały wyłączone." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Wszystkie asercje są włączone." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Uzyskanie identyfikatora komputera nie powiodło się" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "Identyfikator komputera to %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "Identyfikator sesji to %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." -msgstr "Używanie folderu wykonywania %s." +msgstr "Używanie katalogu wykonywania %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." -msgstr "Używanie folderu stanu %s." +msgstr "Używanie katalogu stanu %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." -msgstr "Używanie folderu modułów %s." +msgstr "Używanie katalogu modułów %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Uruchamianie w trybie systemowym: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -368,48 +368,48 @@ msgid "" msgstr "" "OK, więc PA jest uruchomione w trybie systemowym. Proszę zauważyć, że " "prawdopodobnie tak nie powinno być.\n" -"Jeśli mimo to tak jest, to twoja wina, jeśli coś nie działa tak jak " +"Jeśli mimo to tak jest, to wina użytkownika, jeśli coś nie działa tak jak " "powinno.\n" "Proszę przeczytać http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode, " "gdzie wyjaśniono, dlaczego tryb systemowy jest zwykle złym pomysłem." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() nie powiodło się." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Świeże zegary o wysokiej rozdzielczości! Smacznego!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "" -"Koleś, twoje jądro śmierdzi! Szef kuchni poleca dzisiaj Linuksa w włączonymi " +"Koleś, twoje jądro śmierdzi! Szef kuchni poleca dzisiaj Linuksa z włączonymi " "zegarami o wysokiej rozdzielczości!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() nie powiodło się." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Zainicjowanie demona nie powiodło się." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Uruchamianie demona bez żadnych wczytanych modułów, odmawianie pracy." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." -msgstr "Zakończono uruchamianie demona." +msgstr "Ukończono uruchamianie demona." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Zainicjowano wyłączenie demona." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Demon został zniszczony." @@ -565,11 +565,11 @@ msgstr "" #: ../src/daemon/cmdline.c:247 msgid "--daemonize expects boolean argument" -msgstr "--daemonize oczekuje parametru w postaci zmiennej logicznej" +msgstr "--daemonize oczekuje parametru zmiennej logicznej" #: ../src/daemon/cmdline.c:254 msgid "--fail expects boolean argument" -msgstr "--fail oczekuje parametru w postaci zmiennej logicznej" +msgstr "--fail oczekuje parametru zmiennej logicznej" #: ../src/daemon/cmdline.c:264 msgid "" @@ -1138,7 +1138,7 @@ msgstr "XOpenDisplay() nie powiodło się" #: ../src/pulse/client-conf-x11.c:93 msgid "Failed to parse cookie data" -msgstr "Analiza danych ciasteczka nie powiodło się" +msgstr "Przetworzenie danych ciasteczka nie powiodło się" #: ../src/pulse/client-conf.c:111 #, c-format @@ -1147,7 +1147,7 @@ msgstr "Otwarcie pliku konfiguracji \"%s\" nie powiodło się: %s" #: ../src/pulse/context.c:550 msgid "No cookie loaded. Attempting to connect without." -msgstr "Nie wczytano ciasteczka. Próbowanie połączenia się bez niego." +msgstr "Nie wczytano ciasteczka. Próba połączenia się bez niego." #: ../src/pulse/context.c:693 #, c-format @@ -1306,7 +1306,7 @@ msgstr "write() nie powiodło się: %s" #: ../src/utils/pacat.c:561 msgid "Got signal, exiting." -msgstr "Otrzymano sygnał, wyłączanie." +msgstr "Otrzymano sygnał, kończenie pracy." #: ../src/utils/pacat.c:575 #, c-format @@ -1609,7 +1609,7 @@ msgstr "Połączenie nie powiodło się: %s\n" #: ../src/utils/pasuspender.c:176 #, c-format msgid "Got SIGINT, exiting.\n" -msgstr "Otrzymano SIGINT, wyłączanie.\n" +msgstr "Otrzymano SIGINT, kończenie pracy.\n" #: ../src/utils/pasuspender.c:194 #, c-format @@ -2018,7 +2018,7 @@ msgstr "Przedwczesny koniec pliku" #: ../src/utils/pactl.c:863 msgid "Got SIGINT, exiting." -msgstr "Otrzymano SIGINT, wyłączanie." +msgstr "Otrzymano SIGINT, kończenie pracy." #: ../src/utils/pactl.c:869 #, c-format @@ -2218,7 +2218,7 @@ msgstr "" #: ../src/utils/pax11publish.c:94 #, c-format msgid "Failed to parse command line.\n" -msgstr "Analiza wiersza poleceń nie powiodła się.\n" +msgstr "Przetworzenie wiersza poleceń nie powiodła się.\n" #: ../src/utils/pax11publish.c:108 #, c-format @@ -2243,7 +2243,7 @@ msgstr "Ciasteczko: %s\n" #: ../src/utils/pax11publish.c:132 #, c-format msgid "Failed to parse cookie data\n" -msgstr "Analiza danych ciasteczka nie powiodła się\n" +msgstr "Przetworzenie danych ciasteczka nie powiodła się\n" #: ../src/utils/pax11publish.c:137 #, c-format @@ -2329,7 +2329,7 @@ msgid "" "returned 0 or another value < min_avail." msgstr "" "ALSA została wybudzona, aby zapisać nowe dane do urządzenia, ale nie było " -"nic do zapisania!\n" +"nic do zapisania.\n" "Prawdopodobnie jest to błąd w sterowniku ALSA \"%s\". Proszę zgłosić ten " "problem programistom ALSA.\n" "Wybudzono za pomocą ustawienia POLLOUT - ale jednoczesne wywołanie " @@ -2346,7 +2346,7 @@ msgid "" "returned 0 or another value < min_avail." msgstr "" "ALSA została wybudzona, aby odczytać nowe dane z urządzenia, ale nie było " -"nic do odczytania!\n" +"nic do odczytania.\n" "Prawdopodobnie jest to błąd w sterowniku ALSA \"%s\". Proszę zgłosić ten " "problem programistom ALSA.\n" "Wybudzono za pomocą ustawienia POLLIN - ale jednoczesne wywołanie " @@ -2354,6 +2354,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Wyłącz" @@ -2372,3 +2373,221 @@ msgstr "Duplex telefoniczny (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "Serwer dźwięku PulseAudio" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Wewnętrzny dźwięk" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Puste wyjście" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -2,9 +2,9 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 07:34+0000\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: \n" -"Last-Translator: Ricardo Pinto <ricardo.bigote@gmail.com>\n" +"Last-Translator: Rui Gouveia <rui.gouveia@globaltek.pt>\n" "Language-Team: pt <fedora-trans-pt@redhat.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -12,8 +12,7 @@ msgstr "" "X-Poedit-Language: Portuguese\n" "X-Poedit-Country: PORTUGAL\n" -#: ../src/modules/alsa/alsa-util.c:858 -#: ../src/pulsecore/sink.c:2629 +#: ../src/modules/alsa/alsa-util.c:858 ../src/pulsecore/sink.c:2629 #, c-format msgid "%s %s" msgstr "%s %s" @@ -21,36 +20,47 @@ msgstr "%s %s" #: ../src/modules/alsa/alsa-util.c:1106 #, c-format msgid "" -"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers." +"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu " +"ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." msgstr "" -"snd_pcm_avail() retornou um valor excepcionalmente elevado: %lu bytes (%lu ms).\n" -"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este problema aos programadores do ALSA." +"snd_pcm_avail() retornou um valor excepcionalmente elevado: %lu bytes (%lu " +"ms).\n" +"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este " +"problema aos programadores do ALSA." #: ../src/modules/alsa/alsa-util.c:1147 #, c-format msgid "" -"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers." +"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%" +"lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." msgstr "" -"snd_pcm_delay() retornou um valor excepcionalmente elevado: %li bytes (%s%lu ms).\n" -"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este problema aos programadores do ALSA." +"snd_pcm_delay() retornou um valor excepcionalmente elevado: %li bytes (%s%lu " +"ms).\n" +"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este " +"problema aos programadores do ALSA." #: ../src/modules/alsa/alsa-util.c:1194 #, c-format msgid "" -"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers." +"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes " +"(%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." msgstr "" -"snd_pcm_mmap_begin() retornou um valor excepcionalmente elevado: %lu bytes (%lu ms).\n" -"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este problema aos programadores do ALSA." +"snd_pcm_mmap_begin() retornou um valor excepcionalmente elevado: %lu bytes (%" +"lu ms).\n" +"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este " +"problema aos programadores do ALSA." #: ../src/modules/module-always-sink.c:39 msgid "Always keeps at least one sink loaded even if it's a null one" msgstr "Mantém sempre pelo menos um depósito carregado mesmo que seja um nulo" #: ../src/modules/module-always-sink.c:83 -#, fuzzy msgid "Dummy Output" msgstr "Saída Dummy" @@ -59,8 +69,19 @@ msgid "Virtual LADSPA sink" msgstr "Depósito virtual LADSPA" #: ../src/modules/module-ladspa-sink.c:53 -msgid "sink_name=<name for the sink> sink_properties=<properties for the sink> master=<name of sink to filter> format=<sample format> rate=<sample rate> channels=<number of channels> channel_map=<channel map> plugin=<ladspa plugin name> label=<ladspa plugin label> control=<comma seperated list of input control values>" -msgstr "sink_name=<nome do depósito> sink_properties=<propriedades do depósito> master=<nome do depósito a filtrar> format=<formato exemplo> rate=<frequência de amostragem> channels=<número de canais> channel_map=<mapa de canais> plugin=<nome do plugin ladspa> label=<etiqueta do plugin ladspa> control=<Lista de valores de controlo de entrada separados por vírgulas>" +msgid "" +"sink_name=<name for the sink> sink_properties=<properties for the sink> " +"master=<name of sink to filter> format=<sample format> rate=<sample rate> " +"channels=<number of channels> channel_map=<channel map> plugin=<ladspa " +"plugin name> label=<ladspa plugin label> control=<comma seperated list of " +"input control values>" +msgstr "" +"sink_name=<nome do depósito> sink_properties=<propriedades do depósito> " +"master=<nome do depósito a filtrar> format=<formato exemplo> " +"rate=<frequência de amostragem> channels=<número de canais> " +"channel_map=<mapa de canais> plugin=<nome do plugin ladspa> label=<etiqueta " +"do plugin ladspa> control=<Lista de valores de controlo de entrada separados " +"por vírgulas>" #: ../src/modules/module-null-sink.c:55 msgid "Clocked NULL sink" @@ -124,8 +145,7 @@ msgstr "GID do utilizador '%s' e do grupo '%s' não coincidem." msgid "Home directory of user '%s' is not '%s', ignoring." msgstr "Directório pessoal do utilizador '%s' não é '%s'. A ignorar." -#: ../src/daemon/main.c:208 -#: ../src/daemon/main.c:213 +#: ../src/daemon/main.c:208 ../src/daemon/main.c:213 #, c-format msgid "Failed to create '%s': %s" msgstr "Falha ao criar o '%s': %s" @@ -158,220 +178,237 @@ msgstr "Modo de sistema não suportado nesta plataforma." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) falhou: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Não foi possível processar linha de comando." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Serviço não está a executar" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Serviço a executar como PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Tentativa de matar serviço falhou: %s" -#: ../src/daemon/main.c:566 -msgid "This program is not intended to be run as root (unless --system is specified)." -msgstr "Este programa não pretende ser executado como root (a não ser que a opção --system seja especificada)." +#: ../src/daemon/main.c:571 +msgid "" +"This program is not intended to be run as root (unless --system is " +"specified)." +msgstr "" +"Este programa não pretende ser executado como root (a não ser que a opção --" +"system seja especificada)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "São necessários privilégios de root." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start não é suportado para instâncias do sistema." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "A executar em modo de sistema, mas --disallow-exit não está definido!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" -msgstr "A executar em modo de sistema, mas --disallow-module-loading não está definido!" +msgstr "" +"A executar em modo de sistema, mas --disallow-module-loading não está " +"definido!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "A executar em modo de sistema, a forçar a desactivação do modo SHM!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" -msgstr "A executar em modo de sistema, a forçar a desactivação da saída por inactividade!" +msgstr "" +"A executar em modo de sistema, a forçar a desactivação da saída por " +"inactividade!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Não foi possível adquirir o stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe falhou: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() falhou: %s" -#: ../src/daemon/main.c:641 -#: ../src/utils/pacat.c:504 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() falhou: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Arranque do serviço falhou." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Arranque do serviço sucedeu." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Isto é PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Máquina de compilação: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS utilizadas na compilação: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "A executar na máquina: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Foram encontrados %u CPUs." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Tamanho da página é %lu bytes" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Compilado com suporte para Valgrind: sim" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Compilado com suporte para Valgrind: não" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "A executar em modo \"valgrind\": %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimizado: sim" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Compilação optimizada: não" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definido, todas as declarações desactivadas." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH definido, apenas as declarações \"fast path\" desactivadas." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Todas as declarações desactivadas." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "A tentativa de ler o ID da máquina falhou" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "O ID da máquina é %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "O ID da sessão é %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Execução a utilizar o directório %s" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "A manter o estado no directório %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "A utilizar o directório de módulos %s" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Execução em modo de sistema: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" -"OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n" -"If you do it nonetheless then it's your own fault if things don't work as expected.\n" -"Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea." +"OK, so you are running PA in system mode. Please note that you most likely " +"shouldn't be doing that.\n" +"If you do it nonetheless then it's your own fault if things don't work as " +"expected.\n" +"Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an " +"explanation why system mode is usually a bad idea." msgstr "" -"Ok, então está a correr PA em modo de sistema. Por favor repare que não deveria estar a fazê-lo.\n" -"Se, na mesma, o continuar a fazer e as coisas não correrem como esperado, a culpa será sua.\n" -"Por favor leia http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode para uma explicação de como o modo de sistema é usualmente uma má ideia." - -#: ../src/daemon/main.c:804 +"Ok, então está a correr PA em modo de sistema. Por favor repare que não " +"deveria estar a fazê-lo.\n" +"Se, na mesma, o continuar a fazer e as coisas não correrem como esperado, a " +"culpa será sua.\n" +"Por favor leia http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode para uma " +"explicação de como o modo de sistema é usualmente uma má ideia." + +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() falhou." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Timer \"frescos\" de alta resolução disponíveis. Bom apetite!" -#: ../src/daemon/main.c:816 -msgid "Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!" -msgstr "Oh pá, o teu kernel não presta! O prato do dia recomendado é Linux com timers de alta resolução activos!" +#: ../src/daemon/main.c:821 +msgid "" +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-" +"resolution timers enabled!" +msgstr "" +"Oh pá, o teu kernel não presta! O prato do dia recomendado é Linux com " +"timers de alta resolução activos!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() falhou." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Falha ao inicializar serviço." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Serviço arrancou sem módulos carregados. A recusar trabalhar." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Arranque do serviço completo." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Encerramento do serviço iniciado." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Serviço terminado." @@ -386,37 +423,48 @@ msgid "" " --dump-conf Dump default configuration\n" " --dump-modules Dump list of available modules\n" " --dump-resample-methods Dump available resample methods\n" -" --cleanup-shm Cleanup stale shared memory segments\n" -" --start Start the daemon if it is not running\n" +" --cleanup-shm Cleanup stale shared memory " +"segments\n" +" --start Start the daemon if it is not " +"running\n" " -k --kill Kill a running daemon\n" -" --check Check for a running daemon (only returns exit code)\n" +" --check Check for a running daemon (only " +"returns exit code)\n" "\n" "OPTIONS:\n" " --system[=BOOL] Run as system-wide instance\n" " -D, --daemonize[=BOOL] Daemonize after startup\n" " --fail[=BOOL] Quit when startup fails\n" " --high-priority[=BOOL] Try to set high nice level\n" -" (only available as root, when SUID or\n" +" (only available as root, when SUID " +"or\n" " with elevated RLIMIT_NICE)\n" " --realtime[=BOOL] Try to enable realtime scheduling\n" -" (only available as root, when SUID or\n" +" (only available as root, when SUID " +"or\n" " with elevated RLIMIT_RTPRIO)\n" -" --disallow-module-loading[=BOOL] Disallow module user requested module\n" +" --disallow-module-loading[=BOOL] Disallow module user requested " +"module\n" " loading/unloading after startup\n" " --disallow-exit[=BOOL] Disallow user requested exit\n" -" --exit-idle-time=SECS Terminate the daemon when idle and this\n" +" --exit-idle-time=SECS Terminate the daemon when idle and " +"this\n" " time passed\n" -" --module-idle-time=SECS Unload autoloaded modules when idle and\n" +" --module-idle-time=SECS Unload autoloaded modules when idle " +"and\n" " this time passed\n" -" --scache-idle-time=SECS Unload autoloaded samples when idle and\n" +" --scache-idle-time=SECS Unload autoloaded samples when idle " +"and\n" " this time passed\n" " --log-level[=LEVEL] Increase or set verbosity level\n" " -v Increase the verbosity level\n" " --log-target={auto,syslog,stderr} Specify the log target\n" -" --log-meta[=BOOL] Include code location in log messages\n" +" --log-meta[=BOOL] Include code location in log " +"messages\n" " --log-time[=BOOL] Include timestamps in log messages\n" " --log-backtrace=FRAMES Include a backtrace in log messages\n" -" -p, --dl-search-path=PATH Set the search path for dynamic shared\n" +" -p, --dl-search-path=PATH Set the search path for dynamic " +"shared\n" " objects (plugins)\n" " --resample-method=METHOD Use the specified resampling method\n" " (See --dump-resample-methods for\n" @@ -427,10 +475,12 @@ msgid "" " --disable-shm[=BOOL] Disable shared memory support.\n" "\n" "STARTUP SCRIPT:\n" -" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module with\n" +" -L, --load=\"MODULE ARGUMENTS\" Load the specified plugin module " +"with\n" " the specified argument\n" " -F, --file=FILENAME Run the specified script\n" -" -C Open a command line on the running TTY\n" +" -C Open a command line on the running " +"TTY\n" " after startup\n" "\n" " -n Don't load default script file\n" @@ -441,52 +491,77 @@ msgstr "" " -h, --help Mostra esta ajuda\n" " --version Mostra versão\n" " --dump-conf Despeja configuração por omissão\n" -" --dump-modules Despeja lista de módulos disponíveis\n" -" --dump-resample-methods Despeja métodos \"resample\" disponíveis\n" -" --cleanup-shm Limpar segmentos de memória partilhados encravados\n" -" --start Inicia o serviço, se ainda não estiver a executar\n" -" -k --kill Termina o serviço, se estiver a executar \n" -" --check Verifica se o serviço está a executar (apenas retorna um código de saída)\n" +" --dump-modules Despeja lista de módulos " +"disponíveis\n" +" --dump-resample-methods Despeja métodos \"resample\" " +"disponíveis\n" +" --cleanup-shm Limpar segmentos de memória " +"partilhados encravados\n" +" --start Inicia o serviço, se ainda não " +"estiver a executar\n" +" -k --kill Termina o serviço, se estiver a " +"executar \n" +" --check Verifica se o serviço está a " +"executar (apenas retorna um código de saída)\n" "\n" "OPTIONS:\n" " --system[=BOOL] Executa em modo de sistema\n" " -D, --daemonize[=BOOL] Passa a serviço depois de executar\n" " --fail[=BOOL] Termina quando o arranque falha\n" -" --high-priority[=BOOL] Tenta definir um alto nível de execução\n" -" (apenas disponível como root, quando é SUID ou\n" +" --high-priority[=BOOL] Tenta definir um alto nível de " +"execução\n" +" (apenas disponível como root, quando " +"é SUID ou\n" " com níveis elevados de RLIMIT_NICE)\n" -" --realtime[=BOOL] Tenta activar escalonamento em tempo real\n" -" (apenas disponível como root, quando é SUID ou\n" -" com níveis elevados de RLIMIT_RTPRIO)\n" -" --disallow-module-loading[=BOOL] Desautoriza o carregamento/descarregamento\n" -" de módulos, pelo utilizador, depois do arranque\n" -" --disallow-exit[=BOOL] Desautoriza pedidos de saída do utilizador\n" -" --exit-idle-time=SECS Termina o serviço quando inactivo e já passou\n" +" --realtime[=BOOL] Tenta activar escalonamento em tempo " +"real\n" +" (apenas disponível como root, quando " +"é SUID ou\n" +" com níveis elevados de " +"RLIMIT_RTPRIO)\n" +" --disallow-module-loading[=BOOL] Desautoriza o carregamento/" +"descarregamento\n" +" de módulos, pelo utilizador, depois " +"do arranque\n" +" --disallow-exit[=BOOL] Desautoriza pedidos de saída do " +"utilizador\n" +" --exit-idle-time=SECS Termina o serviço quando inactivo e " +"já passou\n" " este tempo\n" -" --module-idle-time=SECS Descarregar módulos de carregamento automático quando inactivo e\n" +" --module-idle-time=SECS Descarregar módulos de carregamento " +"automático quando inactivo e\n" " passou este tempo\n" -" --scache-idle-time=SECS Descarregar amostras de carregamento automático quando inactivas e\n" +" --scache-idle-time=SECS Descarregar amostras de carregamento " +"automático quando inactivas e\n" " passou este tempo\n" -" --log-level[=LEVEL] Aumenta ou define o nível de verbosidade\n" +" --log-level[=LEVEL] Aumenta ou define o nível de " +"verbosidade\n" " -v Aumenta o nível de verbosidade\n" " --log-target={auto,syslog,stderr} Especifica o ficheiro de registo\n" -" --log-meta[=BOOL] Inclui código de localização na mensagem de registo\n" +" --log-meta[=BOOL] Inclui código de localização na " +"mensagem de registo\n" " --log-time[=BOOL] Inclui tempo na mensagem de registo\n" -" --log-backtrace=FRAMES Inclui informação de tracagem na mensagem de registo\n" -" -p, --dl-search-path=PATH Define o caminho de procura para os plugins partilhados dinâmicos\n" -" --resample-method=METHOD Utilizar o método de \"resampling\" especificado\n" +" --log-backtrace=FRAMES Inclui informação de tracagem na " +"mensagem de registo\n" +" -p, --dl-search-path=PATH Define o caminho de procura para os " +"plugins partilhados dinâmicos\n" +" --resample-method=METHOD Utilizar o método de \"resampling\" " +"especificado\n" " (Ver --dump-resample-methods para\n" " possíveis valores)\n" " --use-pid-file[=BOOL] Criar um ficheiro com o PID\n" -" --no-cpu-limit[=BOOL] Não instala limitadores de load no CPU em\n" +" --no-cpu-limit[=BOOL] Não instala limitadores de load no " +"CPU em\n" " plataformas que o suportam.\n" -" --disable-shm[=BOOL] Desactivar suporte para memória partilhada.\n" +" --disable-shm[=BOOL] Desactivar suporte para memória " +"partilhada.\n" "\n" "STARTUP SCRIPT:\n" " -L, --load=\"MODULE ARGUMENTS\" Carrega o módulo especificado com\n" " o argumento especificado\n" " -F, --file=FILENAME Executa o script especificado\n" -" -C Abre uma linha de comando no TTY (consola) em execução\n" +" -C Abre uma linha de comando no TTY " +"(consola) em execução\n" " depois do arranque\n" "\n" " -n Não carrega o script por omissão\n" @@ -500,8 +575,12 @@ msgid "--fail expects boolean argument" msgstr "--fail espera argumento booleano" #: ../src/daemon/cmdline.c:264 -msgid "--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)." -msgstr "--log-level espera um argumento para o nível de log (numérico no intervalo 0..4 ou um dos seguintes: debug, info, notice, warn, error)." +msgid "" +"--log-level expects log level argument (either numeric in range 0..4 or one " +"of debug, info, notice, warn, error)." +msgstr "" +"--log-level espera um argumento para o nível de log (numérico no intervalo " +"0..4 ou um dos seguintes: debug, info, notice, warn, error)." #: ../src/daemon/cmdline.c:276 msgid "--high-priority expects boolean argument" @@ -525,7 +604,9 @@ msgstr "--use-pid-file espera argumento booleano" #: ../src/daemon/cmdline.c:321 msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'." -msgstr "Destino de ficheiro de registo inválido: utilize 'syslog', 'stderr' ou 'auto'." +msgstr "" +"Destino de ficheiro de registo inválido: utilize 'syslog', 'stderr' ou " +"'auto'." #: ../src/daemon/cmdline.c:328 msgid "--log-time expects boolean argument" @@ -588,9 +669,9 @@ msgid "Load Once: %s\n" msgstr "Carregar Uma Vez: %s\n" #: ../src/daemon/dumpmodules.c:75 -#, fuzzy, c-format +#, c-format msgid "DEPRECATION WARNING: %s\n" -msgstr "AVISO DE DEPRECATION WARNING: %s\n" +msgstr "AVISO DE DESCONTINUIDADE: %s\n" #: ../src/daemon/dumpmodules.c:79 #, c-format @@ -663,8 +744,12 @@ msgid "Failed to open configuration file: %s" msgstr "Falha ao abrir ficheiro de configuração: %s" #: ../src/daemon/daemon-conf.c:562 -msgid "The specified default channel map has a different number of channels than the specified default number of channels." -msgstr "O mapa de canais especificado tem um número de canais diferente do número de canais definido por omissão." +msgid "" +"The specified default channel map has a different number of channels than " +"the specified default number of channels." +msgstr "" +"O mapa de canais especificado tem um número de canais diferente do número de " +"canais definido por omissão." #: ../src/daemon/daemon-conf.c:638 #, c-format @@ -683,8 +768,7 @@ msgstr "Sistema de Som PulseAudio" msgid "Start the PulseAudio Sound System" msgstr "Inciar o Sistema de Som PulseAudio" -#: ../src/pulse/channelmap.c:105 -#: ../src/pulse/channelmap.c:757 +#: ../src/pulse/channelmap.c:105 ../src/pulse/channelmap.c:757 msgid "Mono" msgstr "Mono" @@ -888,12 +972,9 @@ msgstr "Topo Traseira Esquerda" msgid "Top Rear Right" msgstr "Topo Traseira Direita" -#: ../src/pulse/channelmap.c:484 -#: ../src/pulse/sample.c:170 -#: ../src/pulse/volume.c:295 -#: ../src/pulse/volume.c:321 -#: ../src/pulse/volume.c:341 -#: ../src/pulse/volume.c:371 +#: ../src/pulse/channelmap.c:484 ../src/pulse/sample.c:170 +#: ../src/pulse/volume.c:295 ../src/pulse/volume.c:321 +#: ../src/pulse/volume.c:341 ../src/pulse/volume.c:371 msgid "(invalid)" msgstr "(inválido)" @@ -1054,8 +1135,7 @@ msgstr "%.1f KiB" msgid "%u B" msgstr "%u B" -#: ../src/pulse/client-conf-x11.c:55 -#: ../src/utils/pax11publish.c:100 +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100 msgid "XOpenDisplay() failed" msgstr "XOpenDisplay() falhou" @@ -1082,7 +1162,7 @@ msgstr "fork(): %s" msgid "waitpid(): %s" msgstr "waitpid(): %s" -#: ../src/pulse/context.c:1435 +#: ../src/pulse/context.c:1438 #, c-format msgid "Received message for unknown extension '%s'" msgstr "Recebida mensagem para extensão desconhecida '%s'" @@ -1115,8 +1195,7 @@ msgstr "pa_stream_write() falhou: %s" msgid "pa_stream_begin_write() failed: %s" msgstr "pa_stream_write() falhou: %s" -#: ../src/utils/pacat.c:237 -#: ../src/utils/pacat.c:267 +#: ../src/utils/pacat.c:237 ../src/utils/pacat.c:267 #, c-format msgid "pa_stream_peek() failed: %s" msgstr "pa_stream_peek() falhou: %s" @@ -1204,51 +1283,50 @@ msgstr "Ligação estabelecida.%s" msgid "pa_stream_new() failed: %s" msgstr "pa_stream_new() falhou: %s" -#: ../src/utils/pacat.c:446 +#: ../src/utils/pacat.c:450 #, c-format msgid "pa_stream_connect_playback() failed: %s" msgstr "pa_stream_connect_playback() falhou: %s" -#: ../src/utils/pacat.c:452 +#: ../src/utils/pacat.c:456 #, c-format msgid "pa_stream_connect_record() failed: %s" msgstr "pa_stream_connect_record() falhou: %s" -#: ../src/utils/pacat.c:466 -#: ../src/utils/pactl.c:857 +#: ../src/utils/pacat.c:470 ../src/utils/pactl.c:857 #, c-format msgid "Connection failure: %s" msgstr "Ligação falhou: %s" -#: ../src/utils/pacat.c:499 +#: ../src/utils/pacat.c:503 msgid "Got EOF." msgstr "Obtive EOF." -#: ../src/utils/pacat.c:536 +#: ../src/utils/pacat.c:540 #, c-format msgid "write() failed: %s" msgstr "write() falhou: %s" -#: ../src/utils/pacat.c:557 +#: ../src/utils/pacat.c:561 msgid "Got signal, exiting." msgstr "Recebido sinal, a sair." -#: ../src/utils/pacat.c:571 +#: ../src/utils/pacat.c:575 #, c-format msgid "Failed to get latency: %s" msgstr "Falhou a obtenção da cadência: %s" -#: ../src/utils/pacat.c:576 +#: ../src/utils/pacat.c:580 #, c-format msgid "Time: %0.3f sec; Latency: %0.0f usec." msgstr "Tempo: %0.3f sec; Cadência: %0.0f usec." -#: ../src/utils/pacat.c:595 +#: ../src/utils/pacat.c:599 #, c-format msgid "pa_stream_update_timing_info() failed: %s" msgstr "pa_stream_update_timing_info() falhou: %s" -#: ../src/utils/pacat.c:605 +#: ../src/utils/pacat.c:609 #, c-format msgid "" "%s [options]\n" @@ -1261,29 +1339,48 @@ msgid "" "\n" " -v, --verbose Enable verbose operations\n" "\n" -" -s, --server=SERVER The name of the server to connect to\n" -" -d, --device=DEVICE The name of the sink/source to connect to\n" -" -n, --client-name=NAME How to call this client on the server\n" -" --stream-name=NAME How to call this stream on the server\n" -" --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" -" --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" -" --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n" -" float32be, ulaw, alaw, s32le, s32be, s24le, s24be,\n" -" s24-32le, s24-32be (defaults to s16ne)\n" -" --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -d, --device=DEVICE The name of the sink/source to " +"connect to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" +" --stream-name=NAME How to call this stream on the " +"server\n" +" --volume=VOLUME Specify the initial (linear) volume " +"in range 0...65536\n" +" --rate=SAMPLERATE The sample rate in Hz (defaults to " +"44100)\n" +" --format=SAMPLEFORMAT The sample type, one of s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be, " +"s24le, s24be,\n" +" s24-32le, s24-32be (defaults to " +"s16ne)\n" +" --channels=CHANNELS The number of channels, 1 for mono, " +"2 for stereo\n" " (defaults to 2)\n" -" --channel-map=CHANNELMAP Channel map to use instead of the default\n" -" --fix-format Take the sample format from the sink the stream is\n" +" --channel-map=CHANNELMAP Channel map to use instead of the " +"default\n" +" --fix-format Take the sample format from the sink " +"the stream is\n" " being connected to.\n" -" --fix-rate Take the sampling rate from the sink the stream is\n" +" --fix-rate Take the sampling rate from the sink " +"the stream is\n" " being connected to.\n" -" --fix-channels Take the number of channels and the channel map\n" -" from the sink the stream is being connected to.\n" +" --fix-channels Take the number of channels and the " +"channel map\n" +" from the sink the stream is being " +"connected to.\n" " --no-remix Don't upmix or downmix channels.\n" -" --no-remap Map channels by index instead of name.\n" -" --latency=BYTES Request the specified latency in bytes.\n" -" --process-time=BYTES Request the specified process time per request in bytes.\n" -" --property=PROPERTY=VALUE Set the specified property to the specified value.\n" +" --no-remap Map channels by index instead of " +"name.\n" +" --latency=BYTES Request the specified latency in " +"bytes.\n" +" --process-time=BYTES Request the specified process time " +"per request in bytes.\n" +" --property=PROPERTY=VALUE Set the specified property to the " +"specified value.\n" " --raw Record/play raw PCM data.\n" " --file-format=FFORMAT Record/play formatted PCM data.\n" " --list-file-formats List available file formats.\n" @@ -1300,32 +1397,50 @@ msgstr "" "\n" " -s, --server=SERVER Nome do servidor a qual ligar\n" " -d, --device=DEVICE Nome do depósito/fonte a qual ligar\n" -" -n, --client-name=NAME Como chamar este cliente no servidor\n" +" -n, --client-name=NAME Como chamar este cliente no " +"servidor\n" " --stream-name=NAME Como chamar este fluxo no servidor\n" -" --volume=VOLUME Especificar o volume (linear) inicial na gama 0...65536\n" -" --rate=SAMPLERATE A mesma taxa em Hz (por omissão 44100)\n" -" --format=SAMPLEFORMAT Tipo de amostragem, uma de s16le, s16be, u8, float32le,\n" -" float32be, ulaw, alaw, s32le, s32be, s24le, s24be,\n" -" s24-32le, s24-32be (por omissão s16ne)\n" -" --channels=CHANNELS Número de canais, 1 para mono, 2 para estéreo\n" +" --volume=VOLUME Especificar o volume (linear) " +"inicial na gama 0...65536\n" +" --rate=SAMPLERATE A mesma taxa em Hz (por omissão " +"44100)\n" +" --format=SAMPLEFORMAT Tipo de amostragem, uma de s16le, " +"s16be, u8, float32le,\n" +" float32be, ulaw, alaw, s32le, s32be, " +"s24le, s24be,\n" +" s24-32le, s24-32be (por omissão " +"s16ne)\n" +" --channels=CHANNELS Número de canais, 1 para mono, 2 " +"para estéreo\n" " (por omissão 2)\n" -" --channel-map=CHANNELMAP Mapa de canais a usar em vez do mapa por omissão\n" -" --fix-format Usa o formato de amostragem do depósito para\n" +" --channel-map=CHANNELMAP Mapa de canais a usar em vez do mapa " +"por omissão\n" +" --fix-format Usa o formato de amostragem do " +"depósito para\n" " onde o fluxo está a ligado.\n" -" --fix-rate Usa a taxa de amostragem do depósito para\n" +" --fix-rate Usa a taxa de amostragem do depósito " +"para\n" " onde o fluxo está ligado.\n" -" --fix-channels Pega no número de canais e no mapa de canais\n" -" do depósito para onde o fluxo está ligado.\n" -" --no-remix Não misturar os canais em cima nem em baixo.\n" -" --no-remap Mapeia os canais por índice em vez do nome.\n" -" --latency=BYTES Pede a cadência especificada em bytes.\n" -" --process-time=BYTES Pede o tempo de processo por pedido em bytes.\n" -" --property=PROPERTY=VALUE Coloca a propriedade específica com o valor especificado.\n" +" --fix-channels Pega no número de canais e no mapa " +"de canais\n" +" do depósito para onde o fluxo está " +"ligado.\n" +" --no-remix Não misturar os canais em cima nem " +"em baixo.\n" +" --no-remap Mapeia os canais por índice em vez " +"do nome.\n" +" --latency=BYTES Pede a cadência especificada em " +"bytes.\n" +" --process-time=BYTES Pede o tempo de processo por pedido " +"em bytes.\n" +" --property=PROPERTY=VALUE Coloca a propriedade específica com " +"o valor especificado.\n" " --raw Grava/Lê dados raw em PCM.\n" " --file-format=FFORMAT Grava/Lê dados formatados em PCM.\n" -" --list-file-formats Lista o formato de ficheiros disponíveis.\n" +" --list-file-formats Lista o formato de ficheiros " +"disponíveis.\n" -#: ../src/utils/pacat.c:727 +#: ../src/utils/pacat.c:731 #, c-format msgid "" "pacat %s\n" @@ -1336,128 +1451,128 @@ msgstr "" "Compilado com libpulse %s\n" "Ligado com libpulse %s\n" -#: ../src/utils/pacat.c:760 -#: ../src/utils/pactl.c:953 +#: ../src/utils/pacat.c:764 ../src/utils/pactl.c:953 #, c-format msgid "Invalid client name '%s'" msgstr "Nome de cliente inválido '%s'" -#: ../src/utils/pacat.c:775 +#: ../src/utils/pacat.c:779 #, c-format msgid "Invalid stream name '%s'" msgstr "Nome de fluxo inválido '%s'" -#: ../src/utils/pacat.c:812 +#: ../src/utils/pacat.c:816 #, c-format msgid "Invalid channel map '%s'" msgstr "Mapa de canais inválido '%s'" -#: ../src/utils/pacat.c:841 +#: ../src/utils/pacat.c:845 #, c-format msgid "Invalid latency specification '%s'" msgstr "Especificação da cadência inválida '%s'" -#: ../src/utils/pacat.c:848 +#: ../src/utils/pacat.c:852 #, c-format msgid "Invalid process time specification '%s'" msgstr "Especificação de tempo de processamento inválido '%s'" -#: ../src/utils/pacat.c:860 +#: ../src/utils/pacat.c:864 #, c-format msgid "Invalid property '%s'" msgstr "Propriedade inválida '%s'" -#: ../src/utils/pacat.c:877 +#: ../src/utils/pacat.c:881 #, c-format msgid "Unknown file format %s." msgstr "Formato de ficheiro desconhecido %s." -#: ../src/utils/pacat.c:896 +#: ../src/utils/pacat.c:900 msgid "Invalid sample specification" msgstr "Especificação de amostra inválida" -#: ../src/utils/pacat.c:906 +#: ../src/utils/pacat.c:910 #, c-format msgid "open(): %s" msgstr "open(): %s" -#: ../src/utils/pacat.c:911 +#: ../src/utils/pacat.c:915 #, c-format msgid "dup2(): %s" msgstr "dup2(): %s" -#: ../src/utils/pacat.c:918 +#: ../src/utils/pacat.c:922 msgid "Too many arguments." msgstr "Demasiados argumentos." -#: ../src/utils/pacat.c:929 +#: ../src/utils/pacat.c:933 msgid "Failed to generate sample specification for file." msgstr "Falha ao gerar especificação de amostra para o ficheiro." -#: ../src/utils/pacat.c:949 +#: ../src/utils/pacat.c:953 msgid "Failed to open audio file." msgstr "Falha ao abrir ficheiro de audio" -#: ../src/utils/pacat.c:955 -msgid "Warning: specified sample specification will be overwritten with specification from file." -msgstr "Aviso: a especificação da amostra será sobrescrita com a especificação do ficheiro." +#: ../src/utils/pacat.c:959 +msgid "" +"Warning: specified sample specification will be overwritten with " +"specification from file." +msgstr "" +"Aviso: a especificação da amostra será sobrescrita com a especificação do " +"ficheiro." -#: ../src/utils/pacat.c:958 -#: ../src/utils/pactl.c:997 +#: ../src/utils/pacat.c:962 ../src/utils/pactl.c:997 msgid "Failed to determine sample specification from file." msgstr "Falha ao determinar a especificação da amostra a partir do ficheiro." -#: ../src/utils/pacat.c:967 +#: ../src/utils/pacat.c:971 msgid "Warning: Failed to determine channel map from file." msgstr "Aviso: Falha a determinar o mapa de canal do ficheiro." -#: ../src/utils/pacat.c:978 +#: ../src/utils/pacat.c:982 msgid "Channel map doesn't match sample specification" msgstr "Mapa de canais não corresponde à especificação da amostra" -#: ../src/utils/pacat.c:989 +#: ../src/utils/pacat.c:993 msgid "Warning: failed to write channel map to file." msgstr "Aviso: falha na escrita do mapa de canais no ficheiro." -#: ../src/utils/pacat.c:1004 +#: ../src/utils/pacat.c:1008 #, c-format -msgid "Opening a %s stream with sample specification '%s' and channel map '%s'." -msgstr "Abrindo um %s fluxo com especificação da amostra '%s' e mapa de canais '%s'." +msgid "" +"Opening a %s stream with sample specification '%s' and channel map '%s'." +msgstr "" +"Abrindo um %s fluxo com especificação da amostra '%s' e mapa de canais '%s'." -#: ../src/utils/pacat.c:1005 +#: ../src/utils/pacat.c:1009 msgid "recording" msgstr "a gravar" -#: ../src/utils/pacat.c:1005 +#: ../src/utils/pacat.c:1009 msgid "playback" msgstr "reprodução" -#: ../src/utils/pacat.c:1031 -#: ../src/utils/pactl.c:1267 +#: ../src/utils/pacat.c:1035 ../src/utils/pactl.c:1267 msgid "pa_mainloop_new() failed." msgstr "pa_mainloop_new() falhou." -#: ../src/utils/pacat.c:1050 +#: ../src/utils/pacat.c:1054 msgid "io_new() failed." msgstr "io_new() falhou." -#: ../src/utils/pacat.c:1057 -#: ../src/utils/pactl.c:1279 +#: ../src/utils/pacat.c:1061 ../src/utils/pactl.c:1279 msgid "pa_context_new() failed." msgstr "pa_context_new() falhou." -#: ../src/utils/pacat.c:1065 -#: ../src/utils/pactl.c:1285 +#: ../src/utils/pacat.c:1069 ../src/utils/pactl.c:1285 #, c-format msgid "pa_context_connect() failed: %s" msgstr "pa_context_connect() falhou: %s" -#: ../src/utils/pacat.c:1071 +#: ../src/utils/pacat.c:1075 msgid "pa_context_rttime_new() failed." msgstr "pa_context_rttime_new() falhou." -#: ../src/utils/pacat.c:1078 -#: ../src/utils/pactl.c:1290 +#: ../src/utils/pacat.c:1082 ../src/utils/pactl.c:1290 msgid "pa_mainloop_run() failed." msgstr "pa_mainloop_run() falhou." @@ -1508,7 +1623,8 @@ msgid "" "\n" " -h, --help Show this help\n" " --version Show version\n" -" -s, --server=SERVER The name of the server to connect to\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" "\n" msgstr "" "%s [opções] ... \n" @@ -1557,7 +1673,8 @@ msgstr "Correntemente em uso: %u blocos contendo %s bytes no total.\n" #: ../src/utils/pactl.c:144 #, c-format msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n" -msgstr "Alocado durante todo o tempo de vida: %u blocos contendo %s bytes no total.\n" +msgstr "" +"Alocado durante todo o tempo de vida: %u blocos contendo %s bytes no total.\n" #: ../src/utils/pactl.c:147 #, c-format @@ -1636,14 +1753,12 @@ msgstr "" "\tPropriedades:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:268 -#: ../src/utils/pactl.c:360 +#: ../src/utils/pactl.c:268 ../src/utils/pactl.c:360 #, c-format msgid "\tPorts:\n" msgstr "\tPorto:\n" -#: ../src/utils/pactl.c:274 -#: ../src/utils/pactl.c:366 +#: ../src/utils/pactl.c:274 ../src/utils/pactl.c:366 #, c-format msgid "\tActive Port: %s\n" msgstr "\tPorto Activo: %s\n" @@ -1692,18 +1807,10 @@ msgstr "" "\tPropriedades:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:345 -#: ../src/utils/pactl.c:401 -#: ../src/utils/pactl.c:436 -#: ../src/utils/pactl.c:473 -#: ../src/utils/pactl.c:532 -#: ../src/utils/pactl.c:533 -#: ../src/utils/pactl.c:543 -#: ../src/utils/pactl.c:587 -#: ../src/utils/pactl.c:588 -#: ../src/utils/pactl.c:594 -#: ../src/utils/pactl.c:637 -#: ../src/utils/pactl.c:638 +#: ../src/utils/pactl.c:345 ../src/utils/pactl.c:401 ../src/utils/pactl.c:436 +#: ../src/utils/pactl.c:473 ../src/utils/pactl.c:532 ../src/utils/pactl.c:533 +#: ../src/utils/pactl.c:543 ../src/utils/pactl.c:587 ../src/utils/pactl.c:588 +#: ../src/utils/pactl.c:594 ../src/utils/pactl.c:637 ../src/utils/pactl.c:638 #: ../src/utils/pactl.c:645 msgid "n/a" msgstr "n/d" @@ -1894,8 +2001,7 @@ msgstr "" "\tPropriedades:\n" "\t\t%s\n" -#: ../src/utils/pactl.c:653 -#: ../src/utils/pactl.c:663 +#: ../src/utils/pactl.c:653 ../src/utils/pactl.c:663 #, c-format msgid "Failure: %s" msgstr "Falha: %s" @@ -1941,8 +2047,10 @@ msgid "" " -h, --help Show this help\n" " --version Show version\n" "\n" -" -s, --server=SERVER The name of the server to connect to\n" -" -n, --client-name=NAME How to call this client on the server\n" +" -s, --server=SERVER The name of the server to connect " +"to\n" +" -n, --client-name=NAME How to call this client on the " +"server\n" msgstr "" "%s [opções] stat\n" "%s [opções] list\n" @@ -1970,7 +2078,8 @@ msgstr "" " --version Mostra a versão\n" "\n" " -s, --server=SERVER O nome do servidor ao qual ligar\n" -" -n, --client-name=NAME Como chamar este cliente no servidor\n" +" -n, --client-name=NAME Como chamar este cliente no " +"servidor\n" #: ../src/utils/pactl.c:933 #, c-format @@ -2020,12 +2129,19 @@ msgid "You have to specify a module index" msgstr "Tem de especificar um índice de módulo" #: ../src/utils/pactl.c:1090 -msgid "You may not specify more than one sink. You have to specify a boolean value." -msgstr "Não pode especificar mais do que um depósito. Tem de especificar um valor booleano." +msgid "" +"You may not specify more than one sink. You have to specify a boolean value." +msgstr "" +"Não pode especificar mais do que um depósito. Tem de especificar um valor " +"booleano." #: ../src/utils/pactl.c:1103 -msgid "You may not specify more than one source. You have to specify a boolean value." -msgstr "Não pode especificar mais do que uma fonte. Tem de especificar um valor booleano." +msgid "" +"You may not specify more than one source. You have to specify a boolean " +"value." +msgstr "" +"Não pode especificar mais do que uma fonte. Tem de especificar um valor " +"booleano." #: ../src/utils/pactl.c:1115 msgid "You have to specify a card name/index and a profile name" @@ -2043,12 +2159,9 @@ msgstr "Tem de especificar um nome/índice de fonte e nome de um porto" msgid "You have to specify a sink name/index and a volume" msgstr "Tem de especificar um nome/índice de depósito e um volume" -#: ../src/utils/pactl.c:1154 -#: ../src/utils/pactl.c:1171 -#: ../src/utils/pactl.c:1193 -#: ../src/utils/pactl.c:1209 -#: ../src/utils/pactl.c:1226 -#: ../src/utils/pactl.c:1248 +#: ../src/utils/pactl.c:1154 ../src/utils/pactl.c:1171 +#: ../src/utils/pactl.c:1193 ../src/utils/pactl.c:1209 +#: ../src/utils/pactl.c:1226 ../src/utils/pactl.c:1248 msgid "Invalid volume specification" msgstr "Especificação de volume inválida" @@ -2091,14 +2204,18 @@ msgid "" "\n" " -d Show current PulseAudio data attached to X11 display (default)\n" " -e Export local PulseAudio data to X11 display\n" -" -i Import PulseAudio data from X11 display to local environment variables and cookie file.\n" +" -i Import PulseAudio data from X11 display to local environment " +"variables and cookie file.\n" " -r Remove PulseAudio data from X11 display\n" msgstr "" -"%s [-D ecrã] [-S servidor] [-O depósito] [-I fonte] [-c ficheiro] [-d|-e|-i|-r]\n" +"%s [-D ecrã] [-S servidor] [-O depósito] [-I fonte] [-c ficheiro] [-d|-e|-" +"i|-r]\n" "\n" -" -d Mostra os dados correntes do PulseAudio anexados ao ecrã X11 (default)\n" +" -d Mostra os dados correntes do PulseAudio anexados ao ecrã X11 " +"(default)\n" " -e Exporta dados locais do PulseAudio para o ecrã X11\n" -" -i Importa dados do PulseAudio do ecrã X11 para variáveis de ambiente locais e ficheiro de cookies.\n" +" -i Importa dados do PulseAudio do ecrã X11 para variáveis de ambiente " +"locais e ficheiro de cookies.\n" " -r Remove dados do PulseAudio do ecrã X11\n" #: ../src/utils/pax11publish.c:94 @@ -2163,7 +2280,8 @@ msgstr "Ainda não implementado.\n" #: ../src/utils/pacmd.c:69 msgid "No PulseAudio daemon running, or not running as session daemon." -msgstr "Não existe um daemon PulseAudio a correr, ou não corre como daemon de sessão." +msgstr "" +"Não existe um daemon PulseAudio a correr, ou não corre como daemon de sessão." #: ../src/utils/pacmd.c:74 #, c-format @@ -2188,49 +2306,57 @@ msgstr "Serviço não responde." msgid "poll(): %s" msgstr "poll(): %s" -#: ../src/utils/pacmd.c:171 -#: ../src/utils/pacmd.c:188 +#: ../src/utils/pacmd.c:171 ../src/utils/pacmd.c:188 #, c-format msgid "read(): %s" msgstr "read(): %s" -#: ../src/utils/pacmd.c:207 -#: ../src/utils/pacmd.c:223 +#: ../src/utils/pacmd.c:207 ../src/utils/pacmd.c:223 #, c-format msgid "write(): %s" msgstr "write(): %s" -#: ../src/pulsecore/lock-autospawn.c:136 -#: ../src/pulsecore/lock-autospawn.c:219 +#: ../src/pulsecore/lock-autospawn.c:136 ../src/pulsecore/lock-autospawn.c:219 msgid "Cannot access autospawn lock." msgstr "Impossível aceder ao lock \"autospawn\"." -#: ../src/modules/alsa/alsa-sink.c:530 -#: ../src/modules/alsa/alsa-sink.c:689 +#: ../src/modules/alsa/alsa-sink.c:530 ../src/modules/alsa/alsa-sink.c:689 #, c-format msgid "" -"ALSA woke us up to write new data to the device, but there was actually nothing to write!\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n" -"We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail." +"ALSA woke us up to write new data to the device, but there was actually " +"nothing to write!\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers.\n" +"We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() " +"returned 0 or another value < min_avail." msgstr "" -"ALSA acordou-nos para escrever novos dados para o dispositivo, mas não havia nada para escrever!\n" -"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este problema aos programadores do ALSA.\n" -"Fomos acordados pelo conjunto POLLOUT -- contudo uma chamada a seguir de snd_pcm_avail() retornou 0 ou outro valor < min_avail." +"ALSA acordou-nos para escrever novos dados para o dispositivo, mas não havia " +"nada para escrever!\n" +"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este " +"problema aos programadores do ALSA.\n" +"Fomos acordados pelo conjunto POLLOUT -- contudo uma chamada a seguir de " +"snd_pcm_avail() retornou 0 ou outro valor < min_avail." -#: ../src/modules/alsa/alsa-source.c:506 -#: ../src/modules/alsa/alsa-source.c:656 +#: ../src/modules/alsa/alsa-source.c:506 ../src/modules/alsa/alsa-source.c:656 #, c-format msgid "" -"ALSA woke us up to read new data from the device, but there was actually nothing to read!\n" -"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.\n" -"We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail." +"ALSA woke us up to read new data from the device, but there was actually " +"nothing to read!\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers.\n" +"We were woken up with POLLIN set -- however a subsequent snd_pcm_avail() " +"returned 0 or another value < min_avail." msgstr "" -"ALSA acordou-nos para ler novos dados do dispositivo, mas não havia nada para ler!\n" -"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este problema aos programadores do ALSA.\n" -"Fomos acordados pelo conjunto POLLIN -- contudo uma chamada a seguir de snd_pcm_avail() retornou 0 ou outro valor < min_avail." +"ALSA acordou-nos para ler novos dados do dispositivo, mas não havia nada " +"para ler!\n" +"Provavelmente isto é um erro no driver ALSA '%s'. Por favor, reporte este " +"problema aos programadores do ALSA.\n" +"Fomos acordados pelo conjunto POLLIN -- contudo uma chamada a seguir de " +"snd_pcm_avail() retornou 0 ou outro valor < min_avail." #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Desligado" @@ -2250,6 +2376,231 @@ msgstr "Telefonia Duplex (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Servidor de Som PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "Entrada %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "Entrada %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Áudio Interno" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "Estéreo Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Saída nula" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "Estéreo Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "Analog Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "Analog Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Analog Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Analog Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "Analog Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "Estéreo Digital (IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "Surround Digital 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "Surround Digital 4.0 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "Surround Digital 5.1 (IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "Estéreo Digital (HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "Mono Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "Estéreo Analógico" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Estéreo Digital (IEC958)" + #, fuzzy #~ msgid "Invalid client name '%s'\n" #~ msgstr "Nome de máquina inválido" @@ -2257,125 +2608,138 @@ msgstr "Servidor de Som PulseAudio" #, fuzzy #~ msgid "Failed to determine sample specification from file.\n" #~ msgstr "não foi possível obter informações da amostra: %s\n" + #~ msgid "select(): %s" #~ msgstr "select(): %s" + #~ msgid "Cannot connect to system bus: %s" #~ msgstr "Incapaz de se ligar ao bus de sistema: %s" + #~ msgid "Cannot get caller from PID: %s" #~ msgstr "Não foi possível obter chamador a partir do PID: %s" + #~ msgid "Cannot set UID on caller object." #~ msgstr "Não foi possível definir o UID no objecto chamador." + #~ msgid "Failed to get CK session." #~ msgstr "Falha ao obter sessão CK." + #~ msgid "Cannot set UID on session object." #~ msgstr "Não foi possível definir o UID no objecto da sessão." + #~ msgid "Cannot allocate PolKitAction." #~ msgstr "Não é possível alocar PolKitAction." + #~ msgid "Cannot set action_id" #~ msgstr "impossível definir action_id" + #~ msgid "Cannot allocate PolKitContext." #~ msgstr "Não é possível alocar contexto PolKitContext." + #~ msgid "Cannot initialize PolKitContext: %s" #~ msgstr "Incapaz de inicializar o PolKitContext: %s" + #~ msgid "Could not determine whether caller is authorized: %s" #~ msgstr "Não foi possível determinar se o chamador está autorizado: %s" + #~ msgid "Cannot obtain auth: %s" #~ msgstr "Não foi possível obter autenticação: %s" + #~ msgid "PolicyKit responded with '%s'" #~ msgstr "PolicyKit respondeu com '%s'" + #~ msgid "" #~ "High-priority scheduling (negative Unix nice level) for the PulseAudio " #~ "daemon" #~ msgstr "" #~ "Escalonamento de alta-prioridade (nível 'nice' negativo em Unix) para o " #~ "serviço PulseAudio" + #~ msgid "Real-time scheduling for the PulseAudio daemon" #~ msgstr "Escalonamento em tempo-real para o serviço PulseAudio" + #~ msgid "" #~ "System policy prevents PulseAudio from acquiring high-priority scheduling." #~ msgstr "" #~ "Politica do sistema impede o PulseAudio de obter escalonamento de alta-" #~ "prioridade." + #~ msgid "" #~ "System policy prevents PulseAudio from acquiring real-time scheduling." #~ msgstr "" #~ "Politica do sistema impede o PulseAudio de obter escalonamento de tempo-" #~ "real." + #~ msgid "read() failed: %s\n" #~ msgstr "read() falhou: %s\n" #, fuzzy #~ msgid "pa_context_connect() failed: %s\n" #~ msgstr "Impossível ligar ao servidor." -#~ msgid "Analog Mono" -#~ msgstr "Mono Analógico" -#~ msgid "Analog Stereo" -#~ msgstr "Estéreo Analógico" -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "Estéreo Digital (IEC958)" -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "Estéreo Digital (HDMI)" -#~ msgid "Analog Surround 4.0" -#~ msgstr "Analog Surround 4.0" -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "Surround Digital 4.0 (IEC958/AC3)" -#~ msgid "Analog Surround 4.1" -#~ msgstr "Analog Surround 4.1" -#~ msgid "Analog Surround 5.0" -#~ msgstr "Analog Surround 5.0" -#~ msgid "Analog Surround 5.1" -#~ msgstr "Analog Surround 5.1" -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "Surround Digital 5.1 (IEC958/AC3)" -#~ msgid "Analog Surround 7.1" -#~ msgstr "Analog Surround 7.1" + #~ msgid "We're in the group '%s', allowing high-priority scheduling." #~ msgstr "Estamos no grupo '%s', permitindo escalonamento de alta-prioridade." + #~ msgid "We're in the group '%s', allowing real-time scheduling." #~ msgstr "Estamos no grupo '%s', permitindo escalonamento em tempo real." + #~ msgid "PolicyKit grants us acquire-high-priority privilege." #~ msgstr "" #~ "O PolicyKit permite-nos o privilégio \"acquire-high-priority\" (adquirir " #~ "alta prioridade)." + #~ msgid "PolicyKit refuses acquire-high-priority privilege." #~ msgstr "" #~ "O PolicyKit recusa-nos o privilégio \"acquire-high-priority\" (adquirir " #~ "alta prioridade)." + #~ msgid "PolicyKit grants us acquire-real-time privilege." #~ msgstr "" #~ "O PolicyKit permite-nos o privilégio \"acquire-real-time\" (adquirir " #~ "tempo real)." + #~ msgid "PolicyKit refuses acquire-real-time privilege." #~ msgstr "" #~ "O PolicyKit recusa-nos o privilégio \"acquire-real-time\" (adquirir tempo " #~ "real)." + #~ msgid "" #~ "High-priority scheduling enabled in configuration but not allowed by " #~ "policy." #~ msgstr "" #~ "Escalonamento de alta prioridade activo na configuração, mas não " #~ "permitido pela politica." + #~ msgid "Successfully increased RLIMIT_RTPRIO" #~ msgstr "RLIMIT_RTPRIO aumentado com sucesso" + #~ msgid "RLIMIT_RTPRIO failed: %s" #~ msgstr "RLIMIT_RTPRIO falhou: %s" + #~ msgid "Giving up CAP_NICE" #~ msgstr "A desistir de CAP_NICE" + #~ msgid "" #~ "Real-time scheduling enabled in configuration but not allowed by policy." #~ msgstr "" #~ "Escalonamento em tempo real activo na configuração, mas não permitido " #~ "pela politica." + #~ msgid "Limited capabilities successfully to CAP_SYS_NICE." #~ msgstr "Capacidades limitadas com sucesso em CAP_SYS_NICE." + #~ msgid "time_new() failed.\n" #~ msgstr "time_new() falhou.\n" + #~ msgid "Stream successfully created\n" #~ msgstr "Fluxo criado com sucesso\n" + #~ msgid "Stream errror: %s\n" #~ msgstr "Erro de fluxo: %s\n" + #~ msgid "Connection established.\n" #~ msgstr "Ligação Estabelecida.\n" + #~ msgid "" #~ "paplay %s\n" #~ "Compiled with libpulse %s\n" @@ -2384,12 +2748,12 @@ msgstr "Servidor de Som PulseAudio" #~ "paplay %s\n" #~ "Compilado com libpulse %s\n" #~ "Linkado com libpulse %s\n" + #~ msgid "Invalid channel map\n" #~ msgstr "Mapa de canais inválido\n" + #~ msgid "Failed to open file '%s'\n" #~ msgstr "Falha ao abrir o ficheiro '%s'\n" + #~ msgid "Output %s + Input %s" #~ msgstr "Saída %s + Entrada %s" -#~ msgid "Input %s" -#~ msgstr "Entrada %s" - diff --git a/po/pt_BR.po b/po/pt_BR.po index f97521c9..6f44ca5f 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-08-24 19:26-0300\n" "Last-Translator: Igor Pires Soares <igor@projetofedora.org>\n" "Language-Team: Brazilian-Portuguese <fedora-trans-pt_br@redhat.com>\n" @@ -184,25 +184,25 @@ msgstr "O modo ampliado do sistema não tem suporte nessa plataforma." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) falhou: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Falha em interpretar a linha de comando." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "O daemon não está em execução" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Daemon executando como PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Falha em encerrar o daemon: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -210,159 +210,159 @@ msgstr "" "Este programa não é para ser executado como root (a não ser que --system " "seja especificado)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Privilégios de root requeridos." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start não tem suporte para instâncias de sistemas." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "Executando em no modo system, mas --disallow-exit não foi configurado!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Executando no modo system, mas --disallow-module-loading não foi configurado!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Executando no modo system, desabilitando forçadamente o modo SHM!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Executando no modo system, desabilitando forçadamente o exit idle time!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Falha em adquirir o stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "O pipe falhou: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "O fork() falhou: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "A operação read() falhou: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Falha na partida do daemon." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Os daemons foram iniciados com sucesso." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Este é o PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Host de compilação: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "Compilação CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Executando no host: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUs localizadas." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "O tamanho da página é %lu bytes" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Compilado com suporte do Valgrind: sim" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Compilado com suporte do Valgrind: não" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Executando em modo valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Build otimizado: sim" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Build otimizado: não" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definido, todas as declarações desabilitadas." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" "FASTPATH definido, somente as declarações do \"fast path\" foram " "desabilitadas." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Todas as declarações habilitadas." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Falha em obter o ID da máquina" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "A ID da máquina é %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "O ID da sessão é %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Usando o diretório de runtime %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Usando o diretório de estado %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Usando o diretório de módulos %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Executando em modo do sistema: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -378,15 +378,15 @@ msgstr "" "Por favor, leia o http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode para " "obter um explicação sobre porque o modo de sistema é uma má idéia." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() falhou." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Timers de alta resolução frequinhos disponíveis! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -394,28 +394,28 @@ msgstr "" "Cara, teu kernel fede! A recomendação do chef hoje é Linux com timers de " "alta resolução habilitados!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() falhou." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Falha em iniciar o daemon." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "O Daemon iniciou sem qualquer módulo carregado, recusando-se a trabalhar." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "A partida dos Daemon está completa." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "O encerramento do Daemon foi iniciado." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Daemon terminado." @@ -2387,6 +2387,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Desligado" @@ -2407,6 +2408,223 @@ msgstr "Duplex telefônico (HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "Servidor de som PulseAudio" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Áudio interno" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +msgid "Analog Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" + #~ msgid "Invalid client name '%s'\n" #~ msgstr "Nome do cliente \"%s\" inválido\n" @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-16 22:10+0100\n" "Last-Translator: Miloš Komarčević <kmilos@gmail.com>\n" "Language-Team: Serbian (sr) <fedora-trans-sr@redhat.com>\n" @@ -183,25 +183,25 @@ msgstr "Режим за читав систем није подржан на о msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) није успело: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Неуспешно тумачење командне линије." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Демон није покренут" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Демон је покренут са PID-ом %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Неуспешно убијање демона: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -209,158 +209,158 @@ msgstr "" "Није намеравано да се овај програм покреће из root налога (осим у случају " "када је --system наведено)" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Потребна су root овлашћења." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start није подржано за системске примерке." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "Покренуто у системском режиму, али --disallow-exit није постављено!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Покренуто у системском режиму, али --disallow-module-loading није постављено!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Покренуто у системском режиму, присилно онемогућујем SHM режим!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Покренуто у системском режиму, присилно онемогућујем гашење после одређеног " "времена мировања!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Неуспешно проналажење стандардног улаза/излаза." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "Неуспешно пуштање података кроз цев: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "Неуспела функција fork(): %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "Неуспела функција read(): %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Неуспешно покретање демона." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Демон успешно покренут." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Ово је PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Домаћин компајлирања: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS компајлирања: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Покренут на домаћину: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Нашао %u процесор(а)" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Величина странице је %lu бајтова" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Компајлирано са подршком за Valgrind: да" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Компајлирано са подршком за Valgrind: не" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Покренут у Valgrind режиму: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Оптимизована изградња: да" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Оптимизована изградња: не" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG дефинисан, сва обавештења искључена." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH дефинисан, само обавештења брзе путање искључена." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Сва обавештења омогућена." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Неуспешно добављање ИБ машине" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "ИБ машине је %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "ИБ сесије је %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Користи се %s извршни директоријум." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Користи се %s директоријум стања." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Користи се %s директоријум модула." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Покренуто у системском режиму: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -376,15 +376,15 @@ msgstr "" "Прочитајте http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode ради " "објашњења зашто је системски режим обично лоша идеја." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "Неуспела функција pa_pid_file_create()." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Доступни су нови бројачи високе резолуције! Пријатно!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -392,27 +392,27 @@ msgstr "" "Ваше језгро није добро подешено за pulseaudio! Препоручује Вам се да " "користите Linux језгро са омогућеним бројачима високе резолуције." -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "Неуспела функција pa_core_new()." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Неуспешно покретање демона." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Демон је покренут без иједног учитаног модула, одбија да ради." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Покретање демона успешно." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Покренуто гашење демона." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Рад демона је прекинут." @@ -2354,6 +2354,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Искључено" @@ -2372,3 +2373,221 @@ msgstr "Двострано телефонирање (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio звучни систем" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Унутрашњи звук" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Празан излаз" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "Стерео" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Окружујући 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Окружујући 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Окружујући 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "Окружујући 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "Окружујући 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "Окружујући 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "Окружујући 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Окружујући 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Окружујући 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Окружујући 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "Окружујући 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" diff --git a/po/sr@latin.po b/po/sr@latin.po index 5330f444..e6945add 100644 --- a/po/sr@latin.po +++ b/po/sr@latin.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-16 22:10+0100\n" "Last-Translator: Miloš Komarčević <kmilos@gmail.com>\n" "Language-Team: Serbian (sr) <fedora-trans-sr@redhat.com>\n" @@ -183,25 +183,25 @@ msgstr "Režim za čitav sistem nije podržan na ovoj platformi." msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) nije uspelo: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Neuspešno tumačenje komandne linije." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Demon nije pokrenut" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Demon je pokrenut sa PID-om %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Neuspešno ubijanje demona: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -209,159 +209,159 @@ msgstr "" "Nije nameravano da se ovaj program pokreće iz root naloga (osim u slučaju " "kada je --system navedeno)" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Potrebna su root ovlašćenja." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start nije podržano za sistemske primerke." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "Pokrenuto u sistemskom režimu, ali --disallow-exit nije postavljeno!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Pokrenuto u sistemskom režimu, ali --disallow-module-loading nije " "postavljeno!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Pokrenuto u sistemskom režimu, prisilno onemogućujem SHM režim!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Pokrenuto u sistemskom režimu, prisilno onemogućujem gašenje posle određenog " "vremena mirovanja!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Neuspešno pronalaženje standardnog ulaza/izlaza." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "Neuspešno puštanje podataka kroz cev: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "Neuspela funkcija fork(): %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "Neuspela funkcija read(): %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Neuspešno pokretanje demona." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Demon uspešno pokrenut." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Ovo je PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Domaćin kompajliranja: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS kompajliranja: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Pokrenut na domaćinu: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Našao %u procesor(a)" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Veličina stranice je %lu bajtova" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Kompajlirano sa podrškom za Valgrind: da" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Kompajlirano sa podrškom za Valgrind: ne" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Pokrenut u Valgrind režimu: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimizovana izgradnja: da" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Optimizovana izgradnja: ne" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG definisan, sva obaveštenja isključena." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH definisan, samo obaveštenja brze putanje isključena." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Sva obaveštenja omogućena." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Neuspešno dobavljanje IB mašine" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "IB mašine je %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "IB sesije je %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Koristi se %s izvršni direktorijum." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Koristi se %s direktorijum stanja." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Koristi se %s direktorijum modula." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Pokrenuto u sistemskom režimu: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -377,15 +377,15 @@ msgstr "" "Pročitajte http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode radi " "objašnjenja zašto je sistemski režim obično loša ideja." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "Neuspela funkcija pa_pid_file_create()." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Dostupni su novi brojači visoke rezolucije! Prijatno!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -393,27 +393,27 @@ msgstr "" "Vaše jezgro nije dobro podešeno za pulseaudio! Preporučuje Vam se da " "koristite Linux jezgro sa omogućenim brojačima visoke rezolucije." -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "Neuspela funkcija pa_core_new()." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Neuspešno pokretanje demona." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "Demon je pokrenut bez ijednog učitanog modula, odbija da radi." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Pokretanje demona uspešno." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Pokrenuto gašenje demona." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Rad demona je prekinut." @@ -2357,6 +2357,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Isključeno" @@ -2375,3 +2376,221 @@ msgstr "Dvostrano telefoniranje (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio zvučni sistem" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Unutrašnji zvuk" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Prazan izlaz" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "Stereo" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Okružujući 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Okružujući 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Okružujući 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "Okružujući 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "Okružujući 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "Okružujući 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "Okružujući 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Okružujući 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Okružujući 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Okružujući 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "Okružujući 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2008-09-05 18:24+0100\n" "Last-Translator: Daniel Nylander <po@danielnylander.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" @@ -165,25 +165,25 @@ msgstr "" msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) misslyckades: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -191,156 +191,156 @@ msgstr "" "Detta program är inte tänkt att köras som root (såvida inte --system har " "angivits)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 #, fuzzy msgid "Root privileges required." msgstr "Root-behörighet krävs." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start stöds inte för systeminstanser." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "pipe misslyckades: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() misslyckades: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() misslyckades: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Detta är PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -350,41 +350,41 @@ msgid "" "explanation why system mode is usually a bad idea." msgstr "" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() misslyckades." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() misslyckades." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "" @@ -2047,6 +2047,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "" @@ -2066,6 +2067,211 @@ msgstr "" msgid "PulseAudio Sound Server" msgstr "" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Internt fel" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +msgid "Analog Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, c-format +msgid "%s+%s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, c-format +msgid "%s / %s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +msgid "Analog Surround 2.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +msgid "Analog Surround 3.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +msgid "Analog Surround 3.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +msgid "Analog Surround 6.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +msgid "Analog Surround 6.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +msgid "Analog Surround 7.0" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" + #~ msgid "select(): %s" #~ msgstr "select(): %s" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.ta\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-18 13:43+0530\n" "Last-Translator: I. Felix <ifelix@redhat.com>\n" "Language-Team: Tamil <fedora-trans-ta@redhat.com>\n" @@ -203,180 +203,180 @@ msgstr "இந்த தளத்தில் கணினியின் தி msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) தோல்வியுற்றது: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "கட்டளை வரியை மாற்றுவதில் தோல்வி." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "டோமோன் இயங்கவில்லை" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "PID %uவாக டோமோன் இயங்குகிறது" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "டோமோனுக்கு முடிவு கட்டுவதில் தோல்வி: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "இந்த நிரல் ரூட்டாக இயங்க முடியவில்லை (--system குறிப்பிடாத வரை)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "ரூட் முன்னுரிமைகள் தேவைப்படுகிறது." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start கணினி நிகழ்வில் துணைபுரியவில்லை." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "கணினி முறைமையில் இயங்குகிறது, ஆனால் --disallow-exit அமைக்கப்படவில்லை!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "கணினி முறைமையில் இயங்குகிறது, ஆனால் --disallow-module-loading அமைக்கப்படவில்லை!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "கணினி முறைமையில் இயங்குகிறது, SHM முறைமை செயல்நீக்குதல் கட்டாயப்படுத்துகிறது!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "கணினி முறைமையில் இயங்குகிறது, வெறுமை நேரத்தை செயல்நீக்க கட்டாயப்படுத்துகிறது!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdioஐ பெற முடியவில்லை." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "பைப் தோல்வியுற்றது: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() தோல்வியுற்றது: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "வாசிப்பதில்() தோல்வியுற்றது: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "டோமோனை துவக்குவதில் தோல்வியுற்றது." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "டோமோனை வெற்றிகரமாக துவக்ககப்பட்டது." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "இது தான் பள்ஸ் ஆடியோ %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "தொகுக்கப்பட்ட புரவலன்: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "தொகுப்பு CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "புரவலனாக இயங்குகிறத: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "CPUs %uவில் காணப்படுகிறது ." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "பக்க அளவுகள் %lu பைட்ஸ்" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Compiled with Valgrind support: yes" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Compiled with Valgrind support: no" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind முறைமையில் இயங்குகிறது: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Optimized build: yes" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "சுருக்கமான உருவாக்கம்: இல்லை" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG வரையறுக்கப்பட்டது, அனைத்தும் உறுதியாக செயல்நீக்கப்பட்டது." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH வரையறுக்கப்பட்டது, விரைவு பாதை மட்டும் உறுதியாக செயல்நீக்கப்பட்டது." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "அனைத்து உறுதியாக செயல்படுகிறது." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "கணினி குறியீடை பெறுவதில் தோல்வி" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "கணினி குறியீடு %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "அமர்வு குறியீடு %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "ஓடும்நேரம் %s அடைவை பயன்படுத்துகிறது." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "%s நிலை அடைவினை பயன்படுத்துகிறது." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "தொகுதி %s அடைவை பயன்படுத்துகிறது." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "கணினியின் முறைமையில் இயங்குகிறது: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -392,15 +392,15 @@ msgstr "" "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an " "explanation why system mode is usually a bad idea." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() தோல்வியுற்றது." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "உயர்ந்த திரைத்திறன் நேரம்காட்டி கிடைக்கிளது! Bon appetit!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -408,27 +408,27 @@ msgstr "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() தோல்வியுற்றது." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "டோமோனை ஆரம்பிப்பதில் தோல்வி." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "டீமான் துவக்கம் எந்த தொகுதிகளும் ஏற்றப்படாமல், வேலையை நிராகரிக்கிறது." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "டோமோன் துவக்குவது முடிவடைந்தது." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "டோமோன் பணிநிறுத்தம் முனைகிறது." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "டோமோன் நீக்கப்பட்டுது." @@ -2359,6 +2359,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "ஆஃப்" @@ -2377,3 +2378,221 @@ msgstr "Telephony Duplex (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "PulseAudio ஒலி சேவையகம்" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "உட்புற ஆடியோ" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "பூஜ்ஜிய வெளிப்பாடு" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "ஸ்டிரியோ" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "Surround 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "Surround 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Surround 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Surround 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "Surround 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx.te\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" -"PO-Revision-Date: 2009-09-10 16:54+0530\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" +"PO-Revision-Date: 2009-09-21 17:28+0530\n" "Last-Translator: Krishna Babu K <kkrothap@redhat.com>\n" "Language-Team: Telugu <en@li.org>\n" "MIME-Version: 1.0\n" @@ -22,6 +22,7 @@ msgstr "" "\n" "\n" "\n" +"\n" #: ../src/modules/alsa/alsa-util.c:858 ../src/pulsecore/sink.c:2629 #, c-format @@ -183,179 +184,179 @@ msgstr "ఈ ప్లాట్ఫాం నందు సిస్టమ్ msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) విఫలమైంది: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "ఆదేశ వరుసను పార్శ్ చేయుటకు విఫలమైంది." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "డెమోన్ నడుచుట లేదు" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "డెమోన్ PID %u వలె నడుచుచున్నది" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "డెమోన్ చంపుటకు విఫలమైంది: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "ఈ ప్రోగ్రామ్ root లా నడుపవలసింది కాదు (--system తెలిపితే తప్ప)" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Root అనుమతులు అవసరము." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "--start సిస్టమ్ సంభవాల ద్వారా మద్దతీయబడదు." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "సిస్టమ్ మోడ్ నందు నడుపుతోంది, అయితే --disallow-exit అమర్చలేదు!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "సిస్టమ్ రీతినందు నడుచుచున్నది, అయితే --disallow-module-loading అమర్చలేదు!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "సిస్టమ్ రీతినందు నడుపుచున్నది, బలవంతంగా SHM రీతిని అచేతనము చేస్తోంది!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "సిస్టమ్ రీతినందు నడుచుచున్నది, బలవంతంగా నిష్క్రమణ వృధా సమయాన్ని అచేతనము చేయుచున్నది!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "stdio పొందుటకు విఫలమైంది." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "పైర్ విఫలమైంది: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork() విఫలమైంది: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read() విఫలమైంది: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "డెమోన్ ప్రారంభం విఫలమైంది." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "డెమోన్ ప్రారంభము సఫలమైంది." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "ఇది PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "నిర్వర్తన హోస్టు: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "నిర్వర్తన CFLAGS: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "హోస్టును నడుపుచున్నది: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "%u CPUలను కనుగొన్నది." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "పేజీ పరిమాణము %lu బైట్లు" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Valgrind మద్దతుతో నిర్వర్తించబడింది: అవును" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Valgrind మద్దతుతో నిర్వర్తించబడింది: లేదు" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "valgrind రీతినందు నడుపుచున్నది: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "ఆప్టిమైజ్డు బుల్డు: అవును" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "ఆప్టిమైజ్డు బుల్డు: కాదు" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "NDEBUG నిర్వచించబడింది, అన్ని స్థిరరాశులు అచేతనమైనవి." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "FASTPATH నిర్వచించబడింది, ఫాస్ట్ పాత్ స్థిరరాశులు మాత్రమే అచేతనమైనవి." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "అన్ని స్థిరరాశులు చేతనమైనవి." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "మిషన్ ID పొందుటకు విఫలమైంది" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "మిషన్ ID %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "సెషన్ ID %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "రన్టైమ్ డైరెక్టరీను వుపయోగించుచున్నది %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "స్థితి డైరెక్టరీను వుపయోగించుచున్నది %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "మాడ్యూళ్ళ డైరెక్టరీ %s వుపయోగిస్తోంది." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "సిస్టమ్ రీతినందు వుపయోగించుచున్నది: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -369,41 +370,41 @@ msgstr "" "సిస్టమ్ రీతి అనునది సరైనటువంటిది యెందుకు కాదో వివరణ కొరకు దయచేసి యిక్కడ చదవండి http://" "pulseaudio.org/wiki/WhatIsWrongWithSystemMode" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create() విఫలమైంది." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "తాజా అధిక-తీవ్రత కాలసూచికలు అందుబాటులో వున్నాయి! బాన్ ఎపటైట్!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "మిత్రమా, నీ కెర్నల్ చెడిపోయింది! అధిక-తీవ్రత కాలసూచకిలను చేతనము చేయమని సూచించడమైనది!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new() విఫలమైంది." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "డెమోన్ సిద్దముచేయుటకు విఫలమైంది." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "ఏవిధమైన మాడ్యూళ్ళు లోడవకుండా డెమోన్ ప్రారంభము, పనిచేయుటకు తిరస్కరించబడింది." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "డెమోన్ ప్రారంభము పూర్తైనది." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "డెమోన్ మూసివేత సిద్దముచేయబడింది." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "డెమోన్ అంతముచేయబడింది." @@ -1086,11 +1087,11 @@ msgstr "కక్షిదారి పోర్క్ చేసిన" #: ../src/pulse/error.c:68 msgid "Input/Output error" -msgstr "" +msgstr "ఇన్పుట్/అవుట్పుట్ దోషము" #: ../src/pulse/error.c:69 msgid "Device or resource busy" -msgstr "" +msgstr "పరికరము లేదా వనరు రద్దీగావుంది" #: ../src/pulse/sample.c:172 #, c-format @@ -2330,6 +2331,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "ఆఫ్" @@ -2348,3 +2350,221 @@ msgstr "టెలిఫోనీ డూప్లెక్స్ (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "పల్స్ ఆడియో సౌండ్ సేవిక" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "అంతర్గత ఆడియో" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Null అవుట్పుట్" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "స్టీరియో" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "సరౌండ్ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "సరౌండ్ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "సరౌండ్ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "సరౌండ్ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "సరౌండ్ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "సరౌండ్ 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "సరౌండ్ 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "సరౌండ్ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "సరౌండ్ 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "సరౌండ్ 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "సరౌండ్ 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-09-11 17:38+0300\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <translation@linux.org.ua>\n" @@ -187,25 +187,25 @@ msgstr "Загальносистемний режим не підтримуєт msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "Спроба виконати setrlimit(%s, (%u, %u)) була невдалою: %s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "Не вдалося обробити рядок команди." -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "Фонову службу не запущено" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "Фонову службу запущено як PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "Не вдалося завершити роботу фонової служби: %s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." @@ -213,161 +213,161 @@ msgstr "" "Цю програму не призначено для запуску від імені користувача root (якщо не " "вказано параметра --system)." -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "Потрібні права доступу користувача root." -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "" "Параметр --start не підтримується для загальносистемних екземплярів програми." -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "" "Запуск у загальносистемному режимі, але не встановлено --disallow-exit!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "" "Запуск у загальносистемному режимі, але не встановлено --disallow-module-" "loading!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "Запуск у загальносистемному режимі, примусове вимикання режиму SHM!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "" "Запуск у загальносистемному режимі, примусове вимикання режиму параметрів " "часу виходу за відсутності активності!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "Не вдалося отримати stdio." -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "Спроба створення каналу завершилася невдало: %s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "Спроба виконання fork() завершилася невдало: %s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "Спроба виконання read() завершилася невдало: %s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "Спроба запуску фонової служби завершилася невдало." -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "Фонову службу успішно запущено." -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "Це PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "Вузол збирання: %s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "CFLAGS збирання: %s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "Запущено на вузлі: %s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "Знайдено %u процесорів." -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "Розмір сторінки дорівнює %lu байтам" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "Зібрано з підтримкою Valgrind: так" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "Зібрано з підтримкою Valgrind: ні" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "Запуск у режимі valgrind: %s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "Зібрано з оптимізацією: так" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "Зібрано з оптимізацією: ні" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "Визначено NDEBUG, всі додавання вимкнено." -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "Визначено FASTPATH, вимкнено лише додавання швидких шляхів." -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "Увімкнено всі додавання." -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "Спроба отримати ідентифікатор системи завершилася невдало" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "Ідентифікатор системи %s." -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, c-format msgid "Session ID is %s." msgstr "Ідентифікатор сеансу — %s." -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "Каталог запуску: %s." -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "Каталог стану: %s." -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, c-format msgid "Using modules directory %s." msgstr "Каталог модулів: %s." -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "Запуску у загальносистемному режимі: %s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -384,15 +384,15 @@ msgstr "" "WhatIsWrongWithSystemMode, щоб дізнатися про те, чому не варто " "використовувати системний режим." -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "Спроба виконання pa_pid_file_create() зазнала невдачі." -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "Доступні свіжі високоточні таймери! Смачного!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" @@ -400,29 +400,29 @@ msgstr "" "Чувак, твоє ядро — лайно! Круті пацани рекомендують Linux з увімкненими " "високоточними таймерами!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "Спроба виконання pa_core_new() зазнала невдачі." -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "Не вдалося ініціалізувати фонову службу." -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "" "Запуск фонової служби без жодного завантаженого модуля, служба не буде " "працездатною." -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "Запуск фонової служби завершено." -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "Ініційовано завершення роботи фонової служби." -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "Виконання фонової служби перервано." @@ -2385,6 +2385,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "Вимкнено" @@ -2403,3 +2404,221 @@ msgstr "Телефонний дуплекс (HSP/HFP)" #: ../src/modules/reserve-wrap.c:151 msgid "PulseAudio Sound Server" msgstr "Звуковий сервер PulseAudio" + +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +msgid "Input Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +msgid "Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "Вбудоване аудіо" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +msgid "Analog Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +msgid "Analog Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +msgid "Analog Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +msgid "Analog Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +msgid "Analog Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "Нуль-відтворення" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +msgid "Analog Headphones" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +msgid "Analog Mono Output" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, fuzzy, c-format +msgid "%s+%s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, fuzzy, c-format +msgid "%s / %s" +msgstr "%s %s" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +#, fuzzy +msgid "Analog Stereo" +msgstr "Стерео" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "Об'ємний 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "Об'ємний 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "Об'ємний 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +#, fuzzy +msgid "Analog Surround 4.0" +msgstr "Об'ємний 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +#, fuzzy +msgid "Analog Surround 4.1" +msgstr "Об'ємний 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +#, fuzzy +msgid "Analog Surround 5.0" +msgstr "Об'ємний 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +#, fuzzy +msgid "Analog Surround 5.1" +msgstr "Об'ємний 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "Об'ємний 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "Об'ємний 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "Об'ємний 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +#, fuzzy +msgid "Analog Surround 7.1" +msgstr "Об'ємний 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +msgid "Digital Surround 4.0 (IEC958)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +msgid "Analog Mono Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +msgid "Analog Stereo Duplex" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "" diff --git a/po/zh_CN.po b/po/zh_CN.po index 84ef1618..a2730668 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: pulseaudio.master-tx\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-09-18 22:17+0200\n" +"POT-Creation-Date: 2009-09-29 23:47+0200\n" "PO-Revision-Date: 2009-04-06 10:26+1000\n" "Last-Translator: Leah Liu <lliu@redhat.com>\n" "Language-Team: Simplified Chinese <zh@li.org>\n" @@ -175,179 +175,179 @@ msgstr "此平台不支持system-wide模式。" msgid "setrlimit(%s, (%u, %u)) failed: %s" msgstr "setrlimit(%s, (%u, %u)) 失败:%s" -#: ../src/daemon/main.c:469 +#: ../src/daemon/main.c:474 msgid "Failed to parse command line." msgstr "分析命令行失败。" -#: ../src/daemon/main.c:536 +#: ../src/daemon/main.c:541 msgid "Daemon not running" msgstr "后台程序没有运行" -#: ../src/daemon/main.c:538 +#: ../src/daemon/main.c:543 #, c-format msgid "Daemon running as PID %u" msgstr "后台程序正在运行,PID %u" -#: ../src/daemon/main.c:548 +#: ../src/daemon/main.c:553 #, c-format msgid "Failed to kill daemon: %s" msgstr "杀死后台程序失败:%s" -#: ../src/daemon/main.c:566 +#: ../src/daemon/main.c:571 msgid "" "This program is not intended to be run as root (unless --system is " "specified)." msgstr "不应以root身份运行本程序(除非指定 --system)。" -#: ../src/daemon/main.c:568 +#: ../src/daemon/main.c:573 msgid "Root privileges required." msgstr "需要 root 权限。" -#: ../src/daemon/main.c:573 +#: ../src/daemon/main.c:578 msgid "--start not supported for system instances." msgstr "系统实例不支持 --start。" -#: ../src/daemon/main.c:578 +#: ../src/daemon/main.c:583 msgid "Running in system mode, but --disallow-exit not set!" msgstr "正在以系统模式运行,但是 --disallow-exit 未设定!" -#: ../src/daemon/main.c:581 +#: ../src/daemon/main.c:586 msgid "Running in system mode, but --disallow-module-loading not set!" msgstr "正在以系统模式运行,但是 --disallow-module-loading 未设定!" -#: ../src/daemon/main.c:584 +#: ../src/daemon/main.c:589 msgid "Running in system mode, forcibly disabling SHM mode!" msgstr "正在以系统模式运行,强制禁用SHM模式!" -#: ../src/daemon/main.c:589 +#: ../src/daemon/main.c:594 msgid "Running in system mode, forcibly disabling exit idle time!" msgstr "正在以系统模式运行,强制禁用退出空闲时间!" -#: ../src/daemon/main.c:616 +#: ../src/daemon/main.c:621 msgid "Failed to acquire stdio." msgstr "获取stdio失败。" -#: ../src/daemon/main.c:622 +#: ../src/daemon/main.c:627 #, c-format msgid "pipe failed: %s" msgstr "管道失败:%s" -#: ../src/daemon/main.c:627 +#: ../src/daemon/main.c:632 #, c-format msgid "fork() failed: %s" msgstr "fork()失败:%s" -#: ../src/daemon/main.c:641 ../src/utils/pacat.c:508 +#: ../src/daemon/main.c:646 ../src/utils/pacat.c:508 #, c-format msgid "read() failed: %s" msgstr "read()失败:%s" -#: ../src/daemon/main.c:647 +#: ../src/daemon/main.c:652 msgid "Daemon startup failed." msgstr "后台程序启动失败。" -#: ../src/daemon/main.c:649 +#: ../src/daemon/main.c:654 msgid "Daemon startup successful." msgstr "后台程序启动成功。" -#: ../src/daemon/main.c:726 +#: ../src/daemon/main.c:731 #, c-format msgid "This is PulseAudio %s" msgstr "这是 PulseAudio %s" -#: ../src/daemon/main.c:727 +#: ../src/daemon/main.c:732 #, c-format msgid "Compilation host: %s" msgstr "编译主机:%s" -#: ../src/daemon/main.c:728 +#: ../src/daemon/main.c:733 #, c-format msgid "Compilation CFLAGS: %s" msgstr "编译CFLAGS:%s" -#: ../src/daemon/main.c:731 +#: ../src/daemon/main.c:736 #, c-format msgid "Running on host: %s" msgstr "正在主机上运行:%s" -#: ../src/daemon/main.c:734 +#: ../src/daemon/main.c:739 #, c-format msgid "Found %u CPUs." msgstr "找到 %u CPU。" -#: ../src/daemon/main.c:736 +#: ../src/daemon/main.c:741 #, c-format msgid "Page size is %lu bytes" msgstr "页面大小为%lu字节" -#: ../src/daemon/main.c:739 +#: ../src/daemon/main.c:744 msgid "Compiled with Valgrind support: yes" msgstr "编译启用Valgrind支持:是" -#: ../src/daemon/main.c:741 +#: ../src/daemon/main.c:746 msgid "Compiled with Valgrind support: no" msgstr "编译启用Valgrind支持:否" -#: ../src/daemon/main.c:744 +#: ../src/daemon/main.c:749 #, c-format msgid "Running in valgrind mode: %s" msgstr "正在以valgrind模式运行:%s" -#: ../src/daemon/main.c:747 +#: ../src/daemon/main.c:752 msgid "Optimized build: yes" msgstr "优化生成:是" -#: ../src/daemon/main.c:749 +#: ../src/daemon/main.c:754 msgid "Optimized build: no" msgstr "优化生成:否" -#: ../src/daemon/main.c:753 +#: ../src/daemon/main.c:758 msgid "NDEBUG defined, all asserts disabled." msgstr "拒绝 NDEBUG,禁用所有 assert" -#: ../src/daemon/main.c:755 +#: ../src/daemon/main.c:760 msgid "FASTPATH defined, only fast path asserts disabled." msgstr "拒绝 FASTPATH,只禁用快速路径 assert。" -#: ../src/daemon/main.c:757 +#: ../src/daemon/main.c:762 msgid "All asserts enabled." msgstr "启用所有 assert。" -#: ../src/daemon/main.c:761 +#: ../src/daemon/main.c:766 msgid "Failed to get machine ID" msgstr "获取machine ID失败" -#: ../src/daemon/main.c:764 +#: ../src/daemon/main.c:769 #, c-format msgid "Machine ID is %s." msgstr "machine ID是%s。" -#: ../src/daemon/main.c:768 +#: ../src/daemon/main.c:773 #, fuzzy, c-format msgid "Session ID is %s." msgstr "machine ID是%s。" -#: ../src/daemon/main.c:774 +#: ../src/daemon/main.c:779 #, c-format msgid "Using runtime directory %s." msgstr "正在使用运行时文件夹%s。" -#: ../src/daemon/main.c:779 +#: ../src/daemon/main.c:784 #, c-format msgid "Using state directory %s." msgstr "正在使用状态文件夹%s。" -#: ../src/daemon/main.c:782 +#: ../src/daemon/main.c:787 #, fuzzy, c-format msgid "Using modules directory %s." msgstr "正在使用运行时文件夹%s。" -#: ../src/daemon/main.c:784 +#: ../src/daemon/main.c:789 #, c-format msgid "Running in system mode: %s" msgstr "正在以系统模式运行:%s" -#: ../src/daemon/main.c:787 +#: ../src/daemon/main.c:792 msgid "" "OK, so you are running PA in system mode. Please note that you most likely " "shouldn't be doing that.\n" @@ -357,41 +357,41 @@ msgid "" "explanation why system mode is usually a bad idea." msgstr "" -#: ../src/daemon/main.c:804 +#: ../src/daemon/main.c:809 msgid "pa_pid_file_create() failed." msgstr "pa_pid_file_create()失败。" -#: ../src/daemon/main.c:814 +#: ../src/daemon/main.c:819 msgid "Fresh high-resolution timers available! Bon appetit!" msgstr "新鲜的高分辨率计时器开锅了!吃个饱!" -#: ../src/daemon/main.c:816 +#: ../src/daemon/main.c:821 msgid "" "Dude, your kernel stinks! The chef's recommendation today is Linux with high-" "resolution timers enabled!" msgstr "老兄,你的内核真臭!现在流行的是启用了高分辩率计分器的Linux!" -#: ../src/daemon/main.c:839 +#: ../src/daemon/main.c:844 msgid "pa_core_new() failed." msgstr "pa_core_new()失败。" -#: ../src/daemon/main.c:899 +#: ../src/daemon/main.c:904 msgid "Failed to initialize daemon." msgstr "后台程序初始化失败。" -#: ../src/daemon/main.c:904 +#: ../src/daemon/main.c:909 msgid "Daemon startup without any loaded modules, refusing to work." msgstr "后台程序启动未加载任何模块,拒绝工作。" -#: ../src/daemon/main.c:921 +#: ../src/daemon/main.c:926 msgid "Daemon startup complete." msgstr "后台程序启动完成。" -#: ../src/daemon/main.c:927 +#: ../src/daemon/main.c:932 msgid "Daemon shutdown initiated." msgstr "开始关闭后台程序。" -#: ../src/daemon/main.c:949 +#: ../src/daemon/main.c:954 msgid "Daemon terminated." msgstr "后台程序已终止。" @@ -2310,6 +2310,7 @@ msgstr "" #: ../src/modules/alsa/module-alsa-card.c:152 #: ../src/modules/bluetooth/module-bluetooth-device.c:2228 +#: ../src/modules/alsa/alsa-mixer.c:2931 msgid "Off" msgstr "关闭" @@ -2330,6 +2331,231 @@ msgstr "双工电话(HSP/HFP)" msgid "PulseAudio Sound Server" msgstr "PulseAudio 声音服务器" +#: ../src/modules/module-rygel-media-server.c:569 +#: ../src/modules/module-rygel-media-server.c:583 +msgid "Output Devices" +msgstr "" + +#: ../src/modules/module-rygel-media-server.c:570 +#: ../src/modules/module-rygel-media-server.c:584 +#, fuzzy +msgid "Input Devices" +msgstr "输入 %s" + +#: ../src/modules/module-rygel-media-server.c:774 +msgid "Audio on @HOSTNAME@" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1701 +#, fuzzy +msgid "Input" +msgstr "输入 %s" + +#: ../src/modules/alsa/alsa-mixer.c:1702 +msgid "Docking Station Input" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1703 +msgid "Docking Station Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1704 +msgid "Line-In" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1705 +msgid "Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1706 +msgid "External Microphone" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1707 +#, fuzzy +msgid "Internal Microphone" +msgstr "内部音频" + +#: ../src/modules/alsa/alsa-mixer.c:1708 +msgid "Radio" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1709 +msgid "Video" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1710 +msgid "Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1711 +msgid "No Automatic Gain Control" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1712 +msgid "Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1713 +msgid "No Boost" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1714 +msgid "Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1715 +msgid "No Amplifier" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1773 +#, fuzzy +msgid "Analog Input" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:1774 +#, fuzzy +msgid "Analog Microphone" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:1775 +#, fuzzy +msgid "Analog Line-In" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:1776 +#, fuzzy +msgid "Analog Radio" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:1777 +#, fuzzy +msgid "Analog Video" +msgstr "模拟立体声" + +#: ../src/modules/alsa/alsa-mixer.c:1778 +#, fuzzy +msgid "Analog Output" +msgstr "输出 %s" + +#: ../src/modules/alsa/alsa-mixer.c:1779 +#, fuzzy +msgid "Analog Headphones" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:1780 +msgid "Analog Output (LFE)" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1781 +#, fuzzy +msgid "Analog Mono Output" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:1981 +#, c-format +msgid "%s+%s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:1984 ../src/modules/alsa/alsa-mixer.c:3404 +#, c-format +msgid "%s / %s" +msgstr "" + +#: ../src/modules/alsa/alsa-mixer.c:2790 +msgid "Analog Mono" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:2791 +msgid "Analog Stereo" +msgstr "模拟立体声" + +#: ../src/modules/alsa/alsa-mixer.c:2792 +#, fuzzy +msgid "Analog Surround 2.1" +msgstr "模拟环绕 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2793 +#, fuzzy +msgid "Analog Surround 3.0" +msgstr "模拟环绕 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2794 +#, fuzzy +msgid "Analog Surround 3.1" +msgstr "模拟环绕 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2795 +msgid "Analog Surround 4.0" +msgstr "模拟环绕 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2796 +msgid "Analog Surround 4.1" +msgstr "模拟环绕 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2797 +msgid "Analog Surround 5.0" +msgstr "模拟环绕 5.0" + +#: ../src/modules/alsa/alsa-mixer.c:2798 +msgid "Analog Surround 5.1" +msgstr "模拟环绕 5.1" + +#: ../src/modules/alsa/alsa-mixer.c:2799 +#, fuzzy +msgid "Analog Surround 6.0" +msgstr "模拟环绕 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2800 +#, fuzzy +msgid "Analog Surround 6.1" +msgstr "模拟环绕 4.1" + +#: ../src/modules/alsa/alsa-mixer.c:2801 +#, fuzzy +msgid "Analog Surround 7.0" +msgstr "模拟环绕 4.0" + +#: ../src/modules/alsa/alsa-mixer.c:2802 +msgid "Analog Surround 7.1" +msgstr "模拟环绕 7.1" + +#: ../src/modules/alsa/alsa-mixer.c:2803 +msgid "Digital Stereo (IEC958)" +msgstr "数字立体声(IEC958)" + +#: ../src/modules/alsa/alsa-mixer.c:2804 +#, fuzzy +msgid "Digital Surround 4.0 (IEC958)" +msgstr "数字环绕 4.0(IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2805 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "数字环绕 4.0(IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2806 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "数字环绕 5.1(IEC958/AC3)" + +#: ../src/modules/alsa/alsa-mixer.c:2807 +msgid "Digital Stereo (HDMI)" +msgstr "数字立体声(HDMI)" + +#: ../src/modules/alsa/alsa-mixer.c:2928 +#, fuzzy +msgid "Analog Mono Duplex" +msgstr "模拟单声道" + +#: ../src/modules/alsa/alsa-mixer.c:2929 +#, fuzzy +msgid "Analog Stereo Duplex" +msgstr "模拟立体声" + +#: ../src/modules/alsa/alsa-mixer.c:2930 +#, fuzzy +msgid "Digital Stereo Duplex (IEC958)" +msgstr "数字立体声(IEC958)" + #, fuzzy #~ msgid "Invalid client name '%s'\n" #~ msgstr "无效的通道映射描述'%s'\n" @@ -2460,45 +2686,9 @@ msgstr "PulseAudio 声音服务器" #~ msgid "time_new() failed.\n" #~ msgstr "time_new()失败。\n" -#~ msgid "Analog Mono" -#~ msgstr "模拟单声道" - -#~ msgid "Analog Stereo" -#~ msgstr "模拟立体声" - -#~ msgid "Digital Stereo (IEC958)" -#~ msgstr "数字立体声(IEC958)" - -#~ msgid "Digital Stereo (HDMI)" -#~ msgstr "数字立体声(HDMI)" - -#~ msgid "Analog Surround 4.0" -#~ msgstr "模拟环绕 4.0" - -#~ msgid "Digital Surround 4.0 (IEC958/AC3)" -#~ msgstr "数字环绕 4.0(IEC958/AC3)" - -#~ msgid "Analog Surround 4.1" -#~ msgstr "模拟环绕 4.1" - -#~ msgid "Analog Surround 5.0" -#~ msgstr "模拟环绕 5.0" - -#~ msgid "Analog Surround 5.1" -#~ msgstr "模拟环绕 5.1" - -#~ msgid "Digital Surround 5.1 (IEC958/AC3)" -#~ msgstr "数字环绕 5.1(IEC958/AC3)" - -#~ msgid "Analog Surround 7.1" -#~ msgstr "模拟环绕 7.1" - #~ msgid "Output %s + Input %s" #~ msgstr "输出 %s + 输入 %s" -#~ msgid "Input %s" -#~ msgstr "输入 %s" - #~ msgid "Stream successfully created\n" #~ msgstr "成功创建流\n" diff --git a/src/Makefile.am b/src/Makefile.am index 6544e2aa..c5d3ab7b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,6 +70,8 @@ AM_CFLAGS = \ -I$(top_builddir)/src/modules/x11 \ -I$(top_srcdir)/src/modules/jack \ -I$(top_builddir)/src/modules/jack \ + -I$(top_srcdir)/src/modules/dbus \ + -I$(top_builddir)/src/modules/dbus \ $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS \ $(LIBSAMPLERATE_CFLAGS) \ $(LIBSNDFILE_CFLAGS) \ @@ -117,9 +119,11 @@ EXTRA_DIST = \ depmod.py \ daemon/esdcompat.in \ daemon/start-pulseaudio-x11.in \ + daemon/start-pulseaudio-kde.in \ utils/padsp \ modules/module-defs.h.m4 \ daemon/pulseaudio.desktop.in \ + daemon/pulseaudio-kde.desktop.in \ map-file \ daemon/pulseaudio-system.conf \ modules/alsa/mixer/profile-sets/default.conf \ @@ -153,7 +157,8 @@ dbuspolicy_DATA = \ if HAVE_X11 xdgautostart_in_files = \ - daemon/pulseaudio.desktop.in + daemon/pulseaudio.desktop.in \ + daemon/pulseaudio-kde.desktop.in endif xdgautostart_DATA = $(xdgautostart_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ @@ -169,13 +174,14 @@ BUILT_SOURCES = \ bin_PROGRAMS = pulseaudio pulseaudio_SOURCES = \ - daemon/caps.h daemon/caps.c \ + daemon/caps.c daemon/caps.h \ daemon/cmdline.c daemon/cmdline.h \ daemon/cpulimit.c daemon/cpulimit.h \ daemon/daemon-conf.c daemon/daemon-conf.h \ daemon/dumpmodules.c daemon/dumpmodules.h \ daemon/ltdl-bind-now.c daemon/ltdl-bind-now.h \ - daemon/main.c + daemon/main.c \ + daemon/server-lookup.c daemon/server-lookup.h pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSPEEX_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(DBUS_CFLAGS) pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSPEEX_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(DBUS_LIBS) @@ -215,7 +221,7 @@ if HAVE_AVAHI bin_PROGRAMS += pabrowse endif -bin_SCRIPTS = esdcompat start-pulseaudio-x11 +bin_SCRIPTS = esdcompat start-pulseaudio-x11 start-pulseaudio-kde pacat_SOURCES = utils/pacat.c pacat_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINORMICRO@.la $(LIBSNDFILE_LIBS) @@ -689,6 +695,7 @@ pulseinclude_HEADERS = \ pulse/context.h \ pulse/def.h \ pulse/error.h \ + pulse/ext-device-manager.h \ pulse/ext-stream-restore.h \ pulse/gccmacro.h \ pulse/introspect.h \ @@ -739,6 +746,7 @@ libpulse_la_SOURCES = \ pulse/context.c pulse/context.h \ pulse/def.h \ pulse/error.c pulse/error.h \ + pulse/ext-device-manager.c pulse/ext-device-manager.h \ pulse/ext-stream-restore.c pulse/ext-stream-restore.h \ pulse/gccmacro.h \ pulse/internal.h \ @@ -869,7 +877,9 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_LDFLAGS += $(X11_LIBS) endif if HAVE_DBUS -libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dbus-shared.c pulsecore/dbus-shared.h +libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES += \ + pulsecore/dbus-shared.c pulsecore/dbus-shared.h \ + pulsecore/protocol-dbus.c pulsecore/protocol-dbus.h libpulsecore_@PA_MAJORMINORMICRO@_la_CFLAGS += $(DBUS_CFLAGS) libpulsecore_@PA_MAJORMINORMICRO@_la_LIBADD += $(DBUS_LIBS) endif @@ -990,6 +1000,7 @@ modlibexec_LTLIBRARIES += \ module-sine-source.la \ module-detect.la \ module-volume-restore.la \ + module-device-manager.la \ module-device-restore.la \ module-stream-restore.la \ module-card-restore.la \ @@ -1156,7 +1167,8 @@ endif if HAVE_DBUS modlibexec_LTLIBRARIES += \ - module-rygel-media-server.la + module-rygel-media-server.la \ + module-dbus-protocol.la endif if HAVE_BLUEZ @@ -1182,6 +1194,11 @@ modlibexec_LTLIBRARIES += \ endif endif +if HAVE_FFTW +modlibexec_LTLIBRARIES += \ + module-equalizer-sink.la +endif + # These are generated by an M4 script SYMDEF_FILES = \ modules/module-cli-symdef.h \ @@ -1200,6 +1217,7 @@ SYMDEF_FILES = \ modules/module-combine-symdef.h \ modules/module-remap-sink-symdef.h \ modules/module-ladspa-sink-symdef.h \ + modules/module-equalizer-sink-symdef.h \ modules/module-esound-compat-spawnfd-symdef.h \ modules/module-esound-compat-spawnpid-symdef.h \ modules/module-match-symdef.h \ @@ -1231,6 +1249,7 @@ SYMDEF_FILES = \ modules/jack/module-jack-sink-symdef.h \ modules/jack/module-jack-source-symdef.h \ modules/module-volume-restore-symdef.h \ + modules/module-device-manager-symdef.h \ modules/module-device-restore-symdef.h \ modules/module-stream-restore-symdef.h \ modules/module-card-restore-symdef.h \ @@ -1251,6 +1270,7 @@ SYMDEF_FILES = \ modules/module-augment-properties-symdef.h \ modules/module-cork-music-on-phone-symdef.h \ modules/module-console-kit-symdef.h \ + modules/dbus/module-dbus-protocol-symdef.h \ modules/module-loopback-symdef.h EXTRA_DIST += $(SYMDEF_FILES) @@ -1300,6 +1320,24 @@ module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(A module_http_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libprotocol-http.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +# D-Bus protocol + +module_dbus_protocol_la_SOURCES = \ + modules/dbus/iface-card.c modules/dbus/iface-card.h \ + modules/dbus/iface-card-profile.c modules/dbus/iface-card-profile.h \ + modules/dbus/iface-client.c modules/dbus/iface-client.h \ + modules/dbus/iface-core.c modules/dbus/iface-core.h \ + modules/dbus/iface-device.c modules/dbus/iface-device.h \ + modules/dbus/iface-device-port.c modules/dbus/iface-device-port.h \ + modules/dbus/iface-memstats.c modules/dbus/iface-memstats.h \ + modules/dbus/iface-module.c modules/dbus/iface-module.h \ + modules/dbus/iface-sample.c modules/dbus/iface-sample.h \ + modules/dbus/iface-stream.c modules/dbus/iface-stream.h \ + modules/dbus/module-dbus-protocol.c +module_dbus_protocol_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) +module_dbus_protocol_la_LDFLAGS = $(MODULE_LDFLAGS) +module_dbus_protocol_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la + # Native protocol module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c @@ -1380,6 +1418,11 @@ module_ladspa_sink_la_CFLAGS = -DLADSPA_PATH=\"$(libdir)/ladspa:/usr/local/lib/l module_ladspa_sink_la_LDFLAGS = $(MODULE_LDFLAGS) module_ladspa_sink_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_equalizer_sink_la_SOURCES = modules/module-equalizer-sink.c +module_equalizer_sink_la_CFLAGS = $(AM_CFLAGS) $(FFTW_CFLAGS) +module_equalizer_sink_la_LDFLAGS = $(MODULE_LDFLAGS) +module_equalizer_sink_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) $(FFTW_LIBS) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la + module_match_la_SOURCES = modules/module-match.c module_match_la_LDFLAGS = $(MODULE_LDFLAGS) module_match_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la @@ -1539,6 +1582,12 @@ module_cork_music_on_phone_la_LDFLAGS = $(MODULE_LDFLAGS) module_cork_music_on_phone_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_cork_music_on_phone_la_CFLAGS = $(AM_CFLAGS) +# Device description restore module +module_device_manager_la_SOURCES = modules/module-device-manager.c +module_device_manager_la_LDFLAGS = $(MODULE_LDFLAGS) +module_device_manager_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la +module_device_manager_la_CFLAGS = $(AM_CFLAGS) + # Device volume/muted restore module module_device_restore_la_SOURCES = modules/module-device-restore.c module_device_restore_la_LDFLAGS = $(MODULE_LDFLAGS) @@ -1551,6 +1600,11 @@ module_stream_restore_la_LDFLAGS = $(MODULE_LDFLAGS) module_stream_restore_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la module_stream_restore_la_CFLAGS = $(AM_CFLAGS) +if HAVE_DBUS +module_stream_restore_la_LIBADD += $(DBUS_LIBS) +module_stream_restore_la_CFLAGS += $(DBUS_CFLAGS) +endif + # Card profile restore module module_card_restore_la_SOURCES = modules/module-card-restore.c module_card_restore_la_LDFLAGS = $(MODULE_LDFLAGS) @@ -1701,7 +1755,7 @@ module_rygel_media_server_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) # Some minor stuff # ################################### -CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11 daemon/pulseaudio.desktop +CLEANFILES = esdcompat client.conf default.pa system.pa daemon.conf start-pulseaudio-x11 start-pulseaudio-kde daemon/pulseaudio.desktop daemon/pulseaudio-kde.desktop esdcompat: daemon/esdcompat.in Makefile sed -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ @@ -1714,6 +1768,11 @@ start-pulseaudio-x11: daemon/start-pulseaudio-x11.in Makefile -e 's,@PACTL_BINARY\@,$(bindir)/pactl,g' < $< > $@ chmod +x start-pulseaudio-x11 +start-pulseaudio-kde: daemon/start-pulseaudio-kde.in Makefile + sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' \ + -e 's,@PACTL_BINARY\@,$(bindir)/pactl,g' < $< > $@ + chmod +x start-pulseaudio-kde + client.conf: pulse/client.conf.in Makefile sed -e 's,@PA_BINARY\@,$(PA_BINARY),g' < $< > $@ diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index 6e7926f8..571faae4 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -83,6 +83,9 @@ static const pa_daemon_conf default_conf = { .config_file = NULL, .use_pid_file = TRUE, .system_instance = FALSE, +#ifdef HAVE_DBUS + .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */ +#endif .no_cpu_limit = TRUE, .disable_shm = FALSE, .lock_memory = FALSE, @@ -220,6 +223,22 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { return 0; } +int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string) { + pa_assert(c); + pa_assert(string); + + if (!strcmp(string, "user")) + c->local_server_type = PA_SERVER_TYPE_USER; + else if (!strcmp(string, "system")) { + c->local_server_type = PA_SERVER_TYPE_SYSTEM; + } else if (!strcmp(string, "none")) { + c->local_server_type = PA_SERVER_TYPE_NONE; + } else + return -1; + + return 0; +} + static int parse_log_target(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; @@ -447,6 +466,22 @@ static int parse_rtprio(const char *filename, unsigned line, const char *section return 0; } +static int parse_server_type(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { + pa_daemon_conf *c = data; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_daemon_conf_set_local_server_type(c, rvalue) < 0) { + pa_log(_("[%s:%u] Invalid server type '%s'."), filename, line, rvalue); + return -1; + } + + return 0; +} + int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; @@ -462,6 +497,9 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "allow-exit", pa_config_parse_not_bool, &c->disallow_exit, NULL }, { "use-pid-file", pa_config_parse_bool, &c->use_pid_file, NULL }, { "system-instance", pa_config_parse_bool, &c->system_instance, NULL }, +#ifdef HAVE_DBUS + { "local-server-type", parse_server_type, c, NULL }, +#endif { "no-cpu-limit", pa_config_parse_bool, &c->no_cpu_limit, NULL }, { "cpu-limit", pa_config_parse_not_bool, &c->no_cpu_limit, NULL }, { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, @@ -627,6 +665,14 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { [PA_LOG_WARN] = "warning", [PA_LOG_ERROR] = "error" }; + + static const char* const server_type_to_string[] = { + [PA_SERVER_TYPE_UNSET] = "!!UNSET!!", + [PA_SERVER_TYPE_USER] = "user", + [PA_SERVER_TYPE_SYSTEM] = "system", + [PA_SERVER_TYPE_NONE] = "none" + }; + pa_strbuf *s; char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; @@ -649,6 +695,9 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit)); pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); +#ifdef HAVE_DBUS + pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]); +#endif pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit)); pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm)); pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index dd69e048..41c3c4b7 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -28,6 +28,7 @@ #include <pulsecore/log.h> #include <pulsecore/macro.h> +#include <pulsecore/core.h> #include <pulsecore/core-util.h> #ifdef HAVE_SYS_RESOURCE_H @@ -75,6 +76,7 @@ typedef struct pa_daemon_conf { log_time, flat_volumes, lock_memory; + pa_server_type_t local_server_type; int exit_idle_time, scache_idle_time, auto_log_target, @@ -152,6 +154,7 @@ int pa_daemon_conf_env(pa_daemon_conf *c); int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string); int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string); int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string); const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c); FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c); diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index 3af68b0a..7c1a7b8c 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -25,6 +25,7 @@ ; allow-exit = yes ; use-pid-file = yes ; system-instance = no +; local-server-type = user ; enable-shm = yes ; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB ; lock-memory = no diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index 00c000eb..f9b9eadd 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -66,6 +66,9 @@ load-module module-bluetooth-discover .ifexists module-esound-protocol-unix@PA_SOEXT@ load-module module-esound-protocol-unix .endif +.ifexists module-dbus-protocol@PA_SOEXT@ +load-module module-dbus-protocol +.endif load-module module-native-protocol-unix ### Network access (may be configured with paprefs, so leave this commented diff --git a/src/daemon/main.c b/src/daemon/main.c index af59adef..9e5647a8 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -102,6 +102,7 @@ #include "dumpmodules.h" #include "caps.h" #include "ltdl-bind-now.h" +#include "server-lookup.h" #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ @@ -343,33 +344,31 @@ static void set_all_rlimits(const pa_daemon_conf *conf) { #endif #ifdef HAVE_DBUS -static pa_dbus_connection *register_dbus(pa_core *c) { +static pa_dbus_connection *register_dbus_name(pa_core *c, DBusBusType bus, const char* name) { DBusError error; pa_dbus_connection *conn; dbus_error_init(&error); - if (!(conn = pa_dbus_bus_get(c, pa_in_system_mode() ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { + if (!(conn = pa_dbus_bus_get(c, bus, &error)) || dbus_error_is_set(&error)) { pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message); goto fail; } - if (dbus_bus_request_name(pa_dbus_connection_get(conn), "org.pulseaudio.Server", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - pa_log_debug("Got org.pulseaudio.Server!"); + if (dbus_bus_request_name(pa_dbus_connection_get(conn), name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + pa_log_debug("Got %s!", name); return conn; } if (dbus_error_is_set(&error)) - pa_log_warn("Failed to acquire org.pulseaudio.Server: %s: %s", error.name, error.message); + pa_log_error("Failed to acquire %s: %s: %s", name, error.name, error.message); else - pa_log_warn("D-Bus name org.pulseaudio.Server already taken. Weird shit!"); + pa_log_error("D-Bus name %s already taken. Weird shit!", name); /* PA cannot be started twice by the same user and hence we can - * ignore mostly the case that org.pulseaudio.Server is already - * taken. */ + * ignore mostly the case that a name is already taken. */ fail: - if (conn) pa_dbus_connection_unref(conn); @@ -399,7 +398,10 @@ int main(int argc, char *argv[]) { int autospawn_fd = -1; pa_bool_t autospawn_locked = FALSE; #ifdef HAVE_DBUS - pa_dbus_connection *dbus = NULL; + pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */ + pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */ + pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */ + pa_bool_t start_server; #endif pa_log_set_ident("pulseaudio"); @@ -416,23 +418,28 @@ int main(int argc, char *argv[]) { if (!getenv("LD_BIND_NOW")) { char *rp; + char *canonical_rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ pa_set_env("LD_BIND_NOW", "1"); + canonical_rp = pa_realpath(PA_BINARY); + if ((rp = pa_readlink("/proc/self/exe"))) { - if (pa_streq(rp, PA_BINARY)) + if (pa_streq(rp, canonical_rp)) pa_assert_se(execv(rp, argv) == 0); else - pa_log_warn("/proc/self/exe does not point to " PA_BINARY ", cannot self execute. Are you playing games?"); + pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); pa_xfree(rp); } else pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); + + pa_xfree(canonical_rp); } #endif @@ -478,6 +485,32 @@ int main(int argc, char *argv[]) { pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET); pa_log_set_show_backtrace(conf->log_backtrace); +#ifdef HAVE_DBUS + /* conf->system_instance and conf->local_server_type control almost the + * same thing; make them agree about what is requested. */ + switch (conf->local_server_type) { + case PA_SERVER_TYPE_UNSET: + conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER; + break; + case PA_SERVER_TYPE_USER: + case PA_SERVER_TYPE_NONE: + conf->system_instance = FALSE; + break; + case PA_SERVER_TYPE_SYSTEM: + conf->system_instance = TRUE; + break; + default: + pa_assert_not_reached(); + } + + start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM); + + if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) { + pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service.")); + conf->system_instance = FALSE; + } +#endif + LTDL_SET_PRELOADED_SYMBOLS(); pa_ltdl_init(); ltdl_init = TRUE; @@ -564,10 +597,12 @@ int main(int argc, char *argv[]) { if (getuid() == 0 && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); +#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */ else if (getuid() != 0 && conf->system_instance) { pa_log(_("Root privileges required.")); goto finish; } +#endif if (conf->cmd == PA_CMD_START && conf->system_instance) { pa_log(_("--start not supported for system instances.")); @@ -854,6 +889,9 @@ int main(int argc, char *argv[]) { c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; c->flat_volumes = conf->flat_volumes; +#ifdef HAVE_DBUS + c->server_type = conf->local_server_type; +#endif pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); @@ -876,34 +914,47 @@ int main(int argc, char *argv[]) { pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0); buf = pa_strbuf_new(); - if (conf->load_default_script_file) { - FILE *f; - if ((f = pa_daemon_conf_open_default_script_file(conf))) { - r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); - fclose(f); +#ifdef HAVE_DBUS + if (start_server) { +#endif + if (conf->load_default_script_file) { + FILE *f; + + if ((f = pa_daemon_conf_open_default_script_file(conf))) { + r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); + fclose(f); + } } - } - if (r >= 0) - r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); + if (r >= 0) + r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); - pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); - pa_xfree(s); + pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); + pa_xfree(s); - /* We completed the initial module loading, so let's disable it - * from now on, if requested */ - c->disallow_module_loading = !!conf->disallow_module_loading; + if (r < 0 && conf->fail) { + pa_log(_("Failed to initialize daemon.")); + goto finish; + } - if (r < 0 && conf->fail) { - pa_log(_("Failed to initialize daemon.")); - goto finish; + if (!c->modules || pa_idxset_size(c->modules) == 0) { + pa_log(_("Daemon startup without any loaded modules, refusing to work.")); + goto finish; + } +#ifdef HAVE_DBUS + } else { + /* When we just provide the D-Bus server lookup service, we don't want + * any modules to be loaded. We haven't loaded any so far, so one might + * think there's no way to contact the server, but receiving certain + * signals could still cause modules to load. */ + conf->disallow_module_loading = TRUE; } +#endif - if (!c->modules || pa_idxset_size(c->modules) == 0) { - pa_log(_("Daemon startup without any loaded modules, refusing to work.")); - goto finish; - } + /* We completed the initial module loading, so let's disable it + * from now on, if requested */ + c->disallow_module_loading = !!conf->disallow_module_loading; #ifdef HAVE_FORK if (daemon_pipe[1] >= 0) { @@ -915,7 +966,15 @@ int main(int argc, char *argv[]) { #endif #ifdef HAVE_DBUS - dbus = register_dbus(c); + if (!conf->system_instance) { + if (!(server_lookup = pa_dbusobj_server_lookup_new(c))) + goto finish; + if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1"))) + goto finish; + } + + if (start_server && !(server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server"))) + goto finish; #endif pa_log_info(_("Daemon startup complete.")); @@ -928,8 +987,12 @@ int main(int argc, char *argv[]) { finish: #ifdef HAVE_DBUS - if (dbus) - pa_dbus_connection_unref(dbus); + if (server_bus) + pa_dbus_connection_unref(server_bus); + if (lookup_service_bus) + pa_dbus_connection_unref(lookup_service_bus); + if (server_lookup) + pa_dbusobj_server_lookup_free(server_lookup); #endif if (autospawn_fd >= 0) { diff --git a/src/daemon/org.pulseaudio.policy.in b/src/daemon/org.pulseaudio.policy.in deleted file mode 100644 index 1d0b6a7d..00000000 --- a/src/daemon/org.pulseaudio.policy.in +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*--> -<!DOCTYPE policyconfig PUBLIC - "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" - "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> - -<!-- -This file is part of PulseAudio. - -PulseAudio 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. - -PulseAudio 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 PulseAudio; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -USA. ---> - -<policyconfig> - <vendor>The PulseAudio Project</vendor> - <vendor_url>http://pulseaudio.org/</vendor_url> - <icon_name>audio-card</icon_name> - - <action id="org.pulseaudio.acquire-real-time"> - <_description>Real-time scheduling for the PulseAudio daemon</_description> - <_message>System policy prevents PulseAudio from acquiring real-time scheduling.</_message> - <defaults> - <allow_any>no</allow_any> - <allow_inactive>no</allow_inactive> - <allow_active>no</allow_active> - </defaults> - </action> - - <action id="org.pulseaudio.acquire-high-priority"> - <_description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</_description> - <_message>System policy prevents PulseAudio from acquiring high-priority scheduling.</_message> - <defaults> - <allow_any>no</allow_any> - <allow_inactive>no</allow_inactive> - <allow_active>no</allow_active> - </defaults> - </action> - -</policyconfig> diff --git a/src/daemon/pulseaudio-kde.desktop.in b/src/daemon/pulseaudio-kde.desktop.in new file mode 100644 index 00000000..06846421 --- /dev/null +++ b/src/daemon/pulseaudio-kde.desktop.in @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +_Name=PulseAudio Sound System KDE Routing Policy +_Comment=Start the PulseAudio Sound System with KDE Routing Policy +Exec=start-pulseaudio-kde +Terminal=false +Type=Application +Categories= +GenericName= +OnlyShowIn=KDE; diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c new file mode 100644 index 00000000..45796e72 --- /dev/null +++ b/src/daemon/server-lookup.c @@ -0,0 +1,522 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulse/client-conf.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/core.h> +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-shared.h> +#include <pulsecore/macro.h> +#include <pulsecore/protocol-dbus.h> + +#include "server-lookup.h" + +#define OBJECT_PATH "/org/pulseaudio/server_lookup1" +#define INTERFACE "org.PulseAudio.ServerLookup1" + +struct pa_dbusobj_server_lookup { + pa_core *core; + pa_dbus_connection *conn; + pa_bool_t path_registered; +}; + +static const char introspection[] = + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "<node>" + " <!-- If you are looking for documentation make sure to check out\n" + " http://pulseaudio.org/wiki/DBusInterface -->\n" + " <interface name=\"" INTERFACE "\">\n" + " <property name=\"Address\" type=\"s\" access=\"read\"/>\n" + " </interface>\n" + " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" + " <method name=\"Introspect\">\n" + " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" + " </method>\n" + " </interface>\n" + " <interface name=\"" DBUS_INTERFACE_PROPERTIES "\">\n" + " <method name=\"Get\">\n" + " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"value\" type=\"v\" direction=\"out\"/>\n" + " </method>\n" + " <method name=\"Set\">\n" + " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"value\" type=\"v\" direction=\"in\"/>\n" + " </method>\n" + " <method name=\"GetAll\">\n" + " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"props\" type=\"a{sv}\" direction=\"out\"/>\n" + " </method>\n" + " </interface>\n" + "</node>\n"; + +static void unregister_cb(DBusConnection *conn, void *user_data) { + pa_dbusobj_server_lookup *sl = user_data; + + pa_assert(sl); + pa_assert(sl->path_registered); + + sl->path_registered = FALSE; +} + +static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + const char *i = introspection; + DBusMessage *reply = NULL; + + pa_assert(conn); + pa_assert(msg); + + if (!(reply = dbus_message_new_method_return(msg))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &i, DBUS_TYPE_INVALID)) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + +finish: + if (reply) + dbus_message_unref(reply); + + return r; +} + +enum get_address_result_t { + SUCCESS, + FAILED_TO_LOAD_CLIENT_CONF, + SERVER_FROM_TYPE_FAILED +}; + +/* Caller frees the returned address. */ +static enum get_address_result_t get_address(pa_server_type_t server_type, char **address) { + enum get_address_result_t r = SUCCESS; + pa_client_conf *conf = pa_client_conf_new(); + + *address = NULL; + + if (pa_client_conf_load(conf, NULL) < 0) { + r = FAILED_TO_LOAD_CLIENT_CONF; + goto finish; + } + + if (conf->default_dbus_server) + *address = pa_xstrdup(conf->default_dbus_server); + else if (!(*address = pa_get_dbus_address_from_server_type(server_type))) { + r = SERVER_FROM_TYPE_FAILED; + goto finish; + } + +finish: + pa_client_conf_free(conf); + return r; +} + +static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + DBusMessage *reply = NULL; + char *address = NULL; + DBusMessageIter msg_iter; + DBusMessageIter variant_iter; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + switch (get_address(sl->core->server_type, &address)) { + case SUCCESS: + if (!(reply = dbus_message_new_method_return(msg))) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + dbus_message_iter_init_append(reply, &msg_iter); + if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&msg_iter, &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case FAILED_TO_LOAD_CLIENT_CONF: + if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case SERVER_FROM_TYPE_FAILED: + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + default: + pa_assert_not_reached(); + } + +finish: + pa_xfree(address); + if (reply) + dbus_message_unref(reply); + + return r; +} + +static DBusHandlerResult handle_get(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + const char* interface; + const char* property; + DBusMessage *reply = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + if (*interface && !pa_streq(interface, INTERFACE)) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + + if (!pa_streq(property, "Address")) { + if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + r = handle_get_address(conn, msg, sl); + +finish: + if (reply) + dbus_message_unref(reply); + + return r; +} + +static DBusHandlerResult handle_set(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + const char* interface; + const char* property; + DBusMessage *reply = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + if (*interface && !pa_streq(interface, INTERFACE)) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + + if (!pa_streq(property, "Address")) { + if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + if (!(reply = dbus_message_new_error_printf(msg, DBUS_ERROR_ACCESS_DENIED, "%s: Property not settable", property))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + +finish: + if (reply) + dbus_message_unref(reply); + + return r; +} + +static DBusHandlerResult handle_get_all(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + DBusMessage *reply = NULL; + const char *property = "Address"; + char *interface = NULL; + char *address = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + DBusMessageIter variant_iter; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + switch (get_address(sl->core->server_type, &address)) { + case SUCCESS: + if (!(reply = dbus_message_new_method_return(msg))) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + dbus_message_iter_init_append(reply, &msg_iter); + if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &property)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&dict_entry_iter, &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&msg_iter, &dict_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case FAILED_TO_LOAD_CLIENT_CONF: + if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case SERVER_FROM_TYPE_FAILED: + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + default: + pa_assert_not_reached(); + } + +finish: + pa_xfree(address); + if (reply) + dbus_message_unref(reply); + + return r; +} + +static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) { + pa_dbusobj_server_lookup *sl = user_data; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + /* pa_log("Got message! type = %s path = %s iface = %s member = %s dest = %s", dbus_message_type_to_string(dbus_message_get_type(msg)), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), dbus_message_get_destination(msg)); */ + + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, "Introspect") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Introspect"))) + return handle_introspect(conn, msg, sl); + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Get") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Get"))) + return handle_get(conn, msg, sl); + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Set") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Set"))) + return handle_set(conn, msg, sl); + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "GetAll") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "GetAll"))) + return handle_get_all(conn, msg, sl); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable vtable = { + .unregister_function = unregister_cb, + .message_function = message_cb, + .dbus_internal_pad1 = NULL, + .dbus_internal_pad2 = NULL, + .dbus_internal_pad3 = NULL, + .dbus_internal_pad4 = NULL +}; + +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c) { + pa_dbusobj_server_lookup *sl; + DBusError error; + + dbus_error_init(&error); + + sl = pa_xnew(pa_dbusobj_server_lookup, 1); + sl->core = c; + sl->path_registered = FALSE; + + if (!(sl->conn = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { + pa_log("Unable to contact D-Bus: %s: %s", error.name, error.message); + goto fail; + } + + if (!dbus_connection_register_object_path(pa_dbus_connection_get(sl->conn), OBJECT_PATH, &vtable, sl)) { + pa_log("dbus_connection_register_object_path() failed for " OBJECT_PATH "."); + goto fail; + } + + sl->path_registered = TRUE; + + return sl; + +fail: + dbus_error_free(&error); + + pa_dbusobj_server_lookup_free(sl); + + return NULL; +} + +void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl) { + pa_assert(sl); + + if (sl->path_registered) { + pa_assert(sl->conn); + if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(sl->conn), OBJECT_PATH)) + pa_log_debug("dbus_connection_unregister_object_path() failed for " OBJECT_PATH "."); + } + + if (sl->conn) + pa_dbus_connection_unref(sl->conn); + + pa_xfree(sl); +} diff --git a/src/daemon/server-lookup.h b/src/daemon/server-lookup.h new file mode 100644 index 00000000..c930d5b7 --- /dev/null +++ b/src/daemon/server-lookup.h @@ -0,0 +1,40 @@ +#ifndef fooserverlookuphfoo +#define fooserverlookuphfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus object at path + * /org/pulseaudio/server_lookup. Implemented interfaces + * are org.pulseaudio.ServerLookup and org.freedesktop.DBus.Introspectable. + * + * See http://pulseaudio.org/wiki/DBusInterface for the ServerLookup interface + * documentation. + */ + +#include <pulsecore/core.h> + +typedef struct pa_dbusobj_server_lookup pa_dbusobj_server_lookup; + +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c); +void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl); + +#endif diff --git a/src/daemon/start-pulseaudio-kde.in b/src/daemon/start-pulseaudio-kde.in new file mode 100755 index 00000000..c319e7dd --- /dev/null +++ b/src/daemon/start-pulseaudio-kde.in @@ -0,0 +1,30 @@ +#!/bin/sh + +# This file is part of PulseAudio. +# +# PulseAudio 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 of the License, or +# (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +set -e + +[ -z "$PULSE_SERVER" ] + +@PA_BINARY@ --start "$@" + +if [ x"$DISPLAY" != x ] ; then + + @PACTL_BINARY@ load-module module-device-manager "do_routing=1" > /dev/null + +fi diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in index 27e42815..0ca32bd3 100755 --- a/src/daemon/system.pa.in +++ b/src/daemon/system.pa.in @@ -32,6 +32,10 @@ load-module module-detect .ifexists module-esound-protocol-unix@PA_SOEXT@ load-module module-esound-protocol-unix .endif +.ifexists module-dbus-protocol@PA_SOEXT@ +### If you want to allow TCP connections, set access to "remote" or "local,remote". +load-module module-dbus-protocol access=local +.endif load-module module-native-protocol-unix ### Automatically restore the volume of streams and devices diff --git a/src/map-file b/src/map-file index 95b2803a..6f7bdace 100644 --- a/src/map-file +++ b/src/map-file @@ -144,6 +144,14 @@ pa_cvolume_set_fade; pa_cvolume_set_position; pa_cvolume_snprint; pa_cvolume_valid; +pa_ext_device_manager_delete; +pa_ext_device_manager_enable_role_device_priority_routing; +pa_ext_device_manager_read; +pa_ext_device_manager_reorder_devices_for_role; +pa_ext_device_manager_set_device_description; +pa_ext_device_manager_set_subscribe_cb; +pa_ext_device_manager_subscribe; +pa_ext_device_manager_test; pa_ext_stream_restore_delete; pa_ext_stream_restore_read; pa_ext_stream_restore_set_subscribe_cb; @@ -185,6 +193,7 @@ pa_path_get_filename; pa_proplist_clear; pa_proplist_contains; pa_proplist_copy; +pa_proplist_equal; pa_proplist_free; pa_proplist_from_string; pa_proplist_get; diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 22e88b4a..37419d98 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -927,7 +927,7 @@ static int update_sw_params(struct userdata *u) { pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min); - if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) { + if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched)) < 0) { pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err)); return err; } diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index fa3ac0aa..37dd6476 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -877,7 +877,7 @@ static int update_sw_params(struct userdata *u) { pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min); - if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) { + if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched)) < 0) { pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err)); return err; } diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 43a8e829..0e22d17e 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -403,7 +403,7 @@ finish: return ret; } -int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) { +int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, pa_bool_t period_event) { snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t boundary; int err; @@ -417,7 +417,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) { return err; } - if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, 0)) < 0) { + if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) { pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err)); return err; } diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 265cd28c..f6206fe2 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -51,7 +51,8 @@ int pa_alsa_set_hw_params( int pa_alsa_set_sw_params( snd_pcm_t *pcm, - snd_pcm_uframes_t avail_min); + snd_pcm_uframes_t avail_min, + pa_bool_t period_event); /* Picks a working mapping from the profile set based on the specified ss/map */ snd_pcm_t *pa_alsa_open_by_device_id_auto( diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 4592fca1..0ba1421b 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -74,7 +74,8 @@ PA_MODULE_USAGE( "profile=<a2dp|hsp> " "rate=<sample rate> " "channels=<number of channels> " - "path=<device object path>"); + "path=<device object path> " + "auto_connect=<automatically connect?>"); /* #ifdef NOKIA @@ -98,6 +99,7 @@ static const char* const valid_modargs[] = { "rate", "channels", "path", + "auto_connect", #ifdef NOKIA "sco_sink", "sco_source", @@ -141,6 +143,7 @@ struct userdata { char *address; char *path; pa_bluetooth_discovery *discovery; + pa_bool_t auto_connect; pa_dbus_connection *connection; @@ -399,7 +402,7 @@ static int get_caps(struct userdata *u, uint8_t seid) { pa_assert(u->profile == PROFILE_HSP); msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO; } - msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT; + msg.getcaps_req.flags = u->auto_connect ? BT_FLAG_AUTOCONNECT : 0; if (service_send(u, &msg.getcaps_req.h) < 0) return -1; @@ -2363,6 +2366,12 @@ int pa__init(pa_module* m) { goto fail; } + u->auto_connect = TRUE; + if (pa_modargs_get_value_boolean(ma, "auto_connect", &u->auto_connect)) { + pa_log("Failed to parse auto_connect= argument"); + goto fail; + } + channels = u->sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels > PA_CHANNELS_MAX) { diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index 02fd4240..0085fa8e 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -117,7 +117,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const #endif if (d->audio_source_state >= PA_BT_AUDIO_STATE_CONNECTED) - args = pa_sprintf_malloc("%s profile=\"a2dp_source\"", args); + args = pa_sprintf_malloc("%s profile=\"a2dp_source\" auto_connect=no", args); pa_log_debug("Loading module-bluetooth-device %s", args); m = pa_module_load(u->module->core, "module-bluetooth-device", args); diff --git a/src/modules/dbus/iface-card-profile.c b/src/modules/dbus/iface-card-profile.c new file mode 100644 index 00000000..004e2e88 --- /dev/null +++ b/src/modules/dbus/iface-card-profile.c @@ -0,0 +1,228 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> + +#include "iface-card-profile.h" + +#define OBJECT_NAME "profile" + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_description(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_priority(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +struct pa_dbusiface_card_profile { + uint32_t index; + pa_card_profile *profile; + char *path; + pa_dbus_protocol *dbus_protocol; +}; + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_DESCRIPTION, + PROPERTY_HANDLER_SINKS, + PROPERTY_HANDLER_SOURCES, + PROPERTY_HANDLER_PRIORITY, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_DESCRIPTION] = { .property_name = "Description", .type = "s", .get_cb = handle_get_description, .set_cb = NULL }, + [PROPERTY_HANDLER_SINKS] = { .property_name = "Sinks", .type = "u", .get_cb = handle_get_sinks, .set_cb = NULL }, + [PROPERTY_HANDLER_SOURCES] = { .property_name = "Sources", .type = "u", .get_cb = handle_get_sources, .set_cb = NULL }, + [PROPERTY_HANDLER_PRIORITY] = { .property_name = "Priority", .type = "u", .get_cb = handle_get_priority, .set_cb = NULL }, +}; + +static pa_dbus_interface_info profile_interface_info = { + .name = PA_DBUSIFACE_CARD_PROFILE_INTERFACE, + .method_handlers = NULL, + .n_method_handlers = 0, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = NULL, + .n_signals = 0 +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &p->index); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &p->profile->name); +} + +static void handle_get_description(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &p->profile->description); +} + +static void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + dbus_uint32_t sinks = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + sinks = p->profile->n_sinks; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sinks); +} + +static void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + dbus_uint32_t sources = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + sources = p->profile->n_sources; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sources); +} + +static void handle_get_priority(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + dbus_uint32_t priority = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + priority = p->profile->priority; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &priority); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card_profile *p = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t sinks = 0; + dbus_uint32_t sources = 0; + dbus_uint32_t priority = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + sinks = p->profile->n_sinks; + sources = p->profile->n_sources; + priority = p->profile->priority; + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &p->index); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &p->profile->name); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DESCRIPTION].property_name, DBUS_TYPE_STRING, &p->profile->description); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SINKS].property_name, DBUS_TYPE_UINT32, &sinks); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SOURCES].property_name, DBUS_TYPE_UINT32, &sources); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PRIORITY].property_name, DBUS_TYPE_UINT32, &priority); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} + +pa_dbusiface_card_profile *pa_dbusiface_card_profile_new( + pa_dbusiface_card *card, + pa_core *core, + pa_card_profile *profile, + uint32_t idx) { + pa_dbusiface_card_profile *p = NULL; + + pa_assert(card); + pa_assert(core); + pa_assert(profile); + + p = pa_xnew(pa_dbusiface_card_profile, 1); + p->index = idx; + p->profile = profile; + p->path = pa_sprintf_malloc("%s/%s%u", pa_dbusiface_card_get_path(card), OBJECT_NAME, idx); + p->dbus_protocol = pa_dbus_protocol_get(core); + + pa_assert_se(pa_dbus_protocol_add_interface(p->dbus_protocol, p->path, &profile_interface_info, p) >= 0); + + return p; +} + +void pa_dbusiface_card_profile_free(pa_dbusiface_card_profile *p) { + pa_assert(p); + + pa_assert_se(pa_dbus_protocol_remove_interface(p->dbus_protocol, p->path, profile_interface_info.name) >= 0); + + pa_dbus_protocol_unref(p->dbus_protocol); + + pa_xfree(p->path); + pa_xfree(p); +} + +const char *pa_dbusiface_card_profile_get_path(pa_dbusiface_card_profile *p) { + pa_assert(p); + + return p->path; +} + +const char *pa_dbusiface_card_profile_get_name(pa_dbusiface_card_profile *p) { + pa_assert(p); + + return p->profile->name; +} diff --git a/src/modules/dbus/iface-card-profile.h b/src/modules/dbus/iface-card-profile.h new file mode 100644 index 00000000..a09767f8 --- /dev/null +++ b/src/modules/dbus/iface-card-profile.h @@ -0,0 +1,50 @@ +#ifndef foodbusifacecardprofilehfoo +#define foodbusifacecardprofilehfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.CardProfile. + * + * See http://pulseaudio.org/wiki/DBusInterface for the CardProfile interface + * documentation. + */ + +#include <pulsecore/core-scache.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-card.h" + +#define PA_DBUSIFACE_CARD_PROFILE_INTERFACE PA_DBUS_CORE_INTERFACE ".CardProfile" + +typedef struct pa_dbusiface_card_profile pa_dbusiface_card_profile; + +pa_dbusiface_card_profile *pa_dbusiface_card_profile_new( + pa_dbusiface_card *card, + pa_core *core, + pa_card_profile *profile, + uint32_t idx); +void pa_dbusiface_card_profile_free(pa_dbusiface_card_profile *p); + +const char *pa_dbusiface_card_profile_get_path(pa_dbusiface_card_profile *p); +const char *pa_dbusiface_card_profile_get_name(pa_dbusiface_card_profile *p); + +#endif diff --git a/src/modules/dbus/iface-card.c b/src/modules/dbus/iface-card.c new file mode 100644 index 00000000..1714df36 --- /dev/null +++ b/src/modules/dbus/iface-card.c @@ -0,0 +1,561 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-card-profile.h" + +#include "iface-card.h" + +#define OBJECT_NAME "card" + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_profiles(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_active_profile(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_active_profile(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); + +struct pa_dbusiface_card { + pa_dbusiface_core *core; + + pa_card *card; + char *path; + pa_hashmap *profiles; + uint32_t next_profile_index; + pa_card_profile *active_profile; + pa_proplist *proplist; + + pa_dbus_protocol *dbus_protocol; + pa_subscription *subscription; +}; + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_DRIVER, + PROPERTY_HANDLER_OWNER_MODULE, + PROPERTY_HANDLER_SINKS, + PROPERTY_HANDLER_SOURCES, + PROPERTY_HANDLER_PROFILES, + PROPERTY_HANDLER_ACTIVE_PROFILE, + PROPERTY_HANDLER_PROPERTY_LIST, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, + [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, + [PROPERTY_HANDLER_SINKS] = { .property_name = "Sinks", .type = "ao", .get_cb = handle_get_sinks, .set_cb = NULL }, + [PROPERTY_HANDLER_SOURCES] = { .property_name = "Sources", .type = "ao", .get_cb = handle_get_sources, .set_cb = NULL }, + [PROPERTY_HANDLER_PROFILES] = { .property_name = "Profiles", .type = "ao", .get_cb = handle_get_profiles, .set_cb = NULL }, + [PROPERTY_HANDLER_ACTIVE_PROFILE] = { .property_name = "ActiveProfile", .type = "o", .get_cb = handle_get_active_profile, .set_cb = handle_set_active_profile }, + [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_GET_PROFILE_BY_NAME, + METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info get_profile_by_name_args[] = { { "name", "s", "in" }, { "profile", "o", "out" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_GET_PROFILE_BY_NAME] = { + .method_name = "GetProfileByName", + .arguments = get_profile_by_name_args, + .n_arguments = sizeof(get_profile_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_profile_by_name } +}; + +enum signal_index { + SIGNAL_ACTIVE_PROFILE_UPDATED, + SIGNAL_PROPERTY_LIST_UPDATED, + SIGNAL_MAX +}; + +static pa_dbus_arg_info active_profile_updated_args[] = { { "profile", "o", NULL } }; +static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_ACTIVE_PROFILE_UPDATED] = { .name = "ActiveProfileUpdated", .arguments = active_profile_updated_args, .n_arguments = 1 }, + [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info card_interface_info = { + .name = PA_DBUSIFACE_CARD_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + dbus_uint32_t idx; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + idx = c->card->index; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &c->card->name); +} + +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &c->card->driver); +} + +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + const char *owner_module; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (!c->card->module) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Card %s doesn't have an owner module.", c->card->name); + return; + } + + owner_module = pa_dbusiface_core_get_module_path(c->core, c->card->module); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &owner_module); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_sinks(pa_dbusiface_card *c, unsigned *n) { + const char **sinks = NULL; + unsigned i = 0; + uint32_t idx = 0; + pa_sink *sink = NULL; + + pa_assert(c); + pa_assert(n); + + *n = pa_idxset_size(c->card->sinks); + + if (*n == 0) + return NULL; + + sinks = pa_xnew(const char *, *n); + + PA_IDXSET_FOREACH(sink, c->card->sinks, idx) { + sinks[i] = pa_dbusiface_core_get_sink_path(c->core, sink); + ++i; + } + + return sinks; +} + +static void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + const char **sinks; + unsigned n_sinks; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + sinks = get_sinks(c, &n_sinks); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sinks, n_sinks); + + pa_xfree(sinks); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_sources(pa_dbusiface_card *c, unsigned *n) { + const char **sources = NULL; + unsigned i = 0; + uint32_t idx = 0; + pa_source *source = NULL; + + pa_assert(c); + pa_assert(n); + + *n = pa_idxset_size(c->card->sources); + + if (*n == 0) + return NULL; + + sources = pa_xnew(const char *, *n); + + PA_IDXSET_FOREACH(source, c->card->sinks, idx) { + sources[i] = pa_dbusiface_core_get_source_path(c->core, source); + ++i; + } + + return sources; +} + +static void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + const char **sources; + unsigned n_sources; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + sources = get_sources(c, &n_sources); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sources, n_sources); + + pa_xfree(sources); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_profiles(pa_dbusiface_card *c, unsigned *n) { + const char **profiles; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_card_profile *profile; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->profiles); + + if (*n == 0) + return NULL; + + profiles = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(profile, c->profiles, state) + profiles[i++] = pa_dbusiface_card_profile_get_path(profile); + + return profiles; +} + +static void handle_get_profiles(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + const char **profiles; + unsigned n_profiles; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + profiles = get_profiles(c, &n_profiles); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, profiles, n_profiles); + + pa_xfree(profiles); +} + +static void handle_get_active_profile(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + const char *active_profile; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (!c->active_profile) { + pa_assert(pa_hashmap_isempty(c->profiles)); + + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "The card %s has no profiles, and therefore there's no active profile either.", c->card->name); + return; + } + + active_profile = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &active_profile); +} + +static void handle_set_active_profile(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_card *c = userdata; + const char *new_active_path; + pa_dbusiface_card_profile *new_active; + int r; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(c); + + if (!c->active_profile) { + pa_assert(pa_hashmap_isempty(c->profiles)); + + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "The card %s has no profiles, and therefore there's no active profile either.", + c->card->name); + return; + } + + dbus_message_iter_get_basic(iter, &new_active_path); + + if (!(new_active = pa_hashmap_get(c->profiles, new_active_path))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such profile.", new_active_path); + return; + } + + if ((r = pa_card_set_profile(c->card, pa_dbusiface_card_profile_get_name(new_active), TRUE)) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, + "Internal error in PulseAudio: pa_card_set_profile() failed with error code %i.", r); + return; + } + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_dbus_send_proplist_variant_reply(conn, msg, c->proplist); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t idx; + const char *owner_module = NULL; + const char **sinks = NULL; + unsigned n_sinks = 0; + const char **sources = NULL; + unsigned n_sources = 0; + const char **profiles = NULL; + unsigned n_profiles = 0; + const char *active_profile = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + idx = c->card->index; + if (c->card->module) + owner_module = pa_dbusiface_core_get_module_path(c->core, c->card->module); + sinks = get_sinks(c, &n_sinks); + sources = get_sources(c, &n_sources); + profiles = get_profiles(c, &n_profiles); + if (c->active_profile) + active_profile = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &c->card->name); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &c->card->driver); + + if (owner_module) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module); + + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, sinks, n_sinks); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SOURCES].property_name, DBUS_TYPE_OBJECT_PATH, sources, n_sources); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROFILES].property_name, DBUS_TYPE_OBJECT_PATH, profiles, n_profiles); + + if (active_profile) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACTIVE_PROFILE].property_name, DBUS_TYPE_OBJECT_PATH, &active_profile); + + pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, c->proplist); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(sinks); + pa_xfree(sources); + pa_xfree(profiles); +} + +static void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_card *c = userdata; + const char *profile_name = NULL; + pa_dbusiface_card_profile *profile = NULL; + const char *profile_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &profile_name, DBUS_TYPE_INVALID)); + + if (!(profile = pa_hashmap_get(c->profiles, profile_name))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such profile on card %s.", profile_name, c->card->name); + return; + } + + profile_path = pa_dbusiface_card_profile_get_path(profile); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &profile_path); +} + +static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_card *c = userdata; + DBusMessage *signal = NULL; + + pa_assert(core); + pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CARD); + pa_assert(c); + + /* We can't use idx != c->card->index, because the c->card pointer may + * be stale at this point. */ + if (pa_idxset_get_by_index(core->cards, idx) != c->card) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + if (c->active_profile != c->card->active_profile) { + const char *object_path; + + c->active_profile = c->card->active_profile; + object_path = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); + + pa_assert_se(signal = dbus_message_new_signal(c->path, + PA_DBUSIFACE_CARD_INTERFACE, + signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + if (!pa_proplist_equal(c->proplist, c->card->proplist)) { + DBusMessageIter msg_iter; + + pa_proplist_update(c->proplist, PA_UPDATE_SET, c->card->proplist); + + pa_assert_se(signal = dbus_message_new_signal(c->path, + PA_DBUSIFACE_CARD_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_dbus_append_proplist(&msg_iter, c->proplist); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } +} + +pa_dbusiface_card *pa_dbusiface_card_new(pa_dbusiface_core *core, pa_card *card) { + pa_dbusiface_card *c = NULL; + + pa_assert(core); + pa_assert(card); + + c = pa_xnew0(pa_dbusiface_card, 1); + c->core = core; + c->card = card; + c->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, card->index); + c->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + c->next_profile_index = 0; + c->active_profile = NULL; + c->proplist = pa_proplist_copy(card->proplist); + c->dbus_protocol = pa_dbus_protocol_get(card->core); + c->subscription = pa_subscription_new(card->core, PA_SUBSCRIPTION_MASK_CARD, subscription_cb, c); + + if (card->profiles) { + pa_card_profile *profile; + void *state = NULL; + + PA_HASHMAP_FOREACH(profile, card->profiles, state) { + pa_dbusiface_card_profile *p = pa_dbusiface_card_profile_new(c, card->core, profile, c->next_profile_index++); + pa_hashmap_put(c->profiles, pa_dbusiface_card_profile_get_name(p), p); + } + pa_assert_se(c->active_profile = card->active_profile); + } + + pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, c->path, &card_interface_info, c) >= 0); + + return c; +} + +static void profile_free_cb(void *p, void *userdata) { + pa_dbusiface_card_profile *profile = p; + + pa_assert(profile); + + pa_dbusiface_card_profile_free(profile); +} + +void pa_dbusiface_card_free(pa_dbusiface_card *c) { + pa_assert(c); + + pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, c->path, card_interface_info.name) >= 0); + + pa_hashmap_free(c->profiles, profile_free_cb, NULL); + pa_proplist_free(c->proplist); + pa_dbus_protocol_unref(c->dbus_protocol); + pa_subscription_free(c->subscription); + + pa_xfree(c->path); + pa_xfree(c); +} + +const char *pa_dbusiface_card_get_path(pa_dbusiface_card *c) { + pa_assert(c); + + return c->path; +} diff --git a/src/modules/dbus/iface-card.h b/src/modules/dbus/iface-card.h new file mode 100644 index 00000000..e2c08a3b --- /dev/null +++ b/src/modules/dbus/iface-card.h @@ -0,0 +1,45 @@ +#ifndef foodbusifacecardhfoo +#define foodbusifacecardhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.Card. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Card interface + * documentation. + */ + +#include <pulsecore/card.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_CARD_INTERFACE PA_DBUS_CORE_INTERFACE ".Card" + +typedef struct pa_dbusiface_card pa_dbusiface_card; + +pa_dbusiface_card *pa_dbusiface_card_new(pa_dbusiface_core *core, pa_card *card); +void pa_dbusiface_card_free(pa_dbusiface_card *c); + +const char *pa_dbusiface_card_get_path(pa_dbusiface_card *c); + +#endif diff --git a/src/modules/dbus/iface-client.c b/src/modules/dbus/iface-client.c new file mode 100644 index 00000000..546370f9 --- /dev/null +++ b/src/modules/dbus/iface-client.c @@ -0,0 +1,459 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + Copyright 2009 Vincent Filali-Ansary <filali.v@azurdigitalnetworks.net> + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-client.h" + +#define OBJECT_NAME "client" + +struct pa_dbusiface_client { + pa_dbusiface_core *core; + + pa_client *client; + char *path; + pa_proplist *proplist; + + pa_dbus_protocol *dbus_protocol; + pa_subscription *subscription; +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_playback_streams(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_record_streams(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_update_properties(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_remove_properties(DBusConnection *conn, DBusMessage *msg, void *userdata); + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_DRIVER, + PROPERTY_HANDLER_OWNER_MODULE, + PROPERTY_HANDLER_PLAYBACK_STREAMS, + PROPERTY_HANDLER_RECORD_STREAMS, + PROPERTY_HANDLER_PROPERTY_LIST, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, + [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, + [PROPERTY_HANDLER_PLAYBACK_STREAMS] = { .property_name = "PlaybackStreams", .type = "ao", .get_cb = handle_get_playback_streams, .set_cb = NULL }, + [PROPERTY_HANDLER_RECORD_STREAMS] = { .property_name = "RecordStreams", .type = "ao", .get_cb = handle_get_record_streams, .set_cb = NULL }, + [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_KILL, + METHOD_HANDLER_UPDATE_PROPERTIES, + METHOD_HANDLER_REMOVE_PROPERTIES, + METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info update_properties_args[] = { { "property_list", "a{say}", "in" }, { "update_mode", "u", "in" } }; +static pa_dbus_arg_info remove_properties_args[] = { { "keys", "as", "in" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_KILL] = { + .method_name = "Kill", + .arguments = NULL, + .n_arguments = 0, + .receive_cb = handle_kill }, + [METHOD_HANDLER_UPDATE_PROPERTIES] = { + .method_name = "UpdateProperties", + .arguments = update_properties_args, + .n_arguments = sizeof(update_properties_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_update_properties }, + [METHOD_HANDLER_REMOVE_PROPERTIES] = { + .method_name = "RemoveProperties", + .arguments = remove_properties_args, + .n_arguments = sizeof(remove_properties_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_remove_properties } +}; + +enum signal_index { + SIGNAL_PROPERTY_LIST_UPDATED, + SIGNAL_CLIENT_EVENT, + SIGNAL_MAX +}; + +static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; +static pa_dbus_arg_info client_event_args[] = { { "name", "s", NULL }, + { "property_list", "a{say}", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 }, + /* ClientEvent is sent from module-dbus-protocol.c. */ + [SIGNAL_CLIENT_EVENT] = { .name = "ClientEvent", .arguments = client_event_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info client_interface_info = { + .name = PA_DBUSIFACE_CLIENT_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + dbus_uint32_t idx = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + idx = c->client->index; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); +} + +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &c->client->driver); +} + +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + const char *owner_module = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (!c->client->module) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Client %d doesn't have an owner module.", c->client->index); + return; + } + + owner_module = pa_dbusiface_core_get_module_path(c->core, c->client->module); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &owner_module); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_playback_streams(pa_dbusiface_client *c, unsigned *n) { + const char **playback_streams = NULL; + unsigned i = 0; + uint32_t idx = 0; + pa_sink_input *sink_input = NULL; + + pa_assert(c); + pa_assert(n); + + *n = pa_idxset_size(c->client->sink_inputs); + + if (*n == 0) + return NULL; + + playback_streams = pa_xnew(const char *, *n); + + PA_IDXSET_FOREACH(sink_input, c->client->sink_inputs, idx) + playback_streams[i++] = pa_dbusiface_core_get_playback_stream_path(c->core, sink_input); + + return playback_streams; +} + +static void handle_get_playback_streams(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + const char **playback_streams = NULL; + unsigned n_playback_streams = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + playback_streams = get_playback_streams(c, &n_playback_streams); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, playback_streams, n_playback_streams); + + pa_xfree(playback_streams); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_record_streams(pa_dbusiface_client *c, unsigned *n) { + const char **record_streams = NULL; + unsigned i = 0; + uint32_t idx = 0; + pa_source_output *source_output = NULL; + + pa_assert(c); + pa_assert(n); + + *n = pa_idxset_size(c->client->source_outputs); + + if (*n == 0) + return NULL; + + record_streams = pa_xnew(const char *, *n); + + PA_IDXSET_FOREACH(source_output, c->client->source_outputs, idx) + record_streams[i++] = pa_dbusiface_core_get_record_stream_path(c->core, source_output); + + return record_streams; +} + +static void handle_get_record_streams(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + const char **record_streams = NULL; + unsigned n_record_streams = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + record_streams = get_record_streams(c, &n_record_streams); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, record_streams, n_record_streams); + + pa_xfree(record_streams); +} + +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_dbus_send_proplist_variant_reply(conn, msg, c->client->proplist); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t idx = 0; + const char *owner_module = NULL; + const char **playback_streams = NULL; + unsigned n_playback_streams = 0; + const char **record_streams = NULL; + unsigned n_record_streams = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + idx = c->client->index; + if (c->client->module) + owner_module = pa_dbusiface_core_get_module_path(c->core, c->client->module); + playback_streams = get_playback_streams(c, &n_playback_streams); + record_streams = get_record_streams(c, &n_record_streams); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &c->client->driver); + + if (owner_module) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module); + + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PLAYBACK_STREAMS].property_name, DBUS_TYPE_OBJECT_PATH, playback_streams, n_playback_streams); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RECORD_STREAMS].property_name, DBUS_TYPE_OBJECT_PATH, record_streams, n_record_streams); + pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, c->client->proplist); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(playback_streams); + pa_xfree(record_streams); +} + +static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + dbus_connection_ref(conn); + + pa_client_kill(c->client); + + pa_dbus_send_empty_reply(conn, msg); + + dbus_connection_unref(conn); +} + +static void handle_update_properties(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + DBusMessageIter msg_iter; + pa_proplist *property_list = NULL; + dbus_uint32_t update_mode = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (pa_dbus_protocol_get_client(c->dbus_protocol, conn) != c->client) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "Client tried to modify the property list of another client."); + return; + } + + pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); + + if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter))) + return; + + dbus_message_iter_get_basic(&msg_iter, &update_mode); + + if (!(update_mode == PA_UPDATE_SET || update_mode == PA_UPDATE_MERGE || update_mode == PA_UPDATE_REPLACE)) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid update mode: %u", update_mode); + goto finish; + } + + pa_client_update_proplist(c->client, update_mode, property_list); + + pa_dbus_send_empty_reply(conn, msg); + +finish: + if (property_list) + pa_proplist_free(property_list); +} + +static void handle_remove_properties(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_client *c = userdata; + char **keys = NULL; + int n_keys = 0; + pa_bool_t changed = FALSE; + int i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (pa_dbus_protocol_get_client(c->dbus_protocol, conn) != c->client) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "Client tried to modify the property list of another client."); + return; + } + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &keys, &n_keys, DBUS_TYPE_INVALID)); + + for (i = 0; i < n_keys; ++i) + changed |= pa_proplist_unset(c->client->proplist, keys[i]) >= 0; + + pa_dbus_send_empty_reply(conn, msg); + + if (changed) + pa_subscription_post(c->client->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index); + + dbus_free_string_array(keys); +} + +static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_client *c = userdata; + DBusMessage *signal = NULL; + + pa_assert(core); + pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CLIENT); + pa_assert(c); + + /* We can't use idx != c->client->index, because the c->client pointer may + * be stale at this point. */ + if (pa_idxset_get_by_index(core->clients, idx) != c->client) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + if (!pa_proplist_equal(c->proplist, c->client->proplist)) { + DBusMessageIter msg_iter; + + pa_proplist_update(c->proplist, PA_UPDATE_SET, c->client->proplist); + + pa_assert_se(signal = dbus_message_new_signal(c->path, + PA_DBUSIFACE_CLIENT_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_dbus_append_proplist(&msg_iter, c->proplist); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } +} + +pa_dbusiface_client *pa_dbusiface_client_new(pa_dbusiface_core *core, pa_client *client) { + pa_dbusiface_client *c = NULL; + + pa_assert(core); + pa_assert(client); + + c = pa_xnew(pa_dbusiface_client, 1); + c->core = core; + c->client = client; + c->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, client->index); + c->proplist = pa_proplist_copy(client->proplist); + c->dbus_protocol = pa_dbus_protocol_get(client->core); + c->subscription = pa_subscription_new(client->core, PA_SUBSCRIPTION_MASK_CLIENT, subscription_cb, c); + + pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, c->path, &client_interface_info, c) >= 0); + + return c; +} + +void pa_dbusiface_client_free(pa_dbusiface_client *c) { + pa_assert(c); + + pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, c->path, client_interface_info.name) >= 0); + + pa_dbus_protocol_unref(c->dbus_protocol); + + pa_xfree(c->path); + pa_xfree(c); +} + +const char *pa_dbusiface_client_get_path(pa_dbusiface_client *c) { + pa_assert(c); + + return c->path; +} diff --git a/src/modules/dbus/iface-client.h b/src/modules/dbus/iface-client.h new file mode 100644 index 00000000..e8f151cd --- /dev/null +++ b/src/modules/dbus/iface-client.h @@ -0,0 +1,45 @@ +#ifndef foodbusifaceclienthfoo +#define foodbusifaceclienthfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.Client. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Client interface + * documentation. + */ + +#include <pulsecore/client.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_CLIENT_INTERFACE PA_DBUS_CORE_INTERFACE ".Client" + +typedef struct pa_dbusiface_client pa_dbusiface_client; + +pa_dbusiface_client *pa_dbusiface_client_new(pa_dbusiface_core *core, pa_client *client); +void pa_dbusiface_client_free(pa_dbusiface_client *c); + +const char *pa_dbusiface_client_get_path(pa_dbusiface_client *c); + +#endif diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c new file mode 100644 index 00000000..169e8e55 --- /dev/null +++ b/src/modules/dbus/iface-core.c @@ -0,0 +1,2197 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <ctype.h> + +#include <dbus/dbus.h> + +#include <pulse/utf8.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/macro.h> +#include <pulsecore/namereg.h> +#include <pulsecore/protocol-dbus.h> +#include <pulsecore/socket-util.h> +#include <pulsecore/strbuf.h> + +#include "iface-card.h" +#include "iface-client.h" +#include "iface-device.h" +#include "iface-memstats.h" +#include "iface-module.h" +#include "iface-sample.h" +#include "iface-stream.h" + +#include "iface-core.h" + +#define INTERFACE_REVISION 0 + +static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_version(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_is_local(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_username(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_hostname(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_default_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_default_channels(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_default_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_default_sample_format(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_default_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_default_sample_rate(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_cards(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_fallback_sink(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_fallback_sink(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_fallback_source(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_fallback_source(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_playback_streams(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_record_streams(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_samples(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_modules(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_clients(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_my_client(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_extensions(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_card_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sink_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_source_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_upload_sample(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_load_module(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_exit(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata); + +struct pa_dbusiface_core { + pa_core *core; + pa_subscription *subscription; + + pa_dbus_protocol *dbus_protocol; + + pa_hashmap *cards; + pa_hashmap *sinks_by_index; + pa_hashmap *sinks_by_path; + pa_hashmap *sources_by_index; + pa_hashmap *sources_by_path; + pa_hashmap *playback_streams; + pa_hashmap *record_streams; + pa_hashmap *samples; + pa_hashmap *modules; + pa_hashmap *clients; + + pa_sink *fallback_sink; + pa_source *fallback_source; + + pa_hook_slot *extension_registered_slot; + pa_hook_slot *extension_unregistered_slot; + + pa_dbusiface_memstats *memstats; +}; + +enum property_handler_index { + PROPERTY_HANDLER_INTERFACE_REVISION, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_VERSION, + PROPERTY_HANDLER_IS_LOCAL, + PROPERTY_HANDLER_USERNAME, + PROPERTY_HANDLER_HOSTNAME, + PROPERTY_HANDLER_DEFAULT_CHANNELS, + PROPERTY_HANDLER_DEFAULT_SAMPLE_FORMAT, + PROPERTY_HANDLER_DEFAULT_SAMPLE_RATE, + PROPERTY_HANDLER_CARDS, + PROPERTY_HANDLER_SINKS, + PROPERTY_HANDLER_FALLBACK_SINK, + PROPERTY_HANDLER_SOURCES, + PROPERTY_HANDLER_FALLBACK_SOURCE, + PROPERTY_HANDLER_PLAYBACK_STREAMS, + PROPERTY_HANDLER_RECORD_STREAMS, + PROPERTY_HANDLER_SAMPLES, + PROPERTY_HANDLER_MODULES, + PROPERTY_HANDLER_CLIENTS, + PROPERTY_HANDLER_MY_CLIENT, + PROPERTY_HANDLER_EXTENSIONS, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_VERSION] = { .property_name = "Version", .type = "s", .get_cb = handle_get_version, .set_cb = NULL }, + [PROPERTY_HANDLER_IS_LOCAL] = { .property_name = "IsLocal", .type = "b", .get_cb = handle_get_is_local, .set_cb = NULL }, + [PROPERTY_HANDLER_USERNAME] = { .property_name = "Username", .type = "s", .get_cb = handle_get_username, .set_cb = NULL }, + [PROPERTY_HANDLER_HOSTNAME] = { .property_name = "Hostname", .type = "s", .get_cb = handle_get_hostname, .set_cb = NULL }, + [PROPERTY_HANDLER_DEFAULT_CHANNELS] = { .property_name = "DefaultChannels", .type = "au", .get_cb = handle_get_default_channels, .set_cb = handle_set_default_channels }, + [PROPERTY_HANDLER_DEFAULT_SAMPLE_FORMAT] = { .property_name = "DefaultSampleFormat", .type = "u", .get_cb = handle_get_default_sample_format, .set_cb = handle_set_default_sample_format }, + [PROPERTY_HANDLER_DEFAULT_SAMPLE_RATE] = { .property_name = "DefaultSampleRate", .type = "u", .get_cb = handle_get_default_sample_rate, .set_cb = handle_set_default_sample_rate }, + [PROPERTY_HANDLER_CARDS] = { .property_name = "Cards", .type = "ao", .get_cb = handle_get_cards, .set_cb = NULL }, + [PROPERTY_HANDLER_SINKS] = { .property_name = "Sinks", .type = "ao", .get_cb = handle_get_sinks, .set_cb = NULL }, + [PROPERTY_HANDLER_FALLBACK_SINK] = { .property_name = "FallbackSink", .type = "o", .get_cb = handle_get_fallback_sink, .set_cb = handle_set_fallback_sink }, + [PROPERTY_HANDLER_SOURCES] = { .property_name = "Sources", .type = "ao", .get_cb = handle_get_sources, .set_cb = NULL }, + [PROPERTY_HANDLER_FALLBACK_SOURCE] = { .property_name = "FallbackSource", .type = "o", .get_cb = handle_get_fallback_source, .set_cb = handle_set_fallback_source }, + [PROPERTY_HANDLER_PLAYBACK_STREAMS] = { .property_name = "PlaybackStreams", .type = "ao", .get_cb = handle_get_playback_streams, .set_cb = NULL }, + [PROPERTY_HANDLER_RECORD_STREAMS] = { .property_name = "RecordStreams", .type = "ao", .get_cb = handle_get_record_streams, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLES] = { .property_name = "Samples", .type = "ao", .get_cb = handle_get_samples, .set_cb = NULL }, + [PROPERTY_HANDLER_MODULES] = { .property_name = "Modules", .type = "ao", .get_cb = handle_get_modules, .set_cb = NULL }, + [PROPERTY_HANDLER_CLIENTS] = { .property_name = "Clients", .type = "ao", .get_cb = handle_get_clients, .set_cb = NULL }, + [PROPERTY_HANDLER_MY_CLIENT] = { .property_name = "MyClient", .type = "o", .get_cb = handle_get_my_client, .set_cb = NULL }, + [PROPERTY_HANDLER_EXTENSIONS] = { .property_name = "Extensions", .type = "as", .get_cb = handle_get_extensions, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_GET_CARD_BY_NAME, + METHOD_HANDLER_GET_SINK_BY_NAME, + METHOD_HANDLER_GET_SOURCE_BY_NAME, + METHOD_HANDLER_GET_SAMPLE_BY_NAME, + METHOD_HANDLER_UPLOAD_SAMPLE, + METHOD_HANDLER_LOAD_MODULE, + METHOD_HANDLER_EXIT, + METHOD_HANDLER_LISTEN_FOR_SIGNAL, + METHOD_HANDLER_STOP_LISTENING_FOR_SIGNAL, + METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info get_card_by_name_args[] = { { "name", "s", "in" }, { "card", "o", "out" } }; +static pa_dbus_arg_info get_sink_by_name_args[] = { { "name", "s", "in" }, { "sink", "o", "out" } }; +static pa_dbus_arg_info get_source_by_name_args[] = { { "name", "s", "in" }, { "source", "o", "out" } }; +static pa_dbus_arg_info get_sample_by_name_args[] = { { "name", "s", "in" }, { "sample", "o", "out" } }; +static pa_dbus_arg_info upload_sample_args[] = { { "name", "s", "in" }, + { "sample_format", "u", "in" }, + { "sample_rate", "u", "in" }, + { "channels", "au", "in" }, + { "default_volume", "au", "in" }, + { "property_list", "a{say}", "in" }, + { "data", "ay", "in" }, + { "sample", "o", "out" } }; +static pa_dbus_arg_info load_module_args[] = { { "name", "s", "in" }, { "arguments", "a{ss}", "in" }, { "module", "o", "out" } }; +static pa_dbus_arg_info listen_for_signal_args[] = { { "signal", "s", "in" }, { "objects", "ao", "in" } }; +static pa_dbus_arg_info stop_listening_for_signal_args[] = { { "signal", "s", "in" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_GET_CARD_BY_NAME] = { + .method_name = "GetCardByName", + .arguments = get_card_by_name_args, + .n_arguments = sizeof(get_card_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_card_by_name }, + [METHOD_HANDLER_GET_SINK_BY_NAME] = { + .method_name = "GetSinkByName", + .arguments = get_sink_by_name_args, + .n_arguments = sizeof(get_sink_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_sink_by_name }, + [METHOD_HANDLER_GET_SOURCE_BY_NAME] = { + .method_name = "GetSourceByName", + .arguments = get_source_by_name_args, + .n_arguments = sizeof(get_source_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_source_by_name }, + [METHOD_HANDLER_GET_SAMPLE_BY_NAME] = { + .method_name = "GetSampleByName", + .arguments = get_sample_by_name_args, + .n_arguments = sizeof(get_sample_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_sample_by_name }, + [METHOD_HANDLER_UPLOAD_SAMPLE] = { + .method_name = "UploadSample", + .arguments = upload_sample_args, + .n_arguments = sizeof(upload_sample_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_upload_sample }, + [METHOD_HANDLER_LOAD_MODULE] = { + .method_name = "LoadModule", + .arguments = load_module_args, + .n_arguments = sizeof(load_module_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_load_module }, + [METHOD_HANDLER_EXIT] = { + .method_name = "Exit", + .arguments = NULL, + .n_arguments = 0, + .receive_cb = handle_exit }, + [METHOD_HANDLER_LISTEN_FOR_SIGNAL] = { + .method_name = "ListenForSignal", + .arguments = listen_for_signal_args, + .n_arguments = sizeof(listen_for_signal_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_listen_for_signal }, + [METHOD_HANDLER_STOP_LISTENING_FOR_SIGNAL] = { + .method_name = "StopListeningForSignal", + .arguments = stop_listening_for_signal_args, + .n_arguments = sizeof(stop_listening_for_signal_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_stop_listening_for_signal } +}; + +enum signal_index { + SIGNAL_NEW_CARD, + SIGNAL_CARD_REMOVED, + SIGNAL_NEW_SINK, + SIGNAL_SINK_REMOVED, + SIGNAL_FALLBACK_SINK_UPDATED, + SIGNAL_FALLBACK_SINK_UNSET, + SIGNAL_NEW_SOURCE, + SIGNAL_SOURCE_REMOVED, + SIGNAL_FALLBACK_SOURCE_UPDATED, + SIGNAL_FALLBACK_SOURCE_UNSET, + SIGNAL_NEW_PLAYBACK_STREAM, + SIGNAL_PLAYBACK_STREAM_REMOVED, + SIGNAL_NEW_RECORD_STREAM, + SIGNAL_RECORD_STREAM_REMOVED, + SIGNAL_NEW_SAMPLE, + SIGNAL_SAMPLE_REMOVED, + SIGNAL_NEW_MODULE, + SIGNAL_MODULE_REMOVED, + SIGNAL_NEW_CLIENT, + SIGNAL_CLIENT_REMOVED, + SIGNAL_NEW_EXTENSION, + SIGNAL_EXTENSION_REMOVED, + SIGNAL_MAX +}; + +static pa_dbus_arg_info new_card_args[] = { { "card", "o", NULL } }; +static pa_dbus_arg_info card_removed_args[] = { { "card", "o", NULL } }; +static pa_dbus_arg_info new_sink_args[] = { { "sink", "o", NULL } }; +static pa_dbus_arg_info sink_removed_args[] = { { "sink", "o", NULL } }; +static pa_dbus_arg_info fallback_sink_updated_args[] = { { "sink", "o", NULL } }; +static pa_dbus_arg_info new_source_args[] = { { "source", "o", NULL } }; +static pa_dbus_arg_info source_removed_args[] = { { "source", "o", NULL } }; +static pa_dbus_arg_info fallback_source_updated_args[] = { { "source", "o", NULL } }; +static pa_dbus_arg_info new_playback_stream_args[] = { { "playback_stream", "o", NULL } }; +static pa_dbus_arg_info playback_stream_removed_args[] = { { "playback_stream", "o", NULL } }; +static pa_dbus_arg_info new_record_stream_args[] = { { "record_stream", "o", NULL } }; +static pa_dbus_arg_info record_stream_removed_args[] = { { "record_stream", "o", NULL } }; +static pa_dbus_arg_info new_sample_args[] = { { "sample", "o", NULL } }; +static pa_dbus_arg_info sample_removed_args[] = { { "sample", "o", NULL } }; +static pa_dbus_arg_info new_module_args[] = { { "module", "o", NULL } }; +static pa_dbus_arg_info module_removed_args[] = { { "module", "o", NULL } }; +static pa_dbus_arg_info new_client_args[] = { { "client", "o", NULL } }; +static pa_dbus_arg_info client_removed_args[] = { { "client", "o", NULL } }; +static pa_dbus_arg_info new_extension_args[] = { { "extension", "s", NULL } }; +static pa_dbus_arg_info extension_removed_args[] = { { "extension", "s", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_NEW_CARD] = { .name = "NewCard", .arguments = new_card_args, .n_arguments = 1 }, + [SIGNAL_CARD_REMOVED] = { .name = "CardRemoved", .arguments = card_removed_args, .n_arguments = 1 }, + [SIGNAL_NEW_SINK] = { .name = "NewSink", .arguments = new_sink_args, .n_arguments = 1 }, + [SIGNAL_SINK_REMOVED] = { .name = "SinkRemoved", .arguments = sink_removed_args, .n_arguments = 1 }, + [SIGNAL_FALLBACK_SINK_UPDATED] = { .name = "FallbackSinkUpdated", .arguments = fallback_sink_updated_args, .n_arguments = 1 }, + [SIGNAL_FALLBACK_SINK_UNSET] = { .name = "FallbackSinkUnset", .arguments = NULL, .n_arguments = 0 }, + [SIGNAL_NEW_SOURCE] = { .name = "NewSource", .arguments = new_source_args, .n_arguments = 1 }, + [SIGNAL_SOURCE_REMOVED] = { .name = "SourceRemoved", .arguments = source_removed_args, .n_arguments = 1 }, + [SIGNAL_FALLBACK_SOURCE_UPDATED] = { .name = "FallbackSourceUpdated", .arguments = fallback_source_updated_args, .n_arguments = 1 }, + [SIGNAL_FALLBACK_SOURCE_UNSET] = { .name = "FallbackSourceUnset", .arguments = NULL, .n_arguments = 0 }, + [SIGNAL_NEW_PLAYBACK_STREAM] = { .name = "NewPlaybackStream", .arguments = new_playback_stream_args, .n_arguments = 1 }, + [SIGNAL_PLAYBACK_STREAM_REMOVED] = { .name = "PlaybackStreamRemoved", .arguments = playback_stream_removed_args, .n_arguments = 1 }, + [SIGNAL_NEW_RECORD_STREAM] = { .name = "NewRecordStream", .arguments = new_record_stream_args, .n_arguments = 1 }, + [SIGNAL_RECORD_STREAM_REMOVED] = { .name = "RecordStreamRemoved", .arguments = record_stream_removed_args, .n_arguments = 1 }, + [SIGNAL_NEW_SAMPLE] = { .name = "NewSample", .arguments = new_sample_args, .n_arguments = 1 }, + [SIGNAL_SAMPLE_REMOVED] = { .name = "SampleRemoved", .arguments = sample_removed_args, .n_arguments = 1 }, + [SIGNAL_NEW_MODULE] = { .name = "NewModule", .arguments = new_module_args, .n_arguments = 1 }, + [SIGNAL_MODULE_REMOVED] = { .name = "ModuleRemoved", .arguments = module_removed_args, .n_arguments = 1 }, + [SIGNAL_NEW_CLIENT] = { .name = "NewClient", .arguments = new_client_args, .n_arguments = 1 }, + [SIGNAL_CLIENT_REMOVED] = { .name = "ClientRemoved", .arguments = client_removed_args, .n_arguments = 1 }, + [SIGNAL_NEW_EXTENSION] = { .name = "NewExtension", .arguments = new_extension_args, .n_arguments = 1 }, + [SIGNAL_EXTENSION_REMOVED] = { .name = "ExtensionRemoved", .arguments = extension_removed_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info core_interface_info = { + .name = PA_DBUS_CORE_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) { + dbus_uint32_t interface_revision = INTERFACE_REVISION; + + pa_assert(conn); + pa_assert(msg); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + const char *server_name = PACKAGE_NAME; + + pa_assert(conn); + pa_assert(msg); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &server_name); +} + +static void handle_get_version(DBusConnection *conn, DBusMessage *msg, void *userdata) { + const char *version = PACKAGE_VERSION; + + pa_assert(conn); + pa_assert(msg); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &version); +} + +static dbus_bool_t get_is_local(DBusConnection *conn) { + int conn_fd; + + pa_assert(conn); + + if (!dbus_connection_get_socket(conn, &conn_fd)) + return FALSE; + + return pa_socket_is_local(conn_fd); +} + +static void handle_get_is_local(DBusConnection *conn, DBusMessage *msg, void *userdata) { + dbus_bool_t is_local; + + pa_assert(conn); + pa_assert(msg); + + is_local = get_is_local(conn); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_local); +} + +static void handle_get_username(DBusConnection *conn, DBusMessage *msg, void *userdata) { + char *username = NULL; + + pa_assert(conn); + pa_assert(msg); + + username = pa_get_user_name_malloc(); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &username); + + pa_xfree(username); +} + +static void handle_get_hostname(DBusConnection *conn, DBusMessage *msg, void *userdata) { + char *hostname = NULL; + + pa_assert(conn); + pa_assert(msg); + + hostname = pa_get_host_name_malloc(); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &hostname); + + pa_xfree(hostname); +} + +/* Caller frees the returned array. */ +static dbus_uint32_t *get_default_channels(pa_dbusiface_core *c, unsigned *n) { + dbus_uint32_t *default_channels = NULL; + unsigned i; + + pa_assert(c); + pa_assert(n); + + *n = c->core->default_channel_map.channels; + default_channels = pa_xnew(dbus_uint32_t, *n); + + for (i = 0; i < *n; ++i) + default_channels[i] = c->core->default_channel_map.map[i]; + + return default_channels; +} + +static void handle_get_default_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + dbus_uint32_t *default_channels = NULL; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + default_channels = get_default_channels(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, default_channels, n); + + pa_xfree(default_channels); +} + +static void handle_set_default_channels(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_core *c = userdata; + DBusMessageIter array_iter; + pa_channel_map new_channel_map; + const dbus_uint32_t *default_channels; + int n_channels; + unsigned i; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(c); + + pa_channel_map_init(&new_channel_map); + + dbus_message_iter_recurse(iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &default_channels, &n_channels); + + if (n_channels <= 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Empty channel array."); + return; + } + + if (n_channels > (int) PA_CHANNELS_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "Too many channels: %i. The maximum number of channels is %u.", n_channels, PA_CHANNELS_MAX); + return; + } + + new_channel_map.channels = n_channels; + + for (i = 0; i < new_channel_map.channels; ++i) { + if (default_channels[i] >= PA_CHANNEL_POSITION_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u.", default_channels[i]); + return; + } + + new_channel_map.map[i] = default_channels[i]; + } + + c->core->default_channel_map = new_channel_map; + c->core->default_sample_spec.channels = n_channels; + + pa_dbus_send_empty_reply(conn, msg); +}; + +static void handle_get_default_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + dbus_uint32_t default_sample_format; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + default_sample_format = c->core->default_sample_spec.format; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &default_sample_format); +} + +static void handle_set_default_sample_format(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_core *c = userdata; + dbus_uint32_t default_sample_format; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(c); + + dbus_message_iter_get_basic(iter, &default_sample_format); + + if (default_sample_format >= PA_SAMPLE_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample format."); + return; + } + + c->core->default_sample_spec.format = default_sample_format; + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_default_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + dbus_uint32_t default_sample_rate; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + default_sample_rate = c->core->default_sample_spec.rate; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &default_sample_rate); +} + +static void handle_set_default_sample_rate(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_core *c = userdata; + dbus_uint32_t default_sample_rate; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(c); + + dbus_message_iter_get_basic(iter, &default_sample_rate); + + if (default_sample_rate <= 0 || default_sample_rate > PA_RATE_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample rate."); + return; + } + + c->core->default_sample_spec.rate = default_sample_rate; + + pa_dbus_send_empty_reply(conn, msg); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_cards(pa_dbusiface_core *c, unsigned *n) { + const char **cards; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_card *card; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->cards); + + if (*n == 0) + return NULL; + + cards = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(card, c->cards, state) + cards[i++] = pa_dbusiface_card_get_path(card); + + return cards; +} + +static void handle_get_cards(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **cards; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + cards = get_cards(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, cards, n); + + pa_xfree(cards); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_sinks(pa_dbusiface_core *c, unsigned *n) { + const char **sinks; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_device *sink; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->sinks_by_index); + + if (*n == 0) + return NULL; + + sinks = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(sink, c->sinks_by_index, state) + sinks[i++] = pa_dbusiface_device_get_path(sink); + + return sinks; +} + +static void handle_get_sinks(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **sinks; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + sinks = get_sinks(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sinks, n); + + pa_xfree(sinks); +} + +static void handle_get_fallback_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + pa_dbusiface_device *fallback_sink; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (!c->fallback_sink) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "There are no sinks, and therefore no fallback sink either."); + return; + } + + pa_assert_se((fallback_sink = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index)))); + object_path = pa_dbusiface_device_get_path(fallback_sink); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_set_fallback_sink(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_core *c = userdata; + pa_dbusiface_device *fallback_sink; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(c); + + if (!c->fallback_sink) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "There are no sinks, and therefore no fallback sink either."); + return; + } + + dbus_message_iter_get_basic(iter, &object_path); + + if (!(fallback_sink = pa_hashmap_get(c->sinks_by_path, object_path))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", object_path); + return; + } + + pa_namereg_set_default_sink(c->core, pa_dbusiface_device_get_sink(fallback_sink)); + + pa_dbus_send_empty_reply(conn, msg); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_sources(pa_dbusiface_core *c, unsigned *n) { + const char **sources; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_device *source; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->sources_by_index); + + if (*n == 0) + return NULL; + + sources = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(source, c->sources_by_index, state) + sources[i++] = pa_dbusiface_device_get_path(source); + + return sources; +} + +static void handle_get_sources(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **sources; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + sources = get_sources(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, sources, n); + + pa_xfree(sources); +} + +static void handle_get_fallback_source(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + pa_dbusiface_device *fallback_source; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (!c->fallback_source) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "There are no sources, and therefore no fallback source either."); + return; + } + + pa_assert_se((fallback_source = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->fallback_source->index)))); + object_path = pa_dbusiface_device_get_path(fallback_source); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_set_fallback_source(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_core *c = userdata; + pa_dbusiface_device *fallback_source; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(c); + + if (!c->fallback_source) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "There are no sources, and therefore no fallback source either."); + return; + } + + dbus_message_iter_get_basic(iter, &object_path); + + if (!(fallback_source = pa_hashmap_get(c->sources_by_path, object_path))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", object_path); + return; + } + + pa_namereg_set_default_source(c->core, pa_dbusiface_device_get_source(fallback_source)); + + pa_dbus_send_empty_reply(conn, msg); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_playback_streams(pa_dbusiface_core *c, unsigned *n) { + const char **streams; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_stream *stream; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->playback_streams); + + if (*n == 0) + return NULL; + + streams = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(stream, c->playback_streams, state) + streams[i++] = pa_dbusiface_stream_get_path(stream); + + return streams; +} + +static void handle_get_playback_streams(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **playback_streams; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + playback_streams = get_playback_streams(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, playback_streams, n); + + pa_xfree(playback_streams); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_record_streams(pa_dbusiface_core *c, unsigned *n) { + const char **streams; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_stream *stream; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->record_streams); + + if (*n == 0) + return NULL; + + streams = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(stream, c->record_streams, state) + streams[i++] = pa_dbusiface_stream_get_path(stream); + + return streams; +} + +static void handle_get_record_streams(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **record_streams; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + record_streams = get_record_streams(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, record_streams, n); + + pa_xfree(record_streams); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_samples(pa_dbusiface_core *c, unsigned *n) { + const char **samples; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_sample *sample; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->samples); + + if (*n == 0) + return NULL; + + samples = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(sample, c->samples, state) + samples[i++] = pa_dbusiface_sample_get_path(sample); + + return samples; +} + +static void handle_get_samples(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **samples; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + samples = get_samples(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, samples, n); + + pa_xfree(samples); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_modules(pa_dbusiface_core *c, unsigned *n) { + const char **modules; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_module *module; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->modules); + + if (*n == 0) + return NULL; + + modules = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(module, c->modules, state) + modules[i++] = pa_dbusiface_module_get_path(module); + + return modules; +} + +static void handle_get_modules(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **modules; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + modules = get_modules(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, modules, n); + + pa_xfree(modules); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_clients(pa_dbusiface_core *c, unsigned *n) { + const char **clients; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_client *client; + + pa_assert(c); + pa_assert(n); + + *n = pa_hashmap_size(c->clients); + + if (*n == 0) + return NULL; + + clients = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(client, c->clients, state) + clients[i++] = pa_dbusiface_client_get_path(client); + + return clients; +} + +static void handle_get_clients(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **clients; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + clients = get_clients(c, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, clients, n); + + pa_xfree(clients); +} + +static const char *get_my_client(pa_dbusiface_core *c, DBusConnection *conn) { + pa_client *my_client; + + pa_assert(c); + pa_assert(conn); + + pa_assert_se((my_client = pa_dbus_protocol_get_client(c->dbus_protocol, conn))); + + return pa_dbusiface_client_get_path(pa_hashmap_get(c->clients, PA_UINT32_TO_PTR(my_client->index))); +} + +static void handle_get_my_client(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char *my_client; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + my_client = get_my_client(c, conn); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &my_client); +} + +static void handle_get_extensions(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char **extensions; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + extensions = pa_dbus_protocol_get_extensions(c->dbus_protocol, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, extensions, n); + + pa_xfree(extensions); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t interface_revision; + const char *server_name; + const char *version; + dbus_bool_t is_local; + char *username; + char *hostname; + dbus_uint32_t *default_channels; + unsigned n_default_channels; + dbus_uint32_t default_sample_format; + dbus_uint32_t default_sample_rate; + const char **cards; + unsigned n_cards; + const char **sinks; + unsigned n_sinks; + const char *fallback_sink; + const char **sources; + unsigned n_sources; + const char *fallback_source; + const char **playback_streams; + unsigned n_playback_streams; + const char **record_streams; + unsigned n_record_streams; + const char **samples; + unsigned n_samples; + const char **modules; + unsigned n_modules; + const char **clients; + unsigned n_clients; + const char *my_client; + const char **extensions; + unsigned n_extensions; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + interface_revision = INTERFACE_REVISION; + server_name = PACKAGE_NAME; + version = PACKAGE_VERSION; + is_local = get_is_local(conn); + username = pa_get_user_name_malloc(); + hostname = pa_get_host_name_malloc(); + default_channels = get_default_channels(c, &n_default_channels); + default_sample_format = c->core->default_sample_spec.format; + default_sample_rate = c->core->default_sample_spec.rate; + cards = get_cards(c, &n_cards); + sinks = get_sinks(c, &n_sinks); + fallback_sink = c->fallback_sink + ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index))) + : NULL; + sources = get_sources(c, &n_sources); + fallback_source = c->fallback_source + ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sources_by_index, + PA_UINT32_TO_PTR(c->fallback_source->index))) + : NULL; + playback_streams = get_playback_streams(c, &n_playback_streams); + record_streams = get_record_streams(c, &n_record_streams); + samples = get_samples(c, &n_samples); + modules = get_modules(c, &n_modules); + clients = get_clients(c, &n_clients); + my_client = get_my_client(c, conn); + extensions = pa_dbus_protocol_get_extensions(c->dbus_protocol, &n_extensions); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &server_name); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VERSION].property_name, DBUS_TYPE_STRING, &version); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_LOCAL].property_name, DBUS_TYPE_BOOLEAN, &is_local); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_USERNAME].property_name, DBUS_TYPE_STRING, &username); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HOSTNAME].property_name, DBUS_TYPE_STRING, &hostname); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_CHANNELS].property_name, DBUS_TYPE_UINT32, default_channels, n_default_channels); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &default_sample_format); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &default_sample_rate); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CARDS].property_name, DBUS_TYPE_OBJECT_PATH, cards, n_cards); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, sinks, n_sinks); + + if (fallback_sink) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_FALLBACK_SINK].property_name, DBUS_TYPE_OBJECT_PATH, &fallback_sink); + + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SOURCES].property_name, DBUS_TYPE_OBJECT_PATH, sources, n_sources); + + if (fallback_source) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_FALLBACK_SOURCE].property_name, DBUS_TYPE_OBJECT_PATH, &fallback_source); + + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PLAYBACK_STREAMS].property_name, DBUS_TYPE_OBJECT_PATH, playback_streams, n_playback_streams); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RECORD_STREAMS].property_name, DBUS_TYPE_OBJECT_PATH, record_streams, n_record_streams); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLES].property_name, DBUS_TYPE_OBJECT_PATH, samples, n_samples); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MODULES].property_name, DBUS_TYPE_OBJECT_PATH, modules, n_modules); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENTS].property_name, DBUS_TYPE_OBJECT_PATH, clients, n_clients); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MY_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &my_client); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_EXTENSIONS].property_name, DBUS_TYPE_STRING, extensions, n_extensions); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(username); + pa_xfree(hostname); + pa_xfree(default_channels); + pa_xfree(cards); + pa_xfree(sinks); + pa_xfree(sources); + pa_xfree(playback_streams); + pa_xfree(record_streams); + pa_xfree(samples); + pa_xfree(modules); + pa_xfree(clients); + pa_xfree(extensions); +} + +static void handle_get_card_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + char *card_name; + pa_card *card; + pa_dbusiface_card *dbus_card; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &card_name, DBUS_TYPE_INVALID)); + + if (!(card = pa_namereg_get(c->core, card_name, PA_NAMEREG_CARD))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such card."); + return; + } + + pa_assert_se((dbus_card = pa_hashmap_get(c->cards, PA_UINT32_TO_PTR(card->index)))); + + object_path = pa_dbusiface_card_get_path(dbus_card); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_sink_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + char *sink_name; + pa_sink *sink; + pa_dbusiface_device *dbus_sink; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &sink_name, DBUS_TYPE_INVALID)); + + if (!(sink = pa_namereg_get(c->core, sink_name, PA_NAMEREG_SINK))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", sink_name); + return; + } + + pa_assert_se((dbus_sink = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(sink->index)))); + + object_path = pa_dbusiface_device_get_path(dbus_sink); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_source_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + char *source_name; + pa_source *source; + pa_dbusiface_device *dbus_source; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &source_name, DBUS_TYPE_INVALID)); + + if (!(source = pa_namereg_get(c->core, source_name, PA_NAMEREG_SOURCE))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", source_name); + return; + } + + pa_assert_se((dbus_source = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(source->index)))); + + object_path = pa_dbusiface_device_get_path(dbus_source); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_sample_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + char *sample_name; + pa_scache_entry *sample; + pa_dbusiface_sample *dbus_sample; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &sample_name, DBUS_TYPE_INVALID)); + + if (!(sample = pa_namereg_get(c->core, sample_name, PA_NAMEREG_SAMPLE))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such sample."); + return; + } + + pa_assert_se((dbus_sample = pa_hashmap_get(c->samples, PA_UINT32_TO_PTR(sample->index)))); + + object_path = pa_dbusiface_sample_get_path(dbus_sample); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_upload_sample(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + DBusMessageIter msg_iter; + DBusMessageIter array_iter; + const char *name; + dbus_uint32_t sample_format; + dbus_uint32_t sample_rate; + const dbus_uint32_t *channels; + int n_channels; + const dbus_uint32_t *default_volume; + int n_volume_entries; + pa_proplist *property_list; + const uint8_t *data; + int data_length; + int i; + pa_sample_spec ss; + pa_channel_map map; + pa_memchunk chunk; + uint32_t idx; + pa_dbusiface_sample *dbus_sample = NULL; + pa_scache_entry *sample = NULL; + const char *object_path; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + chunk.memblock = NULL; + + pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &name); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &sample_format); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &sample_rate); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_recurse(&msg_iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &channels, &n_channels); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_recurse(&msg_iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &default_volume, &n_volume_entries); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter))) + return; + + dbus_message_iter_recurse(&msg_iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &data, &data_length); + + if (sample_format >= PA_SAMPLE_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample format."); + goto finish; + } + + if (sample_rate <= 0 || sample_rate > PA_RATE_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid sample rate."); + goto finish; + } + + if (n_channels <= 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Empty channel map."); + goto finish; + } + + if (n_channels > (int) PA_CHANNELS_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "Too many channels: %i. The maximum is %u.", n_channels, PA_CHANNELS_MAX); + goto finish; + } + + for (i = 0; i < n_channels; ++i) { + if (channels[i] >= PA_CHANNEL_POSITION_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position."); + goto finish; + } + } + + if (n_volume_entries != 0 && n_volume_entries != n_channels) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "The channels and default_volume arguments have different number of elements (%i and %i, resp).", + n_channels, n_volume_entries); + goto finish; + } + + for (i = 0; i < n_volume_entries; ++i) { + if (default_volume[i] > PA_VOLUME_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u.", default_volume[i]); + goto finish; + } + } + + if (data_length == 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Empty data."); + goto finish; + } + + if (data_length > PA_SCACHE_ENTRY_SIZE_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "Too big sample: %i bytes. The maximum sample length is %u bytes.", + data_length, PA_SCACHE_ENTRY_SIZE_MAX); + goto finish; + } + + ss.format = sample_format; + ss.rate = sample_rate; + ss.channels = n_channels; + + pa_assert(pa_sample_spec_valid(&ss)); + + if (!pa_frame_aligned(data_length, &ss)) { + char buf[PA_SAMPLE_SPEC_SNPRINT_MAX]; + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "The sample length (%i bytes) doesn't align with the sample format and channels (%s).", + data_length, pa_sample_spec_snprint(buf, sizeof(buf), &ss)); + goto finish; + } + + map.channels = n_channels; + for (i = 0; i < n_channels; ++i) + map.map[i] = channels[i]; + + chunk.memblock = pa_memblock_new(c->core->mempool, data_length); + chunk.index = 0; + chunk.length = data_length; + + memcpy(pa_memblock_acquire(chunk.memblock), data, data_length); + pa_memblock_release(chunk.memblock); + + if (pa_scache_add_item(c->core, name, &ss, &map, &chunk, property_list, &idx) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Adding the sample failed."); + goto finish; + } + + sample = pa_idxset_get_by_index(c->core->scache, idx); + + if (n_volume_entries > 0) { + sample->volume.channels = n_channels; + for (i = 0; i < n_volume_entries; ++i) + sample->volume.values[i] = default_volume[i]; + sample->volume_is_set = TRUE; + } else { + sample->volume_is_set = FALSE; + } + + dbus_sample = pa_dbusiface_sample_new(c, sample); + pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), dbus_sample); + + object_path = pa_dbusiface_sample_get_path(dbus_sample); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); + +finish: + if (property_list) + pa_proplist_free(property_list); + + if (chunk.memblock) + pa_memblock_unref(chunk.memblock); +} + +static pa_bool_t contains_space(const char *string) { + const char *p; + + pa_assert(string); + + for (p = string; *p; ++p) { + if (isspace(*p)) + return TRUE; + } + + return FALSE; +} + +static void handle_load_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + char *name = NULL; + const char *key = NULL; + const char *value = NULL; + char *escaped_value = NULL; + pa_strbuf *arg_buffer = NULL; + char *arg_string = NULL; + pa_module *module = NULL; + pa_dbusiface_module *dbus_module = NULL; + const char *object_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (c->core->disallow_module_loading) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "The server is configured to disallow module loading."); + return; + } + + pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &name); + + arg_buffer = pa_strbuf_new(); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_recurse(&msg_iter, &dict_iter); + + while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { + if (!pa_strbuf_isempty(arg_buffer)) + pa_strbuf_putc(arg_buffer, ' '); + + dbus_message_iter_recurse(&dict_iter, &dict_entry_iter); + + dbus_message_iter_get_basic(&dict_entry_iter, &key); + + if (strlen(key) <= 0 || !pa_ascii_valid(key) || contains_space(key)) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid module argument name: %s", key); + goto finish; + } + + pa_assert_se(dbus_message_iter_next(&dict_entry_iter)); + dbus_message_iter_get_basic(&dict_entry_iter, &value); + + escaped_value = pa_escape(value, "\""); + pa_strbuf_printf(arg_buffer, "%s=\"%s\"", key, escaped_value); + pa_xfree(escaped_value); + + dbus_message_iter_next(&dict_iter); + } + + arg_string = pa_strbuf_tostring(arg_buffer); + + if (!(module = pa_module_load(c->core, name, arg_string))) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Failed to load module."); + goto finish; + } + + dbus_module = pa_dbusiface_module_new(module); + pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(module->index), dbus_module); + + object_path = pa_dbusiface_module_get_path(dbus_module); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); + +finish: + if (arg_buffer) + pa_strbuf_free(arg_buffer); + + pa_xfree(arg_string); +} + +static void handle_exit(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + if (c->core->disallow_exit) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "The server is configured to disallow exiting."); + return; + } + + pa_dbus_send_empty_reply(conn, msg); + + pa_core_exit(c->core, FALSE, 0); +} + +static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char *signal; + char **objects = NULL; + int n_objects; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &signal, + DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objects, &n_objects, + DBUS_TYPE_INVALID)); + + pa_dbus_protocol_add_signal_listener(c->dbus_protocol, conn, *signal ? signal : NULL, objects, n_objects); + + pa_dbus_send_empty_reply(conn, msg); + + dbus_free_string_array(objects); +} + +static void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_core *c = userdata; + const char *signal; + + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &signal, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_remove_signal_listener(c->dbus_protocol, conn, *signal ? signal : NULL); + + pa_dbus_send_empty_reply(conn, msg); +} + +static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_core *c = userdata; + pa_dbusiface_card *card_iface = NULL; + pa_dbusiface_device *device_iface = NULL; + pa_dbusiface_stream *stream_iface = NULL; + pa_dbusiface_sample *sample_iface = NULL; + pa_dbusiface_module *module_iface = NULL; + pa_dbusiface_client *client_iface = NULL; + DBusMessage *signal = NULL; + const char *object_path = NULL; + pa_sink *new_fallback_sink = NULL; + pa_source *new_fallback_source = NULL; + + pa_assert(c); + + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SERVER: + new_fallback_sink = pa_namereg_get_default_sink(core); + new_fallback_source = pa_namereg_get_default_source(core); + + if (c->fallback_sink != new_fallback_sink) { + if (c->fallback_sink) + pa_sink_unref(c->fallback_sink); + c->fallback_sink = new_fallback_sink ? pa_sink_ref(new_fallback_sink) : NULL; + + if (new_fallback_sink + && (device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(new_fallback_sink->index)))) { + object_path = pa_dbusiface_device_get_path(device_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + + } else if (!new_fallback_sink) { + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SINK_UNSET].name))); + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + } + + if (c->fallback_source != new_fallback_source) { + if (c->fallback_source) + pa_source_unref(c->fallback_source); + c->fallback_source = new_fallback_source ? pa_source_ref(new_fallback_source) : NULL; + + if (new_fallback_source + && (device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(new_fallback_source->index)))) { + object_path = pa_dbusiface_device_get_path(device_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + + } else if (!new_fallback_source) { + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SOURCE_UNSET].name))); + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + } + break; + + case PA_SUBSCRIPTION_EVENT_CARD: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + if (!(card_iface = pa_hashmap_get(c->cards, PA_UINT32_TO_PTR(idx)))) { + pa_card *card = NULL; + + if (!(card = pa_idxset_get_by_index(core->cards, idx))) + return; /* The card was removed immediately after creation. */ + + card_iface = pa_dbusiface_card_new(c, card); + pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(idx), card_iface); + } + + object_path = pa_dbusiface_card_get_path(card_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_CARD].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_card_get_path(card_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_CARD_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_card_free(card_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_SINK: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_sink *sink = NULL; + + if (!(sink = pa_idxset_get_by_index(core->sinks, idx))) + return; /* The sink was removed immediately after creation. */ + + if (!(device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(idx)))) { + device_iface = pa_dbusiface_device_new_sink(c, sink); + pa_hashmap_put(c->sinks_by_index, PA_UINT32_TO_PTR(idx), device_iface); + pa_hashmap_put(c->sinks_by_path, pa_dbusiface_device_get_path(device_iface), device_iface); + } + + object_path = pa_dbusiface_device_get_path(device_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_SINK].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + + if (c->fallback_sink && pa_streq(c->fallback_sink->name, sink->name)) { + /* We have got default sink change event, but at that point + * the D-Bus sink object wasn't created yet. Now that the + * object is created, let's send the fallback sink change + * signal. */ + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(device_iface = pa_hashmap_remove(c->sinks_by_index, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_device_get_path(device_iface); + pa_assert_se(pa_hashmap_remove(c->sinks_by_path, object_path)); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_SINK_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_device_free(device_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_SOURCE: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_source *source = pa_idxset_get_by_index(core->sources, idx); + + if (!(source = pa_idxset_get_by_index(core->sources, idx))) + return; /* The source was removed immediately after creation. */ + + if (!(device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(idx)))) { + device_iface = pa_dbusiface_device_new_source(c, source); + pa_hashmap_put(c->sources_by_index, PA_UINT32_TO_PTR(idx), device_iface); + pa_hashmap_put(c->sources_by_path, pa_dbusiface_device_get_path(device_iface), device_iface); + } + + object_path = pa_dbusiface_device_get_path(device_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_SOURCE].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + + if (c->fallback_source && pa_streq(c->fallback_source->name, source->name)) { + /* We have got default source change event, but at that + * point the D-Bus source object wasn't created yet. Now + * that the object is created, let's send the fallback + * source change signal. */ + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(device_iface = pa_hashmap_remove(c->sources_by_index, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_device_get_path(device_iface); + pa_assert_se(pa_hashmap_remove(c->sources_by_path, object_path)); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_SOURCE_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_device_free(device_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_sink_input *sink_input = NULL; + + if (!(sink_input = pa_idxset_get_by_index(core->sink_inputs, idx))) + return; /* The sink input was removed immediately after creation. */ + + if (!(stream_iface = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(idx)))) { + stream_iface = pa_dbusiface_stream_new_playback(c, sink_input); + pa_hashmap_put(c->playback_streams, PA_UINT32_TO_PTR(idx), stream_iface); + } + + object_path = pa_dbusiface_stream_get_path(stream_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_PLAYBACK_STREAM].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_stream_get_path(stream_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_stream_free(stream_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_source_output *source_output = NULL; + + if (!(source_output = pa_idxset_get_by_index(core->source_outputs, idx))) + return; /* The source output was removed immediately after creation. */ + + if (!(stream_iface = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(idx)))) { + stream_iface = pa_dbusiface_stream_new_record(c, source_output); + pa_hashmap_put(c->record_streams, PA_UINT32_TO_PTR(idx), stream_iface); + } + + object_path = pa_dbusiface_stream_get_path(stream_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_RECORD_STREAM].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_stream_get_path(stream_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_RECORD_STREAM_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_stream_free(stream_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_scache_entry *sample = NULL; + + if (!(sample = pa_idxset_get_by_index(core->scache, idx))) + return; /* The sample was removed immediately after creation. */ + + if (!(sample_iface = pa_hashmap_get(c->samples, PA_UINT32_TO_PTR(idx)))) { + sample_iface = pa_dbusiface_sample_new(c, sample); + pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), sample_iface); + } + + object_path = pa_dbusiface_sample_get_path(sample_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_SAMPLE].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_sample_get_path(sample_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_SAMPLE_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_sample_free(sample_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_MODULE: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_module *module = NULL; + + if (!(module = pa_idxset_get_by_index(core->modules, idx))) + return; /* The module was removed immediately after creation. */ + + if (!(module_iface = pa_hashmap_get(c->modules, PA_UINT32_TO_PTR(idx)))) { + module_iface = pa_dbusiface_module_new(module); + pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(idx), module_iface); + } + + object_path = pa_dbusiface_module_get_path(module_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_MODULE].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_module_get_path(module_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_MODULE_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_module_free(module_iface); + } + break; + + case PA_SUBSCRIPTION_EVENT_CLIENT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + pa_client *client = NULL; + + if (!(client = pa_idxset_get_by_index(core->clients, idx))) + return; /* The client was removed immediately after creation. */ + + if (!(client_iface = pa_hashmap_get(c->clients, PA_UINT32_TO_PTR(idx)))) { + client_iface = pa_dbusiface_client_new(c, client); + pa_hashmap_put(c->clients, PA_UINT32_TO_PTR(idx), client_iface); + } + + object_path = pa_dbusiface_client_get_path(client_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_CLIENT].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + if (!(client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(idx)))) + return; + + object_path = pa_dbusiface_client_get_path(client_iface); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_CLIENT_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_client_free(client_iface); + } + break; + } + + if (signal) { + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + } +} + +static pa_hook_result_t extension_registered_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + const char *ext_name = call_data; + DBusMessage *signal = NULL; + + pa_assert(c); + pa_assert(ext_name); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_EXTENSION].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + + return PA_HOOK_OK; +} + +static pa_hook_result_t extension_unregistered_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + const char *ext_name = call_data; + DBusMessage *signal = NULL; + + pa_assert(c); + pa_assert(ext_name); + + pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_EXTENSION_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal); + dbus_message_unref(signal); + + return PA_HOOK_OK; +} + +pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) { + pa_dbusiface_core *c; + pa_card *card; + pa_sink *sink; + pa_source *source; + pa_dbusiface_device *device; + pa_sink_input *sink_input; + pa_source_output *source_output; + pa_scache_entry *sample; + pa_module *module; + pa_client *client; + uint32_t idx; + + pa_assert(core); + + c = pa_xnew(pa_dbusiface_core, 1); + c->core = pa_core_ref(core); + c->subscription = pa_subscription_new(core, PA_SUBSCRIPTION_MASK_ALL, subscription_cb, c); + c->dbus_protocol = pa_dbus_protocol_get(core); + c->cards = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->sinks_by_index = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->sinks_by_path = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + c->sources_by_index = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->sources_by_path = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + c->playback_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->record_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->samples = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->modules = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->clients = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + c->fallback_sink = pa_namereg_get_default_sink(core); + c->fallback_source = pa_namereg_get_default_source(core); + c->extension_registered_slot = pa_dbus_protocol_hook_connect(c->dbus_protocol, + PA_DBUS_PROTOCOL_HOOK_EXTENSION_REGISTERED, + PA_HOOK_NORMAL, + extension_registered_cb, + c); + c->extension_unregistered_slot = pa_dbus_protocol_hook_connect(c->dbus_protocol, + PA_DBUS_PROTOCOL_HOOK_EXTENSION_UNREGISTERED, + PA_HOOK_NORMAL, + extension_unregistered_cb, + c); + c->memstats = pa_dbusiface_memstats_new(c, core); + + if (c->fallback_sink) + pa_sink_ref(c->fallback_sink); + if (c->fallback_source) + pa_source_ref(c->fallback_source); + + PA_IDXSET_FOREACH(card, core->cards, idx) + pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(idx), pa_dbusiface_card_new(c, card)); + + PA_IDXSET_FOREACH(sink, core->sinks, idx) { + device = pa_dbusiface_device_new_sink(c, sink); + pa_hashmap_put(c->sinks_by_index, PA_UINT32_TO_PTR(idx), device); + pa_hashmap_put(c->sinks_by_path, pa_dbusiface_device_get_path(device), device); + } + + PA_IDXSET_FOREACH(source, core->sources, idx) { + device = pa_dbusiface_device_new_source(c, source); + pa_hashmap_put(c->sources_by_index, PA_UINT32_TO_PTR(idx), device); + pa_hashmap_put(c->sources_by_path, pa_dbusiface_device_get_path(device), device); + } + + PA_IDXSET_FOREACH(sink_input, core->sink_inputs, idx) + pa_hashmap_put(c->playback_streams, PA_UINT32_TO_PTR(idx), pa_dbusiface_stream_new_playback(c, sink_input)); + + PA_IDXSET_FOREACH(source_output, core->source_outputs, idx) + pa_hashmap_put(c->record_streams, PA_UINT32_TO_PTR(idx), pa_dbusiface_stream_new_record(c, source_output)); + + PA_IDXSET_FOREACH(sample, core->scache, idx) + pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), pa_dbusiface_sample_new(c, sample)); + + PA_IDXSET_FOREACH(module, core->modules, idx) + pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(idx), pa_dbusiface_module_new(module)); + + PA_IDXSET_FOREACH(client, core->clients, idx) + pa_hashmap_put(c->clients, PA_UINT32_TO_PTR(idx), pa_dbusiface_client_new(c, client)); + + pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, PA_DBUS_CORE_OBJECT_PATH, &core_interface_info, c) >= 0); + + return c; +} + +static void free_card_cb(void *p, void *userdata) { + pa_dbusiface_card *c = p; + + pa_assert(c); + + pa_dbusiface_card_free(c); +} + +static void free_device_cb(void *p, void *userdata) { + pa_dbusiface_device *d = p; + + pa_assert(d); + + pa_dbusiface_device_free(d); +} + +static void free_stream_cb(void *p, void *userdata) { + pa_dbusiface_stream *s = p; + + pa_assert(s); + + pa_dbusiface_stream_free(s); +} + +static void free_sample_cb(void *p, void *userdata) { + pa_dbusiface_sample *s = p; + + pa_assert(s); + + pa_dbusiface_sample_free(s); +} + +static void free_module_cb(void *p, void *userdata) { + pa_dbusiface_module *m = p; + + pa_assert(m); + + pa_dbusiface_module_free(m); +} + +static void free_client_cb(void *p, void *userdata) { + pa_dbusiface_client *c = p; + + pa_assert(c); + + pa_dbusiface_client_free(c); +} + +void pa_dbusiface_core_free(pa_dbusiface_core *c) { + pa_assert(c); + + pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, PA_DBUS_CORE_OBJECT_PATH, core_interface_info.name) >= 0); + + pa_subscription_free(c->subscription); + pa_hashmap_free(c->cards, free_card_cb, NULL); + pa_hashmap_free(c->sinks_by_index, free_device_cb, NULL); + pa_hashmap_free(c->sinks_by_path, NULL, NULL); + pa_hashmap_free(c->sources_by_index, free_device_cb, NULL); + pa_hashmap_free(c->sources_by_path, NULL, NULL); + pa_hashmap_free(c->playback_streams, free_stream_cb, NULL); + pa_hashmap_free(c->record_streams, free_stream_cb, NULL); + pa_hashmap_free(c->samples, free_sample_cb, NULL); + pa_hashmap_free(c->modules, free_module_cb, NULL); + pa_hashmap_free(c->clients, free_client_cb, NULL); + pa_hook_slot_free(c->extension_registered_slot); + pa_hook_slot_free(c->extension_unregistered_slot); + pa_dbusiface_memstats_free(c->memstats); + + if (c->fallback_sink) + pa_sink_unref(c->fallback_sink); + if (c->fallback_source) + pa_source_unref(c->fallback_source); + + pa_dbus_protocol_unref(c->dbus_protocol); + pa_core_unref(c->core); + + pa_xfree(c); +} + +const char *pa_dbusiface_core_get_card_path(pa_dbusiface_core *c, const pa_card *card) { + pa_assert(c); + pa_assert(card); + + return pa_dbusiface_card_get_path(pa_hashmap_get(c->cards, PA_UINT32_TO_PTR(card->index))); +} + +const char *pa_dbusiface_core_get_sink_path(pa_dbusiface_core *c, const pa_sink *sink) { + pa_assert(c); + pa_assert(sink); + + return pa_dbusiface_device_get_path(pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(sink->index))); +} + +const char *pa_dbusiface_core_get_source_path(pa_dbusiface_core *c, const pa_source *source) { + pa_assert(c); + pa_assert(source); + + return pa_dbusiface_device_get_path(pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(source->index))); +} + +const char *pa_dbusiface_core_get_playback_stream_path(pa_dbusiface_core *c, const pa_sink_input *sink_input) { + pa_assert(c); + pa_assert(sink_input); + + return pa_dbusiface_stream_get_path(pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(sink_input->index))); +} + +const char *pa_dbusiface_core_get_record_stream_path(pa_dbusiface_core *c, const pa_source_output *source_output) { + pa_assert(c); + pa_assert(source_output); + + return pa_dbusiface_stream_get_path(pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(source_output->index))); +} + +const char *pa_dbusiface_core_get_module_path(pa_dbusiface_core *c, const pa_module *module) { + pa_assert(c); + pa_assert(module); + + return pa_dbusiface_module_get_path(pa_hashmap_get(c->modules, PA_UINT32_TO_PTR(module->index))); +} + +const char *pa_dbusiface_core_get_client_path(pa_dbusiface_core *c, const pa_client *client) { + pa_assert(c); + pa_assert(client); + + return pa_dbusiface_client_get_path(pa_hashmap_get(c->clients, PA_UINT32_TO_PTR(client->index))); +} + +pa_sink *pa_dbusiface_core_get_sink(pa_dbusiface_core *c, const char *object_path) { + pa_dbusiface_device *device = NULL; + + pa_assert(c); + pa_assert(object_path); + + device = pa_hashmap_get(c->sinks_by_path, object_path); + + if (device) + return pa_dbusiface_device_get_sink(device); + else + return NULL; +} + +pa_source *pa_dbusiface_core_get_source(pa_dbusiface_core *c, const char *object_path) { + pa_dbusiface_device *device = NULL; + + pa_assert(c); + pa_assert(object_path); + + device = pa_hashmap_get(c->sources_by_path, object_path); + + if (device) + return pa_dbusiface_device_get_source(device); + else + return NULL; +} diff --git a/src/modules/dbus/iface-core.h b/src/modules/dbus/iface-core.h new file mode 100644 index 00000000..900b6d1c --- /dev/null +++ b/src/modules/dbus/iface-core.h @@ -0,0 +1,52 @@ +#ifndef foodbusifacecorehfoo +#define foodbusifacecorehfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Core interface + * documentation. + */ + +#include <pulsecore/core.h> + +typedef struct pa_dbusiface_core pa_dbusiface_core; + +pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core); +void pa_dbusiface_core_free(pa_dbusiface_core *c); + +const char *pa_dbusiface_core_get_card_path(pa_dbusiface_core *c, const pa_card *card); +const char *pa_dbusiface_core_get_sink_path(pa_dbusiface_core *c, const pa_sink *sink); +const char *pa_dbusiface_core_get_source_path(pa_dbusiface_core *c, const pa_source *source); +const char *pa_dbusiface_core_get_playback_stream_path(pa_dbusiface_core *c, const pa_sink_input *sink_input); +const char *pa_dbusiface_core_get_record_stream_path(pa_dbusiface_core *c, const pa_source_output *source_output); +const char *pa_dbusiface_core_get_module_path(pa_dbusiface_core *c, const pa_module *module); +const char *pa_dbusiface_core_get_client_path(pa_dbusiface_core *c, const pa_client *client); + +/* Returns NULL if there's no sink with the given path. */ +pa_sink *pa_dbusiface_core_get_sink(pa_dbusiface_core *c, const char *object_path); + +/* Returns NULL if there's no source with the given path. */ +pa_source *pa_dbusiface_core_get_source(pa_dbusiface_core *c, const char *object_path); + +#endif diff --git a/src/modules/dbus/iface-device-port.c b/src/modules/dbus/iface-device-port.c new file mode 100644 index 00000000..d403b6a2 --- /dev/null +++ b/src/modules/dbus/iface-device-port.c @@ -0,0 +1,190 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> + +#include "iface-device-port.h" + +#define OBJECT_NAME "port" + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_description(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_priority(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +struct pa_dbusiface_device_port { + uint32_t index; + pa_device_port *port; + char *path; + pa_dbus_protocol *dbus_protocol; +}; + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_DESCRIPTION, + PROPERTY_HANDLER_PRIORITY, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_DESCRIPTION] = { .property_name = "Description", .type = "s", .get_cb = handle_get_description, .set_cb = NULL }, + [PROPERTY_HANDLER_PRIORITY] = { .property_name = "Priority", .type = "u", .get_cb = handle_get_priority, .set_cb = NULL }, +}; + +static pa_dbus_interface_info port_interface_info = { + .name = PA_DBUSIFACE_DEVICE_PORT_INTERFACE, + .method_handlers = NULL, + .n_method_handlers = 0, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = NULL, + .n_signals = 0 +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device_port *p = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &p->index); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device_port *p = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &p->port->name); +} + +static void handle_get_description(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device_port *p = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &p->port->description); +} + +static void handle_get_priority(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device_port *p = userdata; + dbus_uint32_t priority = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + priority = p->port->priority; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &priority); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device_port *p = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t priority = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(p); + + priority = p->port->priority; + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &p->index); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &p->port->name); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DESCRIPTION].property_name, DBUS_TYPE_STRING, &p->port->description); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PRIORITY].property_name, DBUS_TYPE_UINT32, &priority); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} + +pa_dbusiface_device_port *pa_dbusiface_device_port_new( + pa_dbusiface_device *device, + pa_core *core, + pa_device_port *port, + uint32_t idx) { + pa_dbusiface_device_port *p = NULL; + + pa_assert(device); + pa_assert(core); + pa_assert(port); + + p = pa_xnew(pa_dbusiface_device_port, 1); + p->index = idx; + p->port = port; + p->path = pa_sprintf_malloc("%s/%s%u", pa_dbusiface_device_get_path(device), OBJECT_NAME, idx); + p->dbus_protocol = pa_dbus_protocol_get(core); + + pa_assert_se(pa_dbus_protocol_add_interface(p->dbus_protocol, p->path, &port_interface_info, p) >= 0); + + return p; +} + +void pa_dbusiface_device_port_free(pa_dbusiface_device_port *p) { + pa_assert(p); + + pa_assert_se(pa_dbus_protocol_remove_interface(p->dbus_protocol, p->path, port_interface_info.name) >= 0); + + pa_dbus_protocol_unref(p->dbus_protocol); + + pa_xfree(p->path); + pa_xfree(p); +} + +const char *pa_dbusiface_device_port_get_path(pa_dbusiface_device_port *p) { + pa_assert(p); + + return p->path; +} + +const char *pa_dbusiface_device_port_get_name(pa_dbusiface_device_port *p) { + pa_assert(p); + + return p->port->name; +} diff --git a/src/modules/dbus/iface-device-port.h b/src/modules/dbus/iface-device-port.h new file mode 100644 index 00000000..0461e2ff --- /dev/null +++ b/src/modules/dbus/iface-device-port.h @@ -0,0 +1,50 @@ +#ifndef foodbusifacedeviceporthfoo +#define foodbusifacedeviceporthfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.DevicePort. + * + * See http://pulseaudio.org/wiki/DBusInterface for the DevicePort interface + * documentation. + */ + +#include <pulsecore/protocol-dbus.h> +#include <pulsecore/sink.h> + +#include "iface-device.h" + +#define PA_DBUSIFACE_DEVICE_PORT_INTERFACE PA_DBUS_CORE_INTERFACE ".DevicePort" + +typedef struct pa_dbusiface_device_port pa_dbusiface_device_port; + +pa_dbusiface_device_port *pa_dbusiface_device_port_new( + pa_dbusiface_device *device, + pa_core *core, + pa_device_port *port, + uint32_t idx); +void pa_dbusiface_device_port_free(pa_dbusiface_device_port *p); + +const char *pa_dbusiface_device_port_get_path(pa_dbusiface_device_port *p); +const char *pa_dbusiface_device_port_get_name(pa_dbusiface_device_port *p); + +#endif diff --git a/src/modules/dbus/iface-device.c b/src/modules/dbus/iface-device.c new file mode 100644 index 00000000..3a747a44 --- /dev/null +++ b/src/modules/dbus/iface-device.c @@ -0,0 +1,1316 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-device-port.h" + +#include "iface-device.h" + +#define SINK_OBJECT_NAME "sink" +#define SOURCE_OBJECT_NAME "source" + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_ports(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +enum device_type { + DEVICE_TYPE_SINK, + DEVICE_TYPE_SOURCE +}; + +struct pa_dbusiface_device { + pa_dbusiface_core *core; + + union { + pa_sink *sink; + pa_source *source; + }; + enum device_type type; + char *path; + pa_cvolume volume; + dbus_bool_t mute; + union { + pa_sink_state_t sink_state; + pa_source_state_t source_state; + }; + pa_hashmap *ports; + uint32_t next_port_index; + pa_device_port *active_port; + pa_proplist *proplist; + + pa_dbus_protocol *dbus_protocol; + pa_subscription *subscription; +}; + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_DRIVER, + PROPERTY_HANDLER_OWNER_MODULE, + PROPERTY_HANDLER_CARD, + PROPERTY_HANDLER_SAMPLE_FORMAT, + PROPERTY_HANDLER_SAMPLE_RATE, + PROPERTY_HANDLER_CHANNELS, + PROPERTY_HANDLER_VOLUME, + PROPERTY_HANDLER_HAS_FLAT_VOLUME, + PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME, + PROPERTY_HANDLER_BASE_VOLUME, + PROPERTY_HANDLER_VOLUME_STEPS, + PROPERTY_HANDLER_MUTE, + PROPERTY_HANDLER_HAS_HARDWARE_VOLUME, + PROPERTY_HANDLER_HAS_HARDWARE_MUTE, + PROPERTY_HANDLER_CONFIGURED_LATENCY, + PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY, + PROPERTY_HANDLER_LATENCY, + PROPERTY_HANDLER_IS_HARDWARE_DEVICE, + PROPERTY_HANDLER_IS_NETWORK_DEVICE, + PROPERTY_HANDLER_STATE, + PROPERTY_HANDLER_PORTS, + PROPERTY_HANDLER_ACTIVE_PORT, + PROPERTY_HANDLER_PROPERTY_LIST, + PROPERTY_HANDLER_MAX +}; + +enum sink_property_handler_index { + SINK_PROPERTY_HANDLER_MONITOR_SOURCE, + SINK_PROPERTY_HANDLER_MAX +}; + +enum source_property_handler_index { + SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK, + SOURCE_PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, + [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, + [PROPERTY_HANDLER_CARD] = { .property_name = "Card", .type = "o", .get_cb = handle_get_card, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, + [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, + [PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "au", .get_cb = handle_get_volume, .set_cb = handle_set_volume }, + [PROPERTY_HANDLER_HAS_FLAT_VOLUME] = { .property_name = "HasFlatVolume", .type = "b", .get_cb = handle_get_has_flat_volume, .set_cb = NULL }, + [PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME] = { .property_name = "HasConvertibleToDecibelVolume", .type = "b", .get_cb = handle_get_has_convertible_to_decibel_volume, .set_cb = NULL }, + [PROPERTY_HANDLER_BASE_VOLUME] = { .property_name = "BaseVolume", .type = "u", .get_cb = handle_get_base_volume, .set_cb = NULL }, + [PROPERTY_HANDLER_VOLUME_STEPS] = { .property_name = "VolumeSteps", .type = "u", .get_cb = handle_get_volume_steps, .set_cb = NULL }, + [PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_get_mute, .set_cb = handle_set_mute }, + [PROPERTY_HANDLER_HAS_HARDWARE_VOLUME] = { .property_name = "HasHardwareVolume", .type = "b", .get_cb = handle_get_has_hardware_volume, .set_cb = NULL }, + [PROPERTY_HANDLER_HAS_HARDWARE_MUTE] = { .property_name = "HasHardwareMute", .type = "b", .get_cb = handle_get_has_hardware_mute, .set_cb = NULL }, + [PROPERTY_HANDLER_CONFIGURED_LATENCY] = { .property_name = "ConfiguredLatency", .type = "t", .get_cb = handle_get_configured_latency, .set_cb = NULL }, + [PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY] = { .property_name = "HasDynamicLatency", .type = "b", .get_cb = handle_get_has_dynamic_latency, .set_cb = NULL }, + [PROPERTY_HANDLER_LATENCY] = { .property_name = "Latency", .type = "t", .get_cb = handle_get_latency, .set_cb = NULL }, + [PROPERTY_HANDLER_IS_HARDWARE_DEVICE] = { .property_name = "IsHardwareDevice", .type = "b", .get_cb = handle_get_is_hardware_device, .set_cb = NULL }, + [PROPERTY_HANDLER_IS_NETWORK_DEVICE] = { .property_name = "IsNetworkDevice", .type = "b", .get_cb = handle_get_is_network_device, .set_cb = NULL }, + [PROPERTY_HANDLER_STATE] = { .property_name = "State", .type = "u", .get_cb = handle_get_state, .set_cb = NULL }, + [PROPERTY_HANDLER_PORTS] = { .property_name = "Ports", .type = "ao", .get_cb = handle_get_ports, .set_cb = NULL }, + [PROPERTY_HANDLER_ACTIVE_PORT] = { .property_name = "ActivePort", .type = "o", .get_cb = handle_get_active_port, .set_cb = handle_set_active_port }, + [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } +}; + +static pa_dbus_property_handler sink_property_handlers[SINK_PROPERTY_HANDLER_MAX] = { + [SINK_PROPERTY_HANDLER_MONITOR_SOURCE] = { .property_name = "MonitorSource", .type = "o", .get_cb = handle_sink_get_monitor_source, .set_cb = NULL } +}; + +static pa_dbus_property_handler source_property_handlers[SOURCE_PROPERTY_HANDLER_MAX] = { + [SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK] = { .property_name = "MonitorOfSink", .type = "o", .get_cb = handle_source_get_monitor_of_sink, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_SUSPEND, + METHOD_HANDLER_GET_PORT_BY_NAME, + METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info suspend_args[] = { { "suspend", "b", "in" } }; +static pa_dbus_arg_info get_port_by_name_args[] = { { "name", "s", "in" }, { "port", "o", "out" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_SUSPEND] = { + .method_name = "Suspend", + .arguments = suspend_args, + .n_arguments = sizeof(suspend_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_suspend }, + [METHOD_HANDLER_GET_PORT_BY_NAME] = { + .method_name = "GetPortByName", + .arguments = get_port_by_name_args, + .n_arguments = sizeof(get_port_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_port_by_name } +}; + +enum signal_index { + SIGNAL_VOLUME_UPDATED, + SIGNAL_MUTE_UPDATED, + SIGNAL_STATE_UPDATED, + SIGNAL_ACTIVE_PORT_UPDATED, + SIGNAL_PROPERTY_LIST_UPDATED, + SIGNAL_MAX +}; + +static pa_dbus_arg_info volume_updated_args[] = { { "volume", "au", NULL } }; +static pa_dbus_arg_info mute_updated_args[] = { { "muted", "b", NULL } }; +static pa_dbus_arg_info state_updated_args[] = { { "state", "u", NULL } }; +static pa_dbus_arg_info active_port_updated_args[] = { { "port", "o", NULL } }; +static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = volume_updated_args, .n_arguments = 1 }, + [SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = mute_updated_args, .n_arguments = 1 }, + [SIGNAL_STATE_UPDATED] = { .name = "StateUpdated", .arguments = state_updated_args, .n_arguments = 1 }, + [SIGNAL_ACTIVE_PORT_UPDATED] = { .name = "ActivePortUpdated", .arguments = active_port_updated_args, .n_arguments = 1 }, + [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info device_interface_info = { + .name = PA_DBUSIFACE_DEVICE_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static pa_dbus_interface_info sink_interface_info = { + .name = PA_DBUSIFACE_SINK_INTERFACE, + .method_handlers = NULL, + .n_method_handlers = 0, + .property_handlers = sink_property_handlers, + .n_property_handlers = SINK_PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_sink_get_all, + .signals = NULL, + .n_signals = 0 +}; + +static pa_dbus_interface_info source_interface_info = { + .name = PA_DBUSIFACE_SOURCE_INTERFACE, + .method_handlers = NULL, + .n_method_handlers = 0, + .property_handlers = source_property_handlers, + .n_property_handlers = SOURCE_PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_source_get_all, + .signals = NULL, + .n_signals = 0 +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t idx = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + idx = (d->type == DEVICE_TYPE_SINK) ? d->sink->index : d->source->index; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *name = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + name = (d->type == DEVICE_TYPE_SINK) ? d->sink->name : d->source->name; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &name); +} + +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *driver = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + driver = (d->type == DEVICE_TYPE_SINK) ? d->sink->driver : d->source->driver; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver); +} + +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + pa_module *owner_module = NULL; + const char *object_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + owner_module = (d->type == DEVICE_TYPE_SINK) ? d->sink->module : d->source->module; + + if (!owner_module) { + if (d->type == DEVICE_TYPE_SINK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sink %s doesn't have an owner module.", d->sink->name); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Source %s doesn't have an owner module.", d->source->name); + return; + } + + object_path = pa_dbusiface_core_get_module_path(d->core, owner_module); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + pa_card *card = NULL; + const char *object_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + card = (d->type == DEVICE_TYPE_SINK) ? d->sink->card : d->source->card; + + if (!card) { + if (d->type == DEVICE_TYPE_SINK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sink %s doesn't belong to any card.", d->sink->name); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Source %s doesn't belong to any card.", d->source->name); + return; + } + + object_path = pa_dbusiface_core_get_card_path(d->core, card); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t sample_format = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + sample_format = (d->type == DEVICE_TYPE_SINK) ? d->sink->sample_spec.format : d->source->sample_spec.format; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format); +} + +static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t sample_rate = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + sample_rate = (d->type == DEVICE_TYPE_SINK) ? d->sink->sample_spec.rate : d->source->sample_spec.rate; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_rate); +} + +static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + pa_channel_map *channel_map = NULL; + dbus_uint32_t channels[PA_CHANNELS_MAX]; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + channel_map = (d->type == DEVICE_TYPE_SINK) ? &d->sink->channel_map : &d->source->channel_map; + + for (i = 0; i < channel_map->channels; ++i) + channels[i] = channel_map->map[i]; + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, channel_map->channels); +} + +static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t volume[PA_CHANNELS_MAX]; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + for (i = 0; i < d->volume.channels; ++i) + volume[i] = d->volume.values[i]; + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, d->volume.channels); +} + +static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_device *d = userdata; + DBusMessageIter array_iter; + int device_channels = 0; + dbus_uint32_t *volume = NULL; + int n_volume_entries = 0; + pa_cvolume new_vol; + int i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(d); + + pa_cvolume_init(&new_vol); + + device_channels = (d->type == DEVICE_TYPE_SINK) ? d->sink->channel_map.channels : d->source->channel_map.channels; + + new_vol.channels = device_channels; + + dbus_message_iter_recurse(iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries); + + if (n_volume_entries != device_channels) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "Expected %u volume entries, got %i.", device_channels, n_volume_entries); + return; + } + + for (i = 0; i < n_volume_entries; ++i) { + if (volume[i] > PA_VOLUME_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]); + return; + } + new_vol.values[i] = volume[i]; + } + + if (d->type == DEVICE_TYPE_SINK) + pa_sink_set_volume(d->sink, &new_vol, TRUE, TRUE); + else + pa_source_set_volume(d->source, &new_vol, TRUE); + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t has_flat_volume = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + has_flat_volume = (d->type == DEVICE_TYPE_SINK) ? (d->sink->flags & PA_SINK_FLAT_VOLUME) : FALSE; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_flat_volume); +} + +static void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t has_convertible_to_decibel_volume = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + has_convertible_to_decibel_volume = (d->type == DEVICE_TYPE_SINK) + ? (d->sink->flags & PA_SINK_DECIBEL_VOLUME) + : (d->source->flags & PA_SOURCE_DECIBEL_VOLUME); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume); +} + +static void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t base_volume; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + base_volume = (d->type == DEVICE_TYPE_SINK) ? d->sink->base_volume : d->source->base_volume; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &base_volume); +} + +static void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t volume_steps; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + volume_steps = (d->type == DEVICE_TYPE_SINK) ? d->sink->n_volume_steps : d->source->n_volume_steps; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &volume_steps); +} + +static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &d->mute); +} + +static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t mute = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(d); + + dbus_message_iter_get_basic(iter, &mute); + + if (d->type == DEVICE_TYPE_SINK) + pa_sink_set_mute(d->sink, mute, TRUE); + else + pa_source_set_mute(d->source, mute, TRUE); + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t has_hardware_volume = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + has_hardware_volume = (d->type == DEVICE_TYPE_SINK) + ? (d->sink->flags & PA_SINK_HW_VOLUME_CTRL) + : (d->source->flags & PA_SOURCE_HW_VOLUME_CTRL); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_volume); +} + +static void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t has_hardware_mute = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + has_hardware_mute = (d->type == DEVICE_TYPE_SINK) + ? (d->sink->flags & PA_SINK_HW_MUTE_CTRL) + : (d->source->flags & PA_SOURCE_HW_MUTE_CTRL); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_mute); +} + +static void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint64_t configured_latency = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + configured_latency = (d->type == DEVICE_TYPE_SINK) + ? pa_sink_get_requested_latency(d->sink) + : pa_source_get_requested_latency(d->source); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &configured_latency); +} + +static void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t has_dynamic_latency = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + has_dynamic_latency = (d->type == DEVICE_TYPE_SINK) + ? (d->sink->flags & PA_SINK_DYNAMIC_LATENCY) + : (d->source->flags & PA_SOURCE_DYNAMIC_LATENCY); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_dynamic_latency); +} + +static void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint64_t latency = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + if (d->type == DEVICE_TYPE_SINK && !(d->sink->flags & PA_SINK_LATENCY)) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sink %s doesn't support latency querying.", d->sink->name); + else if (d->type == DEVICE_TYPE_SOURCE && !(d->source->flags & PA_SOURCE_LATENCY)) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Source %s doesn't support latency querying.", d->source->name); + return; + + latency = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_latency(d->sink) : pa_source_get_latency(d->source); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &latency); +} + +static void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t is_hardware_device = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + is_hardware_device = (d->type == DEVICE_TYPE_SINK) + ? (d->sink->flags & PA_SINK_HARDWARE) + : (d->source->flags & PA_SOURCE_HARDWARE); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_hardware_device); +} + +static void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t is_network_device = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + is_network_device = (d->type == DEVICE_TYPE_SINK) + ? (d->sink->flags & PA_SINK_NETWORK) + : (d->source->flags & PA_SOURCE_NETWORK); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_network_device); +} + +static void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_uint32_t state; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &state); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_ports(pa_dbusiface_device *d, unsigned *n) { + const char **ports; + unsigned i = 0; + void *state = NULL; + pa_dbusiface_device_port *port = NULL; + + pa_assert(d); + pa_assert(n); + + *n = pa_hashmap_size(d->ports); + + if (*n == 0) + return NULL; + + ports = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(port, d->ports, state) + ports[i++] = pa_dbusiface_device_port_get_path(port); + + return ports; +} + +static void handle_get_ports(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char **ports = NULL; + unsigned n_ports = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + ports = get_ports(d, &n_ports); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, ports, n_ports); + + pa_xfree(ports); +} + +static void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *active_port; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + if (!d->active_port) { + pa_assert(pa_hashmap_isempty(d->ports)); + + if (d->type == DEVICE_TYPE_SINK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "The sink %s has no ports, and therefore there's no active port either.", d->sink->name); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "The source %s has no ports, and therefore there's no active port either.", d->source->name); + return; + } + + active_port = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &active_port); +} + +static void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *new_active_path; + pa_dbusiface_device_port *new_active; + int r; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(d); + + if (!d->active_port) { + pa_assert(pa_hashmap_isempty(d->ports)); + + if (d->type == DEVICE_TYPE_SINK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "The sink %s has no ports, and therefore there's no active port either.", d->sink->name); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "The source %s has no ports, and therefore there's no active port either.", d->source->name); + return; + } + + dbus_message_iter_get_basic(iter, &new_active_path); + + if (!(new_active = pa_hashmap_get(d->ports, new_active_path))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such port: %s", new_active_path); + return; + } + + if (d->type == DEVICE_TYPE_SINK) { + if ((r = pa_sink_set_port(d->sink, pa_dbusiface_device_port_get_name(new_active), TRUE)) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, + "Internal error in PulseAudio: pa_sink_set_port() failed with error code %i.", r); + return; + } + } else { + if ((r = pa_source_set_port(d->source, pa_dbusiface_device_port_get_name(new_active), TRUE)) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, + "Internal error in PulseAudio: pa_source_set_port() failed with error code %i.", r); + return; + } + } + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + pa_dbus_send_proplist_variant_reply(conn, msg, d->proplist); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t idx = 0; + const char *name = NULL; + const char *driver = NULL; + pa_module *owner_module = NULL; + const char *owner_module_path = NULL; + pa_card *card = NULL; + const char *card_path = NULL; + dbus_uint32_t sample_format = 0; + dbus_uint32_t sample_rate = 0; + pa_channel_map *channel_map = NULL; + dbus_uint32_t channels[PA_CHANNELS_MAX]; + dbus_uint32_t volume[PA_CHANNELS_MAX]; + dbus_bool_t has_flat_volume = FALSE; + dbus_bool_t has_convertible_to_decibel_volume = FALSE; + dbus_uint32_t base_volume = 0; + dbus_uint32_t volume_steps = 0; + dbus_bool_t has_hardware_volume = FALSE; + dbus_bool_t has_hardware_mute = FALSE; + dbus_uint64_t configured_latency = 0; + dbus_bool_t has_dynamic_latency = FALSE; + dbus_uint64_t latency = 0; + dbus_bool_t is_hardware_device = FALSE; + dbus_bool_t is_network_device = FALSE; + dbus_uint32_t state = 0; + const char **ports = NULL; + unsigned n_ports = 0; + const char *active_port = NULL; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + if (d->type == DEVICE_TYPE_SINK) { + idx = d->sink->index; + name = d->sink->name; + driver = d->sink->driver; + owner_module = d->sink->module; + card = d->sink->card; + sample_format = d->sink->sample_spec.format; + sample_rate = d->sink->sample_spec.rate; + channel_map = &d->sink->channel_map; + has_flat_volume = d->sink->flags & PA_SINK_FLAT_VOLUME; + has_convertible_to_decibel_volume = d->sink->flags & PA_SINK_DECIBEL_VOLUME; + base_volume = d->sink->base_volume; + volume_steps = d->sink->n_volume_steps; + has_hardware_volume = d->sink->flags & PA_SINK_HW_VOLUME_CTRL; + has_hardware_mute = d->sink->flags & PA_SINK_HW_MUTE_CTRL; + configured_latency = pa_sink_get_requested_latency(d->sink); + has_dynamic_latency = d->sink->flags & PA_SINK_DYNAMIC_LATENCY; + latency = pa_sink_get_latency(d->sink); + is_hardware_device = d->sink->flags & PA_SINK_HARDWARE; + is_network_device = d->sink->flags & PA_SINK_NETWORK; + state = pa_sink_get_state(d->sink); + } else { + idx = d->source->index; + name = d->source->name; + driver = d->source->driver; + owner_module = d->source->module; + card = d->source->card; + sample_format = d->source->sample_spec.format; + sample_rate = d->source->sample_spec.rate; + channel_map = &d->source->channel_map; + has_flat_volume = FALSE; + has_convertible_to_decibel_volume = d->source->flags & PA_SOURCE_DECIBEL_VOLUME; + base_volume = d->source->base_volume; + volume_steps = d->source->n_volume_steps; + has_hardware_volume = d->source->flags & PA_SOURCE_HW_VOLUME_CTRL; + has_hardware_mute = d->source->flags & PA_SOURCE_HW_MUTE_CTRL; + configured_latency = pa_source_get_requested_latency(d->source); + has_dynamic_latency = d->source->flags & PA_SOURCE_DYNAMIC_LATENCY; + latency = pa_source_get_latency(d->source); + is_hardware_device = d->source->flags & PA_SOURCE_HARDWARE; + is_network_device = d->source->flags & PA_SOURCE_NETWORK; + state = pa_source_get_state(d->source); + } + if (owner_module) + owner_module_path = pa_dbusiface_core_get_module_path(d->core, owner_module); + if (card) + card_path = pa_dbusiface_core_get_card_path(d->core, card); + for (i = 0; i < channel_map->channels; ++i) + channels[i] = channel_map->map[i]; + for (i = 0; i < d->volume.channels; ++i) + volume[i] = d->volume.values[i]; + ports = get_ports(d, &n_ports); + if (d->active_port) + active_port = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &name); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver); + + if (owner_module) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path); + + if (card) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CARD].property_name, DBUS_TYPE_OBJECT_PATH, &card_path); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &sample_rate); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, d->volume.channels); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_FLAT_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_flat_volume); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_CONVERTIBLE_TO_DECIBEL_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BASE_VOLUME].property_name, DBUS_TYPE_UINT32, &base_volume); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME_STEPS].property_name, DBUS_TYPE_UINT32, &volume_steps); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &d->mute); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_HARDWARE_VOLUME].property_name, DBUS_TYPE_BOOLEAN, &has_hardware_volume); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_HARDWARE_MUTE].property_name, DBUS_TYPE_BOOLEAN, &has_hardware_mute); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CONFIGURED_LATENCY].property_name, DBUS_TYPE_UINT64, &configured_latency); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_HAS_DYNAMIC_LATENCY].property_name, DBUS_TYPE_BOOLEAN, &has_dynamic_latency); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_LATENCY].property_name, DBUS_TYPE_UINT64, &latency); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_HARDWARE_DEVICE].property_name, DBUS_TYPE_BOOLEAN, &is_hardware_device); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_NETWORK_DEVICE].property_name, DBUS_TYPE_BOOLEAN, &is_network_device); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_STATE].property_name, DBUS_TYPE_UINT32, &state); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PORTS].property_name, DBUS_TYPE_OBJECT_PATH, ports, n_ports); + + if (active_port) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACTIVE_PORT].property_name, DBUS_TYPE_OBJECT_PATH, &active_port); + + pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, d->proplist); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(ports); +} + +static void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + dbus_bool_t suspend = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &suspend, DBUS_TYPE_INVALID)); + + if ((d->type == DEVICE_TYPE_SINK) && (pa_sink_suspend(d->sink, suspend, PA_SUSPEND_USER) < 0)) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_sink_suspend() failed."); + return; + } else if ((d->type == DEVICE_TYPE_SOURCE) && (pa_source_suspend(d->source, suspend, PA_SUSPEND_USER) < 0)) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_source_suspend() failed."); + return; + } + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *port_name = NULL; + pa_dbusiface_device_port *port = NULL; + const char *port_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &port_name, DBUS_TYPE_INVALID)); + + if (!(port = pa_hashmap_get(d->ports, port_name))) { + if (d->type == DEVICE_TYPE_SINK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, + "%s: No such port on sink %s.", port_name, d->sink->name); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, + "%s: No such port on source %s.", port_name, d->source->name); + return; + } + + port_path = pa_dbusiface_device_port_get_path(port); + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &port_path); +} + +static void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *monitor_source = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + pa_assert(d->type == DEVICE_TYPE_SINK); + + monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &monitor_source); +} + +static void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + const char *monitor_source = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + pa_assert(d->type == DEVICE_TYPE_SINK); + + monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[SINK_PROPERTY_HANDLER_MONITOR_SOURCE].property_name, DBUS_TYPE_OBJECT_PATH, &monitor_source); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); +} + +static void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + const char *monitor_of_sink = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + pa_assert(d->type == DEVICE_TYPE_SOURCE); + + if (!d->source->monitor_of) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Source %s is not a monitor source.", d->source->name); + return; + } + + monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &monitor_of_sink); +} + +static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_device *d = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + const char *monitor_of_sink = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(d); + pa_assert(d->type == DEVICE_TYPE_SOURCE); + + if (d->source->monitor_of) + monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + if (monitor_of_sink) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[SOURCE_PROPERTY_HANDLER_MONITOR_OF_SINK].property_name, DBUS_TYPE_OBJECT_PATH, &monitor_of_sink); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); +} + +static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_device *d = userdata; + DBusMessage *signal = NULL; + const pa_cvolume *new_volume = NULL; + pa_bool_t new_mute = FALSE; + pa_sink_state_t new_sink_state = 0; + pa_source_state_t new_source_state = 0; + pa_device_port *new_active_port = NULL; + pa_proplist *new_proplist = NULL; + unsigned i = 0; + + pa_assert(c); + pa_assert(d); + + if ((d->type == DEVICE_TYPE_SINK && idx != d->sink->index) || (d->type == DEVICE_TYPE_SOURCE && idx != d->source->index)) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + pa_assert(((d->type == DEVICE_TYPE_SINK) + && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK)) + || ((d->type == DEVICE_TYPE_SOURCE) + && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE))); + + new_volume = (d->type == DEVICE_TYPE_SINK) + ? pa_sink_get_volume(d->sink, FALSE) + : pa_source_get_volume(d->source, FALSE); + + if (!pa_cvolume_equal(&d->volume, new_volume)) { + dbus_uint32_t volume[PA_CHANNELS_MAX]; + dbus_uint32_t *volume_ptr = volume; + + d->volume = *new_volume; + + for (i = 0; i < d->volume.channels; ++i) + volume[i] = d->volume.values[i]; + + pa_assert_se(signal = dbus_message_new_signal(d->path, + PA_DBUSIFACE_DEVICE_INTERFACE, + signals[SIGNAL_VOLUME_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, + DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, d->volume.channels, + DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(d->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + new_mute = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, FALSE) : pa_source_get_mute(d->source, FALSE); + + if (d->mute != new_mute) { + d->mute = new_mute; + + pa_assert_se(signal = dbus_message_new_signal(d->path, + PA_DBUSIFACE_DEVICE_INTERFACE, + signals[SIGNAL_MUTE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(d->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + if (d->type == DEVICE_TYPE_SINK) + new_sink_state = pa_sink_get_state(d->sink); + else + new_source_state = pa_source_get_state(d->source); + + if ((d->type == DEVICE_TYPE_SINK && d->sink_state != new_sink_state) + || (d->type == DEVICE_TYPE_SOURCE && d->source_state != new_source_state)) { + dbus_uint32_t state = 0; + + if (d->type == DEVICE_TYPE_SINK) + d->sink_state = new_sink_state; + else + d->source_state = new_source_state; + + state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state; + + pa_assert_se(signal = dbus_message_new_signal(d->path, + PA_DBUSIFACE_DEVICE_INTERFACE, + signals[SIGNAL_STATE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(d->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + new_active_port = (d->type == DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port; + + if (d->active_port != new_active_port) { + const char *object_path = NULL; + + d->active_port = new_active_port; + object_path = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); + + pa_assert_se(signal = dbus_message_new_signal(d->path, + PA_DBUSIFACE_DEVICE_INTERFACE, + signals[SIGNAL_ACTIVE_PORT_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(d->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + new_proplist = (d->type == DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist; + + if (!pa_proplist_equal(d->proplist, new_proplist)) { + DBusMessageIter msg_iter; + + pa_proplist_update(d->proplist, PA_UPDATE_SET, new_proplist); + + pa_assert_se(signal = dbus_message_new_signal(d->path, + PA_DBUSIFACE_DEVICE_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_dbus_append_proplist(&msg_iter, d->proplist); + + pa_dbus_protocol_send_signal(d->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } +} + +pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_sink *sink) { + pa_dbusiface_device *d = NULL; + + pa_assert(core); + pa_assert(sink); + + d = pa_xnew0(pa_dbusiface_device, 1); + d->core = core; + d->sink = pa_sink_ref(sink); + d->type = DEVICE_TYPE_SINK; + d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SINK_OBJECT_NAME, sink->index); + d->volume = *pa_sink_get_volume(sink, FALSE); + d->mute = pa_sink_get_mute(sink, FALSE); + d->sink_state = pa_sink_get_state(sink); + d->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + d->next_port_index = 0; + d->active_port = NULL; + d->proplist = pa_proplist_copy(sink->proplist); + d->dbus_protocol = pa_dbus_protocol_get(sink->core); + d->subscription = pa_subscription_new(sink->core, PA_SUBSCRIPTION_MASK_SINK, subscription_cb, d); + + if (sink->ports) { + pa_device_port *port; + void *state = NULL; + + PA_HASHMAP_FOREACH(port, sink->ports, state) { + pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++); + pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p); + } + pa_assert_se(d->active_port = sink->active_port); + } + + pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0); + pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &sink_interface_info, d) >= 0); + + return d; +} + +pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_source *source) { + pa_dbusiface_device *d = NULL; + + pa_assert(core); + pa_assert(source); + + d = pa_xnew0(pa_dbusiface_device, 1); + d->core = core; + d->source = pa_source_ref(source); + d->type = DEVICE_TYPE_SOURCE; + d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SOURCE_OBJECT_NAME, source->index); + d->volume = *pa_source_get_volume(source, FALSE); + d->mute = pa_source_get_mute(source, FALSE); + d->source_state = pa_source_get_state(source); + d->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + d->next_port_index = 0; + d->active_port = NULL; + d->proplist = pa_proplist_copy(source->proplist); + d->dbus_protocol = pa_dbus_protocol_get(source->core); + d->subscription = pa_subscription_new(source->core, PA_SUBSCRIPTION_MASK_SOURCE, subscription_cb, d); + + if (source->ports) { + pa_device_port *port; + void *state = NULL; + + PA_HASHMAP_FOREACH(port, source->ports, state) { + pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++); + pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p); + } + pa_assert_se(d->active_port = source->active_port); + } + + pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0); + pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &source_interface_info, d) >= 0); + + return d; +} + +static void port_free_cb(void *p, void *userdata) { + pa_dbusiface_device_port *port = p; + + pa_assert(port); + + pa_dbusiface_device_port_free(port); +} + +void pa_dbusiface_device_free(pa_dbusiface_device *d) { + pa_assert(d); + + pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, device_interface_info.name) >= 0); + + if (d->type == DEVICE_TYPE_SINK) { + pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, sink_interface_info.name) >= 0); + pa_sink_unref(d->sink); + + } else { + pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, source_interface_info.name) >= 0); + pa_source_unref(d->source); + } + pa_hashmap_free(d->ports, port_free_cb, NULL); + pa_proplist_free(d->proplist); + pa_dbus_protocol_unref(d->dbus_protocol); + pa_subscription_free(d->subscription); + + pa_xfree(d->path); + pa_xfree(d); +} + +const char *pa_dbusiface_device_get_path(pa_dbusiface_device *d) { + pa_assert(d); + + return d->path; +} + +pa_sink *pa_dbusiface_device_get_sink(pa_dbusiface_device *d) { + pa_assert(d); + pa_assert(d->type == DEVICE_TYPE_SINK); + + return d->sink; +} + +pa_source *pa_dbusiface_device_get_source(pa_dbusiface_device *d) { + pa_assert(d); + pa_assert(d->type == DEVICE_TYPE_SOURCE); + + return d->source; +} diff --git a/src/modules/dbus/iface-device.h b/src/modules/dbus/iface-device.h new file mode 100644 index 00000000..62e05e9a --- /dev/null +++ b/src/modules/dbus/iface-device.h @@ -0,0 +1,53 @@ +#ifndef foodbusifacedevicehfoo +#define foodbusifacedevicehfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interfaces org.PulseAudio.Core1.Device, + * org.PulseAudio.Core1.Sink and org.PulseAudio.Core1.Source. + * + * See http://pulseaudio.org/wiki/DBusInterface for the interface + * documentation. + */ + +#include <pulsecore/protocol-dbus.h> +#include <pulsecore/sink.h> +#include <pulsecore/source.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_DEVICE_INTERFACE PA_DBUS_CORE_INTERFACE ".Device" +#define PA_DBUSIFACE_SINK_INTERFACE PA_DBUS_CORE_INTERFACE ".Sink" +#define PA_DBUSIFACE_SOURCE_INTERFACE PA_DBUS_CORE_INTERFACE ".Source" + +typedef struct pa_dbusiface_device pa_dbusiface_device; + +pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_sink *sink); +pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_source *source); +void pa_dbusiface_device_free(pa_dbusiface_device *d); + +const char *pa_dbusiface_device_get_path(pa_dbusiface_device *d); + +pa_sink *pa_dbusiface_device_get_sink(pa_dbusiface_device *d); +pa_source *pa_dbusiface_device_get_source(pa_dbusiface_device *d); + +#endif diff --git a/src/modules/dbus/iface-memstats.c b/src/modules/dbus/iface-memstats.c new file mode 100644 index 00000000..73a84be8 --- /dev/null +++ b/src/modules/dbus/iface-memstats.c @@ -0,0 +1,231 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulsecore/core-scache.h> +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-memstats.h" + +#define OBJECT_NAME "memstats" + +static void handle_get_current_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_current_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_accumulated_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_accumulated_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_cache_size(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +struct pa_dbusiface_memstats { + pa_core *core; + char *path; + pa_dbus_protocol *dbus_protocol; +}; + +enum property_handler_index { + PROPERTY_HANDLER_CURRENT_MEMBLOCKS, + PROPERTY_HANDLER_CURRENT_MEMBLOCKS_SIZE, + PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS, + PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS_SIZE, + PROPERTY_HANDLER_SAMPLE_CACHE_SIZE, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_CURRENT_MEMBLOCKS] = { .property_name = "CurrentMemblocks", .type = "u", .get_cb = handle_get_current_memblocks, .set_cb = NULL }, + [PROPERTY_HANDLER_CURRENT_MEMBLOCKS_SIZE] = { .property_name = "CurrentMemblocksSize", .type = "u", .get_cb = handle_get_current_memblocks_size, .set_cb = NULL }, + [PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS] = { .property_name = "AccumulatedMemblocks", .type = "u", .get_cb = handle_get_accumulated_memblocks, .set_cb = NULL }, + [PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS_SIZE] = { .property_name = "AccumulatedMemblocksSize", .type = "u", .get_cb = handle_get_accumulated_memblocks_size, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_CACHE_SIZE] = { .property_name = "SampleCacheSize", .type = "u", .get_cb = handle_get_sample_cache_size, .set_cb = NULL } +}; + +static pa_dbus_interface_info memstats_interface_info = { + .name = PA_DBUSIFACE_MEMSTATS_INTERFACE, + .method_handlers = NULL, + .n_method_handlers = 0, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = NULL, + .n_signals = 0 +}; + +static void handle_get_current_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_memstats *m = userdata; + const pa_mempool_stat *stat; + dbus_uint32_t current_memblocks; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + stat = pa_mempool_get_stat(m->core->mempool); + + current_memblocks = pa_atomic_load(&stat->n_allocated); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, ¤t_memblocks); +} + +static void handle_get_current_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_memstats *m = userdata; + const pa_mempool_stat *stat; + dbus_uint32_t current_memblocks_size; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + stat = pa_mempool_get_stat(m->core->mempool); + + current_memblocks_size = pa_atomic_load(&stat->allocated_size); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, ¤t_memblocks_size); +} + +static void handle_get_accumulated_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_memstats *m = userdata; + const pa_mempool_stat *stat; + dbus_uint32_t accumulated_memblocks; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + stat = pa_mempool_get_stat(m->core->mempool); + + accumulated_memblocks = pa_atomic_load(&stat->n_accumulated); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &accumulated_memblocks); +} + +static void handle_get_accumulated_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_memstats *m = userdata; + const pa_mempool_stat *stat; + dbus_uint32_t accumulated_memblocks_size; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + stat = pa_mempool_get_stat(m->core->mempool); + + accumulated_memblocks_size = pa_atomic_load(&stat->accumulated_size); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &accumulated_memblocks_size); +} + +static void handle_get_sample_cache_size(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_memstats *m = userdata; + dbus_uint32_t sample_cache_size; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + sample_cache_size = pa_scache_total_size(m->core); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_cache_size); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_memstats *m = userdata; + const pa_mempool_stat *stat; + dbus_uint32_t current_memblocks; + dbus_uint32_t current_memblocks_size; + dbus_uint32_t accumulated_memblocks; + dbus_uint32_t accumulated_memblocks_size; + dbus_uint32_t sample_cache_size; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + stat = pa_mempool_get_stat(m->core->mempool); + + current_memblocks = pa_atomic_load(&stat->n_allocated); + current_memblocks_size = pa_atomic_load(&stat->allocated_size); + accumulated_memblocks = pa_atomic_load(&stat->n_accumulated); + accumulated_memblocks_size = pa_atomic_load(&stat->accumulated_size); + sample_cache_size = pa_scache_total_size(m->core); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CURRENT_MEMBLOCKS].property_name, DBUS_TYPE_UINT32, ¤t_memblocks); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CURRENT_MEMBLOCKS_SIZE].property_name, DBUS_TYPE_UINT32, ¤t_memblocks_size); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS].property_name, DBUS_TYPE_UINT32, &accumulated_memblocks); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS_SIZE].property_name, DBUS_TYPE_UINT32, &accumulated_memblocks_size); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_CACHE_SIZE].property_name, DBUS_TYPE_UINT32, &sample_cache_size); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); +} + +pa_dbusiface_memstats *pa_dbusiface_memstats_new(pa_dbusiface_core *dbus_core, pa_core *core) { + pa_dbusiface_memstats *m; + + pa_assert(dbus_core); + pa_assert(core); + + m = pa_xnew(pa_dbusiface_memstats, 1); + m->core = pa_core_ref(core); + m->path = pa_sprintf_malloc("%s/%s", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME); + m->dbus_protocol = pa_dbus_protocol_get(core); + + pa_assert_se(pa_dbus_protocol_add_interface(m->dbus_protocol, m->path, &memstats_interface_info, m) >= 0); + + return m; +} + +void pa_dbusiface_memstats_free(pa_dbusiface_memstats *m) { + pa_assert(m); + + pa_assert_se(pa_dbus_protocol_remove_interface(m->dbus_protocol, m->path, memstats_interface_info.name) >= 0); + + pa_xfree(m->path); + + pa_dbus_protocol_unref(m->dbus_protocol); + pa_core_unref(m->core); + + pa_xfree(m); +} + +const char *pa_dbusiface_memstats_get_path(pa_dbusiface_memstats *m) { + pa_assert(m); + + return m->path; +} diff --git a/src/modules/dbus/iface-memstats.h b/src/modules/dbus/iface-memstats.h new file mode 100644 index 00000000..0820e8fe --- /dev/null +++ b/src/modules/dbus/iface-memstats.h @@ -0,0 +1,45 @@ +#ifndef foodbusifacememstatshfoo +#define foodbusifacememstatshfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.Memstats. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Memstats interface + * documentation. + */ + +#include <pulsecore/core.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_MEMSTATS_INTERFACE PA_DBUS_CORE_INTERFACE ".Memstats" + +typedef struct pa_dbusiface_memstats pa_dbusiface_memstats; + +pa_dbusiface_memstats *pa_dbusiface_memstats_new(pa_dbusiface_core *dbus_core, pa_core *core); +void pa_dbusiface_memstats_free(pa_dbusiface_memstats *m); + +const char *pa_dbusiface_memstats_get_path(pa_dbusiface_memstats *m); + +#endif diff --git a/src/modules/dbus/iface-module.c b/src/modules/dbus/iface-module.c new file mode 100644 index 00000000..e8aea50f --- /dev/null +++ b/src/modules/dbus/iface-module.c @@ -0,0 +1,336 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/modargs.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-module.h" + +#define OBJECT_NAME "module" + +struct pa_dbusiface_module { + pa_module *module; + char *path; + pa_proplist *proplist; + + pa_dbus_protocol *dbus_protocol; + pa_subscription *subscription; +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_arguments(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_usage_counter(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_unload(DBusConnection *conn, DBusMessage *msg, void *userdata); + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_ARGUMENTS, + PROPERTY_HANDLER_USAGE_COUNTER, + PROPERTY_HANDLER_PROPERTY_LIST, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_ARGUMENTS] = { .property_name = "Arguments", .type = "a{ss}", .get_cb = handle_get_arguments, .set_cb = NULL }, + [PROPERTY_HANDLER_USAGE_COUNTER] = { .property_name = "UsageCounter", .type = "u", .get_cb = handle_get_usage_counter, .set_cb = NULL }, + [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_UNLOAD, + METHOD_HANDLER_MAX +}; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_UNLOAD] = { + .method_name = "Unload", + .arguments = NULL, + .n_arguments = 0, + .receive_cb = handle_unload } +}; + +enum signal_index { + SIGNAL_PROPERTY_LIST_UPDATED, + SIGNAL_MAX +}; + +static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info module_interface_info = { + .name = PA_DBUSIFACE_MODULE_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + dbus_uint32_t idx = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + idx = m->module->index; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &m->module->name); +} + +static void append_modargs_variant(DBusMessageIter *iter, pa_dbusiface_module *m) { + pa_modargs *ma = NULL; + DBusMessageIter variant_iter; + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + void *state = NULL; + const char *key = NULL; + const char *value = NULL; + + pa_assert(iter); + pa_assert(m); + + pa_assert_se(ma = pa_modargs_new(m->module->argument, NULL)); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{ss}", &variant_iter)); + pa_assert_se(dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, "{ss}", &dict_iter)); + + for (state = NULL, key = pa_modargs_iterate(ma, &state); key; key = pa_modargs_iterate(ma, &state)) { + pa_assert_se(value = pa_modargs_get_value(ma, key, NULL)); + + pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &value)); + + pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)); + } + + pa_assert_se(dbus_message_iter_close_container(&variant_iter, &dict_iter)); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); + + pa_modargs_free(ma); +} + +static void handle_get_arguments(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + pa_assert_se(reply = dbus_message_new_method_return(msg)); + dbus_message_iter_init_append(reply, &msg_iter); + append_modargs_variant(&msg_iter, m); + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} + +static void handle_get_usage_counter(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + int real_counter_value = -1; + dbus_uint32_t usage_counter = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + if (!m->module->get_n_used || (real_counter_value = m->module->get_n_used(m->module)) < 0) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Module %u (%s) doesn't have a usage counter.", m->module->index, m->module->name); + return; + } + + usage_counter = real_counter_value; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &usage_counter); +} + +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + pa_dbus_send_proplist_variant_reply(conn, msg, m->proplist); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + dbus_uint32_t idx = 0; + int real_counter_value = -1; + dbus_uint32_t usage_counter = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + idx = m->module->index; + if (m->module->get_n_used && (real_counter_value = m->module->get_n_used(m->module)) >= 0) + usage_counter = real_counter_value; + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &m->module->name); + + pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &property_handlers[PROPERTY_HANDLER_ARGUMENTS].property_name)); + append_modargs_variant(&dict_entry_iter, m); + pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)); + + if (real_counter_value >= 0) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ARGUMENTS].property_name, DBUS_TYPE_UINT32, &usage_counter); + + pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, m->proplist); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); +} + +static void handle_unload(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_module *m = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(m); + + if (m->module->core->disallow_module_loading) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "The server is configured to disallow module unloading."); + return; + } + + pa_module_unload_request(m->module, FALSE); + + pa_dbus_send_empty_reply(conn, msg); +} + +static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_module *m = userdata; + DBusMessage *signal = NULL; + + pa_assert(core); + pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_MODULE); + pa_assert(m); + + /* We can't use idx != m->module->index, because the m->module pointer may + * be stale at this point. */ + if (pa_idxset_get_by_index(core->modules, idx) != m->module) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + if (!pa_proplist_equal(m->proplist, m->module->proplist)) { + DBusMessageIter msg_iter; + + pa_proplist_update(m->proplist, PA_UPDATE_SET, m->module->proplist); + + pa_assert_se(signal = dbus_message_new_signal(m->path, + PA_DBUSIFACE_MODULE_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_dbus_append_proplist(&msg_iter, m->proplist); + + pa_dbus_protocol_send_signal(m->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } +} + +pa_dbusiface_module *pa_dbusiface_module_new(pa_module *module) { + pa_dbusiface_module *m; + + pa_assert(module); + + m = pa_xnew0(pa_dbusiface_module, 1); + m->module = module; + m->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, module->index); + m->proplist = pa_proplist_copy(module->proplist); + m->dbus_protocol = pa_dbus_protocol_get(module->core); + m->subscription = pa_subscription_new(module->core, PA_SUBSCRIPTION_MASK_MODULE, subscription_cb, m); + + pa_assert_se(pa_dbus_protocol_add_interface(m->dbus_protocol, m->path, &module_interface_info, m) >= 0); + + return m; +} + +void pa_dbusiface_module_free(pa_dbusiface_module *m) { + pa_assert(m); + + pa_assert_se(pa_dbus_protocol_remove_interface(m->dbus_protocol, m->path, module_interface_info.name) >= 0); + + pa_proplist_free(m->proplist); + pa_dbus_protocol_unref(m->dbus_protocol); + pa_subscription_free(m->subscription); + + pa_xfree(m->path); + pa_xfree(m); +} + +const char *pa_dbusiface_module_get_path(pa_dbusiface_module *m) { + pa_assert(m); + + return m->path; +} diff --git a/src/modules/dbus/iface-module.h b/src/modules/dbus/iface-module.h new file mode 100644 index 00000000..68ca1de5 --- /dev/null +++ b/src/modules/dbus/iface-module.h @@ -0,0 +1,45 @@ +#ifndef foodbusifacemodulehfoo +#define foodbusifacemodulehfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.Module. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Module interface + * documentation. + */ + +#include <pulsecore/module.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_MODULE_INTERFACE PA_DBUS_CORE_INTERFACE ".Module" + +typedef struct pa_dbusiface_module pa_dbusiface_module; + +pa_dbusiface_module *pa_dbusiface_module_new(pa_module *module); +void pa_dbusiface_module_free(pa_dbusiface_module *m); + +const char *pa_dbusiface_module_get_path(pa_dbusiface_module *m); + +#endif diff --git a/src/modules/dbus/iface-sample.c b/src/modules/dbus/iface-sample.c new file mode 100644 index 00000000..b0542a60 --- /dev/null +++ b/src/modules/dbus/iface-sample.c @@ -0,0 +1,519 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/namereg.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-sample.h" + +#define OBJECT_NAME "sample" + +struct pa_dbusiface_sample { + pa_dbusiface_core *core; + + pa_scache_entry *sample; + char *path; + pa_proplist *proplist; + + pa_dbus_protocol *dbus_protocol; + pa_subscription *subscription; +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_default_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_duration(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_bytes(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_play(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_play_to_sink(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_remove(DBusConnection *conn, DBusMessage *msg, void *userdata); + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_NAME, + PROPERTY_HANDLER_SAMPLE_FORMAT, + PROPERTY_HANDLER_SAMPLE_RATE, + PROPERTY_HANDLER_CHANNELS, + PROPERTY_HANDLER_DEFAULT_VOLUME, + PROPERTY_HANDLER_DURATION, + PROPERTY_HANDLER_BYTES, + PROPERTY_HANDLER_PROPERTY_LIST, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_get_name, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, + [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, + [PROPERTY_HANDLER_DEFAULT_VOLUME] = { .property_name = "DefaultVolume", .type = "au", .get_cb = handle_get_default_volume, .set_cb = NULL }, + [PROPERTY_HANDLER_DURATION] = { .property_name = "Duration", .type = "t", .get_cb = handle_get_duration, .set_cb = NULL }, + [PROPERTY_HANDLER_BYTES] = { .property_name = "Bytes", .type = "u", .get_cb = handle_get_bytes, .set_cb = NULL }, + [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_PLAY, + METHOD_HANDLER_PLAY_TO_SINK, + METHOD_HANDLER_REMOVE, + METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info play_args[] = { { "volume", "u", "in" }, { "property_list", "a{say}", "in" } }; +static pa_dbus_arg_info play_to_sink_args[] = { { "sink", "o", "in" }, + { "volume", "u", "in" }, + { "property_list", "a{say}", "in" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_PLAY] = { + .method_name = "Play", + .arguments = play_args, + .n_arguments = sizeof(play_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_play }, + [METHOD_HANDLER_PLAY_TO_SINK] = { + .method_name = "PlayToSink", + .arguments = play_to_sink_args, + .n_arguments = sizeof(play_to_sink_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_play_to_sink }, + [METHOD_HANDLER_REMOVE] = { + .method_name = "Remove", + .arguments = NULL, + .n_arguments = 0, + .receive_cb = handle_remove } +}; + +enum signal_index { + SIGNAL_PROPERTY_LIST_UPDATED, + SIGNAL_MAX +}; + +static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info sample_interface_info = { + .name = PA_DBUSIFACE_SAMPLE_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint32_t idx = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + idx = s->sample->index; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); +} + +static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &s->sample->name); +} + +static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint32_t sample_format = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (!s->sample->memchunk.memblock) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sample %s isn't loaded into memory yet, so its sample format is unknown.", s->sample->name); + return; + } + + sample_format = s->sample->sample_spec.format; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format); +} + +static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint32_t sample_rate = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (!s->sample->memchunk.memblock) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sample %s isn't loaded into memory yet, so its sample rate is unknown.", s->sample->name); + return; + } + + sample_rate = s->sample->sample_spec.rate; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_rate); +} + +static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint32_t channels[PA_CHANNELS_MAX]; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (!s->sample->memchunk.memblock) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sample %s isn't loaded into memory yet, so its channel map is unknown.", s->sample->name); + return; + } + + for (i = 0; i < s->sample->channel_map.channels; ++i) + channels[i] = s->sample->channel_map.map[i]; + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, s->sample->channel_map.channels); +} + +static void handle_get_default_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint32_t default_volume[PA_CHANNELS_MAX]; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (!s->sample->volume_is_set) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sample %s doesn't have default volume stored.", s->sample->name); + return; + } + + for (i = 0; i < s->sample->volume.channels; ++i) + default_volume[i] = s->sample->volume.values[i]; + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, default_volume, s->sample->volume.channels); +} + +static void handle_get_duration(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint64_t duration = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (!s->sample->memchunk.memblock) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sample %s isn't loaded into memory yet, so its duration is unknown.", s->sample->name); + return; + } + + duration = pa_bytes_to_usec(s->sample->memchunk.length, &s->sample->sample_spec); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &duration); +} + +static void handle_get_bytes(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + dbus_uint32_t bytes = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (!s->sample->memchunk.memblock) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Sample %s isn't loaded into memory yet, so its size is unknown.", s->sample->name); + return; + } + + bytes = s->sample->memchunk.length; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &bytes); +} + +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t idx = 0; + dbus_uint32_t sample_format = 0; + dbus_uint32_t sample_rate = 0; + dbus_uint32_t channels[PA_CHANNELS_MAX]; + dbus_uint32_t default_volume[PA_CHANNELS_MAX]; + dbus_uint64_t duration = 0; + dbus_uint32_t bytes = 0; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + idx = s->sample->index; + if (s->sample->memchunk.memblock) { + sample_format = s->sample->sample_spec.format; + sample_rate = s->sample->sample_spec.rate; + for (i = 0; i < s->sample->channel_map.channels; ++i) + channels[i] = s->sample->channel_map.map[i]; + duration = pa_bytes_to_usec(s->sample->memchunk.length, &s->sample->sample_spec); + bytes = s->sample->memchunk.length; + } + if (s->sample->volume_is_set) { + for (i = 0; i < s->sample->volume.channels; ++i) + default_volume[i] = s->sample->volume.values[i]; + } + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &s->sample->name); + + if (s->sample->memchunk.memblock) { + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &sample_rate); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, s->sample->channel_map.channels); + } + + if (s->sample->volume_is_set) + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEFAULT_VOLUME].property_name, DBUS_TYPE_UINT32, default_volume, s->sample->volume.channels); + + if (s->sample->memchunk.memblock) { + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DURATION].property_name, DBUS_TYPE_UINT64, &duration); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BYTES].property_name, DBUS_TYPE_UINT32, &bytes); + } + + pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} + +static void handle_play(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + DBusMessageIter msg_iter; + dbus_uint32_t volume = 0; + pa_proplist *property_list = NULL; + pa_sink *sink = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &volume); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter))) + return; + + if (volume > PA_VOLUME_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume."); + goto finish; + } + + if (!(sink = pa_namereg_get_default_sink(s->sample->core))) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, + "Can't play sample %s, because there are no sinks available.", s->sample->name); + goto finish; + } + + if (pa_scache_play_item(s->sample->core, s->sample->name, sink, volume, property_list, NULL) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Playing sample %s failed.", s->sample->name); + goto finish; + } + + pa_dbus_send_empty_reply(conn, msg); + +finish: + if (property_list) + pa_proplist_free(property_list); +} + +static void handle_play_to_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + DBusMessageIter msg_iter; + const char *sink_path = NULL; + dbus_uint32_t volume = 0; + pa_proplist *property_list = NULL; + pa_sink *sink = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &sink_path); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &volume); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + if (!(property_list = pa_dbus_get_proplist_arg(conn, msg, &msg_iter))) + return; + + if (!(sink = pa_dbusiface_core_get_sink(s->core, sink_path))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", sink_path); + goto finish; + } + + if (volume > PA_VOLUME_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume."); + goto finish; + } + + if (pa_scache_play_item(s->sample->core, s->sample->name, sink, volume, property_list, NULL) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Playing sample %s failed.", s->sample->name); + goto finish; + } + + pa_dbus_send_empty_reply(conn, msg); + +finish: + if (property_list) + pa_proplist_free(property_list); +} + +static void handle_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_sample *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (pa_scache_remove_item(s->sample->core, s->sample->name) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Removing sample %s failed.", s->sample->name); + return; + } + + pa_dbus_send_empty_reply(conn, msg); +} + +static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_sample *s = userdata; + DBusMessage *signal = NULL; + + pa_assert(c); + pa_assert(s); + + /* We can't use idx != s->sample->index, because the s->sample pointer may + * be stale at this point. */ + if (pa_idxset_get_by_index(c->scache, idx) != s->sample) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + if (!pa_proplist_equal(s->proplist, s->sample->proplist)) { + DBusMessageIter msg_iter; + + pa_proplist_update(s->proplist, PA_UPDATE_SET, s->sample->proplist); + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_SAMPLE_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_dbus_append_proplist(&msg_iter, s->proplist); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } +} + +pa_dbusiface_sample *pa_dbusiface_sample_new(pa_dbusiface_core *core, pa_scache_entry *sample) { + pa_dbusiface_sample *s = NULL; + + pa_assert(core); + pa_assert(sample); + + s = pa_xnew0(pa_dbusiface_sample, 1); + s->core = core; + s->sample = sample; + s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, sample->index); + s->proplist = pa_proplist_copy(sample->proplist); + s->dbus_protocol = pa_dbus_protocol_get(sample->core); + s->subscription = pa_subscription_new(sample->core, PA_SUBSCRIPTION_MASK_SAMPLE_CACHE, subscription_cb, s); + + pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &sample_interface_info, s) >= 0); + + return s; +} + +void pa_dbusiface_sample_free(pa_dbusiface_sample *s) { + pa_assert(s); + + pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, sample_interface_info.name) >= 0); + + pa_proplist_free(s->proplist); + pa_dbus_protocol_unref(s->dbus_protocol); + pa_subscription_free(s->subscription); + + pa_xfree(s->path); + pa_xfree(s); +} + +const char *pa_dbusiface_sample_get_path(pa_dbusiface_sample *s) { + pa_assert(s); + + return s->path; +} diff --git a/src/modules/dbus/iface-sample.h b/src/modules/dbus/iface-sample.h new file mode 100644 index 00000000..f1947ce8 --- /dev/null +++ b/src/modules/dbus/iface-sample.h @@ -0,0 +1,45 @@ +#ifndef foodbusifacesamplehfoo +#define foodbusifacesamplehfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.Sample. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Sample interface + * documentation. + */ + +#include <pulsecore/core-scache.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_SAMPLE_INTERFACE PA_DBUS_CORE_INTERFACE ".Sample" + +typedef struct pa_dbusiface_sample pa_dbusiface_sample; + +pa_dbusiface_sample *pa_dbusiface_sample_new(pa_dbusiface_core *core, pa_scache_entry *sample); +void pa_dbusiface_sample_free(pa_dbusiface_sample *c); + +const char *pa_dbusiface_sample_get_path(pa_dbusiface_sample *c); + +#endif diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c new file mode 100644 index 00000000..04a45e6c --- /dev/null +++ b/src/modules/dbus/iface-stream.c @@ -0,0 +1,894 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + Copyright 2009 Vincent Filali-Ansary <filali.v@azurdigitalnetworks.net> + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-stream.h" + +#define PLAYBACK_OBJECT_NAME "playback_stream" +#define RECORD_OBJECT_NAME "record_stream" + +enum stream_type { + STREAM_TYPE_PLAYBACK, + STREAM_TYPE_RECORD +}; + +struct pa_dbusiface_stream { + pa_dbusiface_core *core; + + union { + pa_sink_input *sink_input; + pa_source_output *source_output; + }; + enum stream_type type; + char *path; + union { + pa_sink *sink; + pa_source *source; + }; + uint32_t sample_rate; + pa_cvolume volume; + dbus_bool_t mute; + pa_proplist *proplist; + + pa_dbus_protocol *dbus_protocol; + pa_subscription *subscription; + pa_hook_slot *send_event_slot; +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata); + +enum property_handler_index { + PROPERTY_HANDLER_INDEX, + PROPERTY_HANDLER_DRIVER, + PROPERTY_HANDLER_OWNER_MODULE, + PROPERTY_HANDLER_CLIENT, + PROPERTY_HANDLER_DEVICE, + PROPERTY_HANDLER_SAMPLE_FORMAT, + PROPERTY_HANDLER_SAMPLE_RATE, + PROPERTY_HANDLER_CHANNELS, + PROPERTY_HANDLER_VOLUME, + PROPERTY_HANDLER_MUTE, + PROPERTY_HANDLER_BUFFER_LATENCY, + PROPERTY_HANDLER_DEVICE_LATENCY, + PROPERTY_HANDLER_RESAMPLE_METHOD, + PROPERTY_HANDLER_PROPERTY_LIST, + PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, + [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, + [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, + [PROPERTY_HANDLER_CLIENT] = { .property_name = "Client", .type = "o", .get_cb = handle_get_client, .set_cb = NULL }, + [PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "o", .get_cb = handle_get_device, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL }, + [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, + [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, + [PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "au", .get_cb = handle_get_volume, .set_cb = handle_set_volume }, + [PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_get_mute, .set_cb = handle_set_mute }, + [PROPERTY_HANDLER_BUFFER_LATENCY] = { .property_name = "BufferLatency", .type = "t", .get_cb = handle_get_buffer_latency, .set_cb = NULL }, + [PROPERTY_HANDLER_DEVICE_LATENCY] = { .property_name = "DeviceLatency", .type = "t", .get_cb = handle_get_device_latency, .set_cb = NULL }, + [PROPERTY_HANDLER_RESAMPLE_METHOD] = { .property_name = "ResampleMethod", .type = "s", .get_cb = handle_get_resample_method, .set_cb = NULL }, + [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } +}; + +enum method_handler_index { + METHOD_HANDLER_MOVE, + METHOD_HANDLER_KILL, + METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info move_args[] = { { "device", "o", "in" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_MOVE] = { + .method_name = "Move", + .arguments = move_args, + .n_arguments = sizeof(move_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_move }, + [METHOD_HANDLER_KILL] = { + .method_name = "Kill", + .arguments = NULL, + .n_arguments = 0, + .receive_cb = handle_kill } +}; + +enum signal_index { + SIGNAL_DEVICE_UPDATED, + SIGNAL_SAMPLE_RATE_UPDATED, + SIGNAL_VOLUME_UPDATED, + SIGNAL_MUTE_UPDATED, + SIGNAL_PROPERTY_LIST_UPDATED, + SIGNAL_STREAM_EVENT, + SIGNAL_MAX +}; + +static pa_dbus_arg_info device_updated_args[] = { { "device", "o", NULL } }; +static pa_dbus_arg_info sample_rate_updated_args[] = { { "sample_rate", "u", NULL } }; +static pa_dbus_arg_info volume_updated_args[] = { { "volume", "au", NULL } }; +static pa_dbus_arg_info mute_updated_args[] = { { "muted", "b", NULL } }; +static pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; +static pa_dbus_arg_info stream_event_args[] = { { "name", "s", NULL }, { "property_list", "a{say}", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = device_updated_args, .n_arguments = 1 }, + [SIGNAL_SAMPLE_RATE_UPDATED] = { .name = "SampleRateUpdated", .arguments = sample_rate_updated_args, .n_arguments = 1 }, + [SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = volume_updated_args, .n_arguments = 1 }, + [SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = mute_updated_args, .n_arguments = 1 }, + [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 }, + [SIGNAL_STREAM_EVENT] = { .name = "StreamEvent", .arguments = stream_event_args, .n_arguments = sizeof(stream_event_args) / sizeof(pa_dbus_arg_info) } +}; + +static pa_dbus_interface_info stream_interface_info = { + .name = PA_DBUSIFACE_STREAM_INTERFACE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + dbus_uint32_t idx; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + idx = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->index : s->source_output->index; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); +} + +static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + const char *driver = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + driver = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->driver : s->source_output->driver; + + if (!driver) { + if (s->type == STREAM_TYPE_PLAYBACK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Playback stream %u doesn't have a driver.", s->sink_input->index); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Record stream %u doesn't have a driver.", s->source_output->index); + return; + } + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver); +} + +static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + pa_module *owner_module = NULL; + const char *object_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + owner_module = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->module : s->source_output->module; + + if (!owner_module) { + if (s->type == STREAM_TYPE_PLAYBACK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Playback stream %u doesn't have an owner module.", s->sink_input->index); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Record stream %u doesn't have an owner module.", s->source_output->index); + return; + } + + object_path = pa_dbusiface_core_get_module_path(s->core, owner_module); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + pa_client *client = NULL; + const char *object_path = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + client = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->client : s->source_output->client; + + if (!client) { + if (s->type == STREAM_TYPE_PLAYBACK) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Playback stream %u isn't associated to any client.", s->sink_input->index); + else + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, + "Record stream %u isn't associated to any client.", s->source_output->index); + return; + } + + object_path = pa_dbusiface_core_get_client_path(s->core, client); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); +} + +static void handle_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + const char *device = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) + device = pa_dbusiface_core_get_sink_path(s->core, s->sink); + else + device = pa_dbusiface_core_get_source_path(s->core, s->source); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &device); +} + +static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + dbus_uint32_t sample_format = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + sample_format = (s->type == STREAM_TYPE_PLAYBACK) + ? s->sink_input->sample_spec.format + : s->source_output->sample_spec.format; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format); +} + +static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &s->sample_rate); +} + +static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + pa_channel_map *channel_map = NULL; + dbus_uint32_t channels[PA_CHANNELS_MAX]; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + channel_map = (s->type == STREAM_TYPE_PLAYBACK) ? &s->sink_input->channel_map : &s->source_output->channel_map; + + for (i = 0; i < channel_map->channels; ++i) + channels[i] = channel_map->map[i]; + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, channel_map->channels); +} + +static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + dbus_uint32_t volume[PA_CHANNELS_MAX]; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_RECORD) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume."); + return; + } + + for (i = 0; i < s->volume.channels; ++i) + volume[i] = s->volume.values[i]; + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, s->volume.channels); +} + +static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_stream *s = userdata; + DBusMessageIter array_iter; + int stream_channels = 0; + dbus_uint32_t *volume = NULL; + int n_volume_entries = 0; + pa_cvolume new_vol; + int i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(s); + + if (s->type == STREAM_TYPE_RECORD) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume."); + return; + } + + pa_cvolume_init(&new_vol); + + stream_channels = s->sink_input->channel_map.channels; + + new_vol.channels = stream_channels; + + dbus_message_iter_recurse(iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries); + + if (n_volume_entries != stream_channels) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, + "Expected %u volume entries, got %u.", stream_channels, n_volume_entries); + return; + } + + for (i = 0; i < n_volume_entries; ++i) { + if (volume[i] > PA_VOLUME_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]); + return; + } + new_vol.values[i] = volume[i]; + } + + pa_sink_input_set_volume(s->sink_input, &new_vol, TRUE, TRUE); + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_RECORD) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute."); + return; + } + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &s->mute); +} + +static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + pa_dbusiface_stream *s = userdata; + dbus_bool_t mute = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(s); + + dbus_message_iter_get_basic(iter, &mute); + + if (s->type == STREAM_TYPE_RECORD) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute."); + return; + } + + pa_sink_input_set_mute(s->sink_input, mute, TRUE); + + pa_dbus_send_empty_reply(conn, msg); +}; + +static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + dbus_uint64_t buffer_latency = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) + buffer_latency = pa_sink_input_get_latency(s->sink_input, NULL); + else + buffer_latency = pa_source_output_get_latency(s->source_output, NULL); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &buffer_latency); +} + +static void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + dbus_uint64_t device_latency = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) + pa_sink_input_get_latency(s->sink_input, &device_latency); + else + pa_source_output_get_latency(s->source_output, &device_latency); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &device_latency); +} + +static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + const char *resample_method = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) + resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method); + else + resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &resample_method); +} + +static void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t idx = 0; + const char *driver = NULL; + pa_module *owner_module = NULL; + const char *owner_module_path = NULL; + pa_client *client = NULL; + const char *client_path = NULL; + const char *device = NULL; + dbus_uint32_t sample_format = 0; + pa_channel_map *channel_map = NULL; + dbus_uint32_t channels[PA_CHANNELS_MAX]; + dbus_uint32_t volume[PA_CHANNELS_MAX]; + dbus_uint64_t buffer_latency = 0; + dbus_uint64_t device_latency = 0; + const char *resample_method = NULL; + unsigned i = 0; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) { + idx = s->sink_input->index; + driver = s->sink_input->driver; + owner_module = s->sink_input->module; + client = s->sink_input->client; + device = pa_dbusiface_core_get_sink_path(s->core, s->sink); + sample_format = s->sink_input->sample_spec.format; + channel_map = &s->sink_input->channel_map; + for (i = 0; i < s->volume.channels; ++i) + volume[i] = s->volume.values[i]; + buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency); + resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method); + } else { + idx = s->source_output->index; + driver = s->source_output->driver; + owner_module = s->source_output->module; + client = s->source_output->client; + device = pa_dbusiface_core_get_source_path(s->core, s->source); + sample_format = s->source_output->sample_spec.format; + channel_map = &s->source_output->channel_map; + buffer_latency = pa_source_output_get_latency(s->source_output, &device_latency); + resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method); + } + if (owner_module) + owner_module_path = pa_dbusiface_core_get_module_path(s->core, owner_module); + if (client) + client_path = pa_dbusiface_core_get_client_path(s->core, client); + for (i = 0; i < channel_map->channels; ++i) + channels[i] = channel_map->map[i]; + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); + + if (driver) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver); + + if (owner_module) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path); + + if (client) + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels); + + if (s->type == STREAM_TYPE_PLAYBACK) { + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &s->mute); + } + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BUFFER_LATENCY].property_name, DBUS_TYPE_UINT64, &buffer_latency); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE_LATENCY].property_name, DBUS_TYPE_UINT64, &device_latency); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RESAMPLE_METHOD].property_name, DBUS_TYPE_STRING, &resample_method); + pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} + +static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + const char *device = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID)); + + if (s->type == STREAM_TYPE_PLAYBACK) { + pa_sink *sink = pa_dbusiface_core_get_sink(s->core, device); + + if (!sink) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", device); + return; + } + + if (pa_sink_input_move_to(s->sink_input, sink, TRUE) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, + "Moving playback stream %u to sink %s failed.", s->sink_input->index, sink->name); + return; + } + } else { + pa_source *source = pa_dbusiface_core_get_source(s->core, device); + + if (!source) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", device); + return; + } + + if (pa_source_output_move_to(s->source_output, source, TRUE) < 0) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, + "Moving record stream %u to source %s failed.", s->source_output->index, source->name); + return; + } + } + + pa_dbus_send_empty_reply(conn, msg); +} + +static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) { + pa_dbusiface_stream *s = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) + pa_sink_input_kill(s->sink_input); + else + pa_source_output_kill(s->source_output); + + pa_dbus_send_empty_reply(conn, msg); +} + +static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + pa_dbusiface_stream *s = userdata; + DBusMessage *signal = NULL; + const char *new_device_path = NULL; + uint32_t new_sample_rate = 0; + pa_proplist *new_proplist = NULL; + unsigned i = 0; + + pa_assert(c); + pa_assert(s); + + if ((s->type == STREAM_TYPE_PLAYBACK && idx != s->sink_input->index) + || (s->type == STREAM_TYPE_RECORD && idx != s->source_output->index)) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) + return; + + pa_assert(((s->type == STREAM_TYPE_PLAYBACK) + && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT)) + || ((s->type == STREAM_TYPE_RECORD) + && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT))); + + if (s->type == STREAM_TYPE_PLAYBACK) { + pa_sink *new_sink = s->sink_input->sink; + + if (s->sink != new_sink) { + pa_sink_unref(s->sink); + s->sink = pa_sink_ref(new_sink); + + new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink); + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_DEVICE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + } else { + pa_source *new_source = s->source_output->source; + + if (s->source != new_source) { + pa_source_unref(s->source); + s->source = pa_source_ref(new_source); + + new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source); + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_DEVICE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + } + + new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->sample_spec.rate : s->source_output->sample_spec.rate; + + if (s->sample_rate != new_sample_rate) { + s->sample_rate = new_sample_rate; + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + if (s->type == STREAM_TYPE_PLAYBACK) { + pa_cvolume new_volume; + pa_bool_t new_mute = FALSE; + + pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE); + + if (!pa_cvolume_equal(&s->volume, &new_volume)) { + dbus_uint32_t volume[PA_CHANNELS_MAX]; + dbus_uint32_t *volume_ptr = volume; + + s->volume = new_volume; + + for (i = 0; i < s->volume.channels; ++i) + volume[i] = s->volume.values[i]; + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_VOLUME_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, + DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels, + DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + + new_mute = pa_sink_input_get_mute(s->sink_input); + + if (s->mute != new_mute) { + s->mute = new_mute; + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_MUTE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } + } + + new_proplist = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->proplist : s->source_output->proplist; + + if (!pa_proplist_equal(s->proplist, new_proplist)) { + DBusMessageIter msg_iter; + + pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist); + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_dbus_append_proplist(&msg_iter, s->proplist); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + signal = NULL; + } +} + +static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_stream *s = slot_data; + DBusMessage *signal = NULL; + DBusMessageIter msg_iter; + const char *name = NULL; + pa_proplist *property_list = NULL; + + pa_assert(call_data); + pa_assert(s); + + if (s->type == STREAM_TYPE_PLAYBACK) { + pa_sink_input_send_event_hook_data *data = call_data; + + if (data->sink_input != s->sink_input) + return PA_HOOK_OK; + + name = data->event; + property_list = data->data; + } else { + pa_source_output_send_event_hook_data *data = call_data; + + if (data->source_output != s->source_output) + return PA_HOOK_OK; + + name = data->event; + property_list = data->data; + } + + pa_assert_se(signal = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_STREAM_EVENT].name)); + dbus_message_iter_init_append(signal, &msg_iter); + pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name)); + pa_dbus_append_proplist(&msg_iter, property_list); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal); + dbus_message_unref(signal); + + return PA_HOOK_OK; +} + +pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, pa_sink_input *sink_input) { + pa_dbusiface_stream *s; + + pa_assert(core); + pa_assert(sink_input); + + s = pa_xnew(pa_dbusiface_stream, 1); + s->core = core; + s->sink_input = pa_sink_input_ref(sink_input); + s->type = STREAM_TYPE_PLAYBACK; + s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index); + s->sink = pa_sink_ref(sink_input->sink); + s->sample_rate = sink_input->sample_spec.rate; + pa_sink_input_get_volume(sink_input, &s->volume, TRUE); + s->mute = pa_sink_input_get_mute(sink_input); + s->proplist = pa_proplist_copy(sink_input->proplist); + s->dbus_protocol = pa_dbus_protocol_get(sink_input->core); + s->subscription = pa_subscription_new(sink_input->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscription_cb, s); + s->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], + PA_HOOK_NORMAL, + send_event_cb, + s); + + pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); + + return s; +} + +pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_source_output *source_output) { + pa_dbusiface_stream *s; + + pa_assert(core); + pa_assert(source_output); + + s = pa_xnew(pa_dbusiface_stream, 1); + s->core = core; + s->source_output = pa_source_output_ref(source_output); + s->type = STREAM_TYPE_RECORD; + s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, RECORD_OBJECT_NAME, source_output->index); + s->source = pa_source_ref(source_output->source); + s->sample_rate = source_output->sample_spec.rate; + pa_cvolume_init(&s->volume); + s->mute = FALSE; + s->proplist = pa_proplist_copy(source_output->proplist); + s->dbus_protocol = pa_dbus_protocol_get(source_output->core); + s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s); + s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], + PA_HOOK_NORMAL, + send_event_cb, + s); + + pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); + + return s; +} + +void pa_dbusiface_stream_free(pa_dbusiface_stream *s) { + pa_assert(s); + + pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, stream_interface_info.name) >= 0); + + if (s->type == STREAM_TYPE_PLAYBACK) { + pa_sink_input_unref(s->sink_input); + pa_sink_unref(s->sink); + } else { + pa_source_output_unref(s->source_output); + pa_source_unref(s->source); + } + + pa_proplist_free(s->proplist); + pa_dbus_protocol_unref(s->dbus_protocol); + pa_subscription_free(s->subscription); + pa_hook_slot_free(s->send_event_slot); + + pa_xfree(s->path); + pa_xfree(s); +} + +const char *pa_dbusiface_stream_get_path(pa_dbusiface_stream *s) { + pa_assert(s); + + return s->path; +} diff --git a/src/modules/dbus/iface-stream.h b/src/modules/dbus/iface-stream.h new file mode 100644 index 00000000..036b4e7e --- /dev/null +++ b/src/modules/dbus/iface-stream.h @@ -0,0 +1,47 @@ +#ifndef foodbusifacestreamhfoo +#define foodbusifacestreamhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus interface org.PulseAudio.Core1.Stream. + * + * See http://pulseaudio.org/wiki/DBusInterface for the Stream interface + * documentation. + */ + +#include <pulsecore/protocol-dbus.h> +#include <pulsecore/sink-input.h> +#include <pulsecore/source-output.h> + +#include "iface-core.h" + +#define PA_DBUSIFACE_STREAM_INTERFACE PA_DBUS_CORE_INTERFACE ".Stream" + +typedef struct pa_dbusiface_stream pa_dbusiface_stream; + +pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, pa_sink_input *sink_input); +pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_source_output *source_output); +void pa_dbusiface_stream_free(pa_dbusiface_stream *s); + +const char *pa_dbusiface_stream_get_path(pa_dbusiface_stream *s); + +#endif diff --git a/src/modules/dbus/module-dbus-protocol.c b/src/modules/dbus/module-dbus-protocol.c new file mode 100644 index 00000000..11064c33 --- /dev/null +++ b/src/modules/dbus/module-dbus-protocol.c @@ -0,0 +1,607 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulse/mainloop-api.h> +#include <pulse/timeval.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/client.h> +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/idxset.h> +#include <pulsecore/macro.h> +#include <pulsecore/modargs.h> +#include <pulsecore/module.h> +#include <pulsecore/protocol-dbus.h> + +#include "iface-client.h" +#include "iface-core.h" + +#include "module-dbus-protocol-symdef.h" + +PA_MODULE_DESCRIPTION("D-Bus interface"); +PA_MODULE_USAGE( + "access=local|remote|local,remote " + "tcp_port=<port number>"); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_AUTHOR("Tanu Kaskinen"); +PA_MODULE_VERSION(PACKAGE_VERSION); + +#define CLEANUP_INTERVAL 10 /* seconds */ + +enum server_type { + SERVER_TYPE_LOCAL, + SERVER_TYPE_TCP +}; + +struct server; +struct connection; + +struct userdata { + pa_module *module; + pa_bool_t local_access; + pa_bool_t remote_access; + uint32_t tcp_port; + + struct server *local_server; + struct server *tcp_server; + + pa_idxset *connections; + + pa_time_event *cleanup_event; + + pa_dbus_protocol *dbus_protocol; + pa_dbusiface_core *core_iface; +}; + +struct server { + struct userdata *userdata; + enum server_type type; + DBusServer *dbus_server; +}; + +struct connection { + struct server *server; + pa_dbus_wrap_connection *wrap_conn; + pa_client *client; +}; + +static const char* const valid_modargs[] = { + "access", + "tcp_port", + NULL +}; + +static void connection_free(struct connection *c) { + pa_assert(c); + + pa_assert_se(pa_dbus_protocol_unregister_connection(c->server->userdata->dbus_protocol, pa_dbus_wrap_connection_get(c->wrap_conn)) >= 0); + + pa_client_free(c->client); + pa_assert_se(pa_idxset_remove_by_data(c->server->userdata->connections, c, NULL)); + pa_dbus_wrap_connection_free(c->wrap_conn); + pa_xfree(c); +} + +/* Called from pa_client_kill(). */ +static void client_kill_cb(pa_client *c) { + struct connection *conn; + + pa_assert(c); + pa_assert(c->userdata); + + conn = c->userdata; + connection_free(conn); + c->userdata = NULL; + + pa_log_info("Connection killed."); +} + +/* Called from pa_client_send_event(). */ +static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *data) { + struct connection *conn = NULL; + DBusMessage *signal = NULL; + DBusMessageIter msg_iter; + + pa_assert(c); + pa_assert(name); + pa_assert(data); + pa_assert(c->userdata); + + conn = c->userdata; + + pa_assert_se(signal = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c), + PA_DBUSIFACE_CLIENT_INTERFACE, + "ClientEvent")); + dbus_message_iter_init_append(signal, &msg_iter); + pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name)); + pa_dbus_append_proplist(&msg_iter, data); + + pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal, NULL)); + dbus_message_unref(signal); +} + +/* Called by D-Bus at the authentication phase. */ +static dbus_bool_t user_check_cb(DBusConnection *connection, unsigned long uid, void *data) { + pa_log_debug("Allowing connection by user %lu.", uid); + + return TRUE; +} + +/* Called by D-Bus when a new client connection is received. */ +static void connection_new_cb(DBusServer *dbus_server, DBusConnection *new_connection, void *data) { + struct server *s = data; + struct connection *c; + pa_client_new_data new_data; + pa_client *client; + + pa_assert(new_connection); + pa_assert(s); + + pa_client_new_data_init(&new_data); + new_data.module = s->userdata->module; + new_data.driver = __FILE__; + pa_proplist_sets(new_data.proplist, PA_PROP_APPLICATION_NAME, "D-Bus client"); + client = pa_client_new(s->userdata->module->core, &new_data); + pa_client_new_data_done(&new_data); + + if (!client) { + dbus_connection_close(new_connection); + return; + } + + if (s->type == SERVER_TYPE_TCP || s->userdata->module->core->server_type == PA_SERVER_TYPE_SYSTEM) { + /* FIXME: Here we allow anyone from anywhere to access the server, + * anonymously. Access control should be configurable. */ + dbus_connection_set_unix_user_function(new_connection, user_check_cb, NULL, NULL); + dbus_connection_set_allow_anonymous(new_connection, TRUE); + } + + c = pa_xnew(struct connection, 1); + c->server = s; + c->wrap_conn = pa_dbus_wrap_connection_new_from_existing(s->userdata->module->core->mainloop, TRUE, new_connection); + c->client = client; + + c->client->kill = client_kill_cb; + c->client->send_event = client_send_event_cb; + c->client->userdata = c; + + pa_idxset_put(s->userdata->connections, c, NULL); + + pa_assert_se(pa_dbus_protocol_register_connection(s->userdata->dbus_protocol, new_connection, c->client) >= 0); +} + +/* Called by PA mainloop when a D-Bus fd watch event needs handling. */ +static void io_event_cb(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) { + unsigned int flags = 0; + DBusWatch *watch = userdata; + +#if HAVE_DBUS_WATCH_GET_UNIX_FD + pa_assert(fd == dbus_watch_get_unix_fd(watch)); +#else + pa_assert(fd == dbus_watch_get_fd(watch)); +#endif + + if (!dbus_watch_get_enabled(watch)) { + pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd); + return; + } + + if (events & PA_IO_EVENT_INPUT) + flags |= DBUS_WATCH_READABLE; + if (events & PA_IO_EVENT_OUTPUT) + flags |= DBUS_WATCH_WRITABLE; + if (events & PA_IO_EVENT_HANGUP) + flags |= DBUS_WATCH_HANGUP; + if (events & PA_IO_EVENT_ERROR) + flags |= DBUS_WATCH_ERROR; + + dbus_watch_handle(watch, flags); +} + +/* Called by PA mainloop when a D-Bus timer event needs handling. */ +static void time_event_cb(pa_mainloop_api *mainloop, pa_time_event* e, const struct timeval *tv, void *userdata) { + DBusTimeout *timeout = userdata; + + if (dbus_timeout_get_enabled(timeout)) { + struct timeval next = *tv; + dbus_timeout_handle(timeout); + + /* restart it for the next scheduled time */ + pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); + mainloop->time_restart(e, &next); + } +} + +/* Translates D-Bus fd watch event flags to PA IO event flags. */ +static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) { + unsigned int flags; + pa_io_event_flags_t events = 0; + + pa_assert(watch); + + flags = dbus_watch_get_flags(watch); + + /* no watch flags for disabled watches */ + if (!dbus_watch_get_enabled(watch)) + return PA_IO_EVENT_NULL; + + if (flags & DBUS_WATCH_READABLE) + events |= PA_IO_EVENT_INPUT; + if (flags & DBUS_WATCH_WRITABLE) + events |= PA_IO_EVENT_OUTPUT; + + return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR; +} + +/* Called by D-Bus when a D-Bus fd watch event is added. */ +static dbus_bool_t watch_add_cb(DBusWatch *watch, void *data) { + struct server *s = data; + pa_mainloop_api *mainloop; + pa_io_event *ev; + + pa_assert(watch); + pa_assert(s); + + mainloop = s->userdata->module->core->mainloop; + + ev = mainloop->io_new( + mainloop, +#if HAVE_DBUS_WATCH_GET_UNIX_FD + dbus_watch_get_unix_fd(watch), +#else + dbus_watch_get_fd(watch), +#endif + get_watch_flags(watch), io_event_cb, watch); + + dbus_watch_set_data(watch, ev, NULL); + + return TRUE; +} + +/* Called by D-Bus when a D-Bus fd watch event is removed. */ +static void watch_remove_cb(DBusWatch *watch, void *data) { + struct server *s = data; + pa_io_event *ev; + + pa_assert(watch); + pa_assert(s); + + if ((ev = dbus_watch_get_data(watch))) + s->userdata->module->core->mainloop->io_free(ev); +} + +/* Called by D-Bus when a D-Bus fd watch event is toggled. */ +static void watch_toggled_cb(DBusWatch *watch, void *data) { + struct server *s = data; + pa_io_event *ev; + + pa_assert(watch); + pa_assert(s); + + pa_assert_se(ev = dbus_watch_get_data(watch)); + + /* get_watch_flags() checks if the watch is enabled */ + s->userdata->module->core->mainloop->io_enable(ev, get_watch_flags(watch)); +} + +/* Called by D-Bus when a D-Bus timer event is added. */ +static dbus_bool_t timeout_add_cb(DBusTimeout *timeout, void *data) { + struct server *s = data; + pa_mainloop_api *mainloop; + pa_time_event *ev; + struct timeval tv; + + pa_assert(timeout); + pa_assert(s); + + if (!dbus_timeout_get_enabled(timeout)) + return FALSE; + + mainloop = s->userdata->module->core->mainloop; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); + + ev = mainloop->time_new(mainloop, &tv, time_event_cb, timeout); + + dbus_timeout_set_data(timeout, ev, NULL); + + return TRUE; +} + +/* Called by D-Bus when a D-Bus timer event is removed. */ +static void timeout_remove_cb(DBusTimeout *timeout, void *data) { + struct server *s = data; + pa_time_event *ev; + + pa_assert(timeout); + pa_assert(s); + + if ((ev = dbus_timeout_get_data(timeout))) + s->userdata->module->core->mainloop->time_free(ev); +} + +/* Called by D-Bus when a D-Bus timer event is toggled. */ +static void timeout_toggled_cb(DBusTimeout *timeout, void *data) { + struct server *s = data; + pa_mainloop_api *mainloop; + pa_time_event *ev; + + pa_assert(timeout); + pa_assert(s); + + mainloop = s->userdata->module->core->mainloop; + + pa_assert_se(ev = dbus_timeout_get_data(timeout)); + + if (dbus_timeout_get_enabled(timeout)) { + struct timeval tv; + + pa_gettimeofday(&tv); + pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000); + + mainloop->time_restart(ev, &tv); + } else + mainloop->time_restart(ev, NULL); +} + +static void server_free(struct server *s) { + pa_assert(s); + + if (s->dbus_server) { + dbus_server_disconnect(s->dbus_server); + dbus_server_unref(s->dbus_server); + } + + pa_xfree(s); +} + +static struct server *start_server(struct userdata *u, const char *address, enum server_type type) { + /* XXX: We assume that when we unref the DBusServer instance at module + * shutdown, nobody else holds any references to it. If we stop assuming + * that someday, dbus_server_set_new_connection_function, + * dbus_server_set_watch_functions and dbus_server_set_timeout_functions + * calls should probably register free callbacks, instead of providing NULL + * as they do now. */ + + struct server *s = NULL; + DBusError error; + + pa_assert(u); + pa_assert(address); + + dbus_error_init(&error); + + s = pa_xnew0(struct server, 1); + s->userdata = u; + s->dbus_server = dbus_server_listen(address, &error); + + if (dbus_error_is_set(&error)) { + pa_log("dbus_server_listen() failed: %s: %s", error.name, error.message); + goto fail; + } + + dbus_server_set_new_connection_function(s->dbus_server, connection_new_cb, s, NULL); + + if (!dbus_server_set_watch_functions(s->dbus_server, watch_add_cb, watch_remove_cb, watch_toggled_cb, s, NULL)) { + pa_log("dbus_server_set_watch_functions() ran out of memory."); + goto fail; + } + + if (!dbus_server_set_timeout_functions(s->dbus_server, timeout_add_cb, timeout_remove_cb, timeout_toggled_cb, s, NULL)) { + pa_log("dbus_server_set_timeout_functions() ran out of memory."); + goto fail; + } + + return s; + +fail: + if (s) + server_free(s); + + dbus_error_free(&error); + + return NULL; +} + +static struct server *start_local_server(struct userdata *u) { + struct server *s = NULL; + char *address = NULL; + + pa_assert(u); + + address = pa_get_dbus_address_from_server_type(u->module->core->server_type); + + s = start_server(u, address, SERVER_TYPE_LOCAL); /* May return NULL */ + + pa_xfree(address); + + return s; +} + +static struct server *start_tcp_server(struct userdata *u) { + struct server *s = NULL; + char *address = NULL; + + pa_assert(u); + + address = pa_sprintf_malloc("tcp:host=127.0.0.1,port=%u", u->tcp_port); + + s = start_server(u, address, SERVER_TYPE_TCP); /* May return NULL */ + + pa_xfree(address); + + return s; +} + +static int get_access_arg(pa_modargs *ma, pa_bool_t *local_access, pa_bool_t *remote_access) { + const char *value = NULL; + + pa_assert(ma); + pa_assert(local_access); + pa_assert(remote_access); + + if (!(value = pa_modargs_get_value(ma, "access", NULL))) + return 0; + + if (!strcmp(value, "local")) { + *local_access = TRUE; + *remote_access = FALSE; + } else if (!strcmp(value, "remote")) { + *local_access = FALSE; + *remote_access = TRUE; + } else if (!strcmp(value, "local,remote")) { + *local_access = TRUE; + *remote_access = TRUE; + } else + return -1; + + return 0; +} + +/* Frees dead client connections. Called every CLEANUP_INTERVAL seconds. */ +static void cleanup_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata) { + struct userdata *u = userdata; + struct connection *conn = NULL; + uint32_t idx; + struct timeval cleanup_timeval; + unsigned free_count = 0; + + for (conn = pa_idxset_first(u->connections, &idx); conn; conn = pa_idxset_next(u->connections, &idx)) { + if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn))) { + connection_free(conn); + ++free_count; + } + } + + if (free_count > 0) + pa_log_debug("Freed %u dead D-Bus client connections.", free_count); + + pa_gettimeofday(&cleanup_timeval); + cleanup_timeval.tv_sec += CLEANUP_INTERVAL; + u->module->core->mainloop->time_restart(e, &cleanup_timeval); +} + +int pa__init(pa_module *m) { + struct userdata *u = NULL; + pa_modargs *ma = NULL; + struct timeval cleanup_timeval; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + m->userdata = u = pa_xnew0(struct userdata, 1); + u->module = m; + u->local_access = TRUE; + u->remote_access = FALSE; + u->tcp_port = PA_DBUS_DEFAULT_PORT; + + if (get_access_arg(ma, &u->local_access, &u->remote_access) < 0) { + pa_log("Invalid access argument: '%s'", pa_modargs_get_value(ma, "access", NULL)); + goto fail; + } + + if (pa_modargs_get_value_u32(ma, "tcp_port", &u->tcp_port) < 0 || u->tcp_port < 1 || u->tcp_port > 49150) { + pa_log("Invalid tcp_port argument: '%s'", pa_modargs_get_value(ma, "tcp_port", NULL)); + goto fail; + } + + if (u->local_access && !(u->local_server = start_local_server(u))) { + pa_log("Starting the local D-Bus server failed."); + goto fail; + } + + if (u->remote_access && !(u->tcp_server = start_tcp_server(u))) { + pa_log("Starting the D-Bus server for remote connections failed."); + goto fail; + } + + u->connections = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + + pa_gettimeofday(&cleanup_timeval); + cleanup_timeval.tv_sec += CLEANUP_INTERVAL; + u->cleanup_event = m->core->mainloop->time_new(m->core->mainloop, &cleanup_timeval, cleanup_cb, u); + + u->dbus_protocol = pa_dbus_protocol_get(m->core); + u->core_iface = pa_dbusiface_core_new(m->core); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +/* Called by idxset when the connection set is freed. */ +static void connection_free_cb(void *p, void *userdata) { + struct connection *conn = p; + + pa_assert(conn); + + connection_free(conn); +} + +void pa__done(pa_module *m) { + struct userdata *u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->core_iface) + pa_dbusiface_core_free(u->core_iface); + + if (u->cleanup_event) + m->core->mainloop->time_free(u->cleanup_event); + + if (u->connections) + pa_idxset_free(u->connections, connection_free_cb, NULL); + + if (u->tcp_server) + server_free(u->tcp_server); + + if (u->local_server) + server_free(u->local_server); + + if (u->dbus_protocol) + pa_dbus_protocol_unref(u->dbus_protocol); + + pa_xfree(u); + m->userdata = NULL; +} diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c new file mode 100644 index 00000000..bfcbfeaf --- /dev/null +++ b/src/modules/module-device-manager.c @@ -0,0 +1,1540 @@ +/*** + This file is part of PulseAudio. + + Copyright 2006-2008 Lennart Poettering + Copyright 2009 Colin Guthrie + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include <pulse/xmalloc.h> +#include <pulse/volume.h> +#include <pulse/timeval.h> +#include <pulse/util.h> +#include <pulse/rtclock.h> + +#include <pulsecore/core-error.h> +#include <pulsecore/module.h> +#include <pulsecore/core-util.h> +#include <pulsecore/modargs.h> +#include <pulsecore/log.h> +#include <pulsecore/core-subscribe.h> +#include <pulsecore/sink-input.h> +#include <pulsecore/source-output.h> +#include <pulsecore/namereg.h> +#include <pulsecore/protocol-native.h> +#include <pulsecore/pstream.h> +#include <pulsecore/pstream-util.h> +#include <pulsecore/database.h> + +#include "module-device-manager-symdef.h" + +PA_MODULE_AUTHOR("Colin Guthrie"); +PA_MODULE_DESCRIPTION("Keep track of devices (and their descriptions) both past and present and prioritise by role"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE( + "do_routing=<Automatically route streams based on a priority list (unique per-role)?> " + "on_hotplug=<When new device becomes available, recheck streams?> " + "on_rescue=<When device becomes unavailable, recheck streams?>"); + +#define SAVE_INTERVAL (10 * PA_USEC_PER_SEC) +#define DUMP_DATABASE + +static const char* const valid_modargs[] = { + "do_routing", + "on_hotplug", + "on_rescue", + NULL +}; + +#define NUM_ROLES 9 +enum { + ROLE_NONE, + ROLE_VIDEO, + ROLE_MUSIC, + ROLE_GAME, + ROLE_EVENT, + ROLE_PHONE, + ROLE_ANIMATION, + ROLE_PRODUCTION, + ROLE_A11Y, +}; + +typedef uint32_t role_indexes_t[NUM_ROLES]; + +static const char* role_names[NUM_ROLES] = { + "none", + "video", + "music", + "game", + "event", + "phone", + "animation", + "production", + "a11y", +}; + +struct userdata { + pa_core *core; + pa_module *module; + pa_subscription *subscription; + pa_hook_slot + *sink_new_hook_slot, + *source_new_hook_slot, + *sink_input_new_hook_slot, + *source_output_new_hook_slot, + *sink_put_hook_slot, + *source_put_hook_slot, + *sink_unlink_hook_slot, + *source_unlink_hook_slot, + *connection_unlink_hook_slot; + pa_time_event *save_time_event; + pa_database *database; + + pa_native_protocol *protocol; + pa_idxset *subscribed; + + pa_bool_t on_hotplug; + pa_bool_t on_rescue; + pa_bool_t do_routing; + + role_indexes_t preferred_sinks; + role_indexes_t preferred_sources; +}; + +#define ENTRY_VERSION 1 + +struct entry { + uint8_t version; + char description[PA_NAME_MAX]; + pa_bool_t user_set_description; + char icon[PA_NAME_MAX]; + role_indexes_t priority; +} PA_GCC_PACKED; + +enum { + SUBCOMMAND_TEST, + SUBCOMMAND_READ, + SUBCOMMAND_RENAME, + SUBCOMMAND_DELETE, + SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING, + SUBCOMMAND_REORDER, + SUBCOMMAND_SUBSCRIBE, + SUBCOMMAND_EVENT +}; + + +static struct entry* read_entry(struct userdata *u, const char *name) { + pa_datum key, data; + struct entry *e; + + pa_assert(u); + pa_assert(name); + + key.data = (char*) name; + key.size = strlen(name); + + pa_zero(data); + + if (!pa_database_get(u->database, &key, &data)) + goto fail; + + if (data.size != sizeof(struct entry)) { + pa_log_debug("Database contains entry for device %s of wrong size %lu != %lu. Probably due to upgrade, ignoring.", name, (unsigned long) data.size, (unsigned long) sizeof(struct entry)); + goto fail; + } + + e = (struct entry*) data.data; + + if (e->version != ENTRY_VERSION) { + pa_log_debug("Version of database entry for device %s doesn't match our version. Probably due to upgrade, ignoring.", name); + goto fail; + } + + if (!memchr(e->description, 0, sizeof(e->description))) { + pa_log_warn("Database contains entry for device %s with missing NUL byte in description", name); + goto fail; + } + + if (!memchr(e->icon, 0, sizeof(e->icon))) { + pa_log_warn("Database contains entry for device %s with missing NUL byte in icon", name); + goto fail; + } + + return e; + +fail: + + pa_datum_free(&data); + return NULL; +} + +#ifdef DUMP_DATABASE +static void dump_database_helper(struct userdata *u, uint32_t role_index, const char* human, pa_bool_t sink_mode) { + pa_assert(u); + pa_assert(human); + + if (sink_mode) { + pa_sink *s; + if (PA_INVALID_INDEX != u->preferred_sinks[role_index] && (s = pa_idxset_get_by_index(u->core->sinks, u->preferred_sinks[role_index]))) + pa_log_debug(" %s %s (%s)", human, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION)), s->name); + else + pa_log_debug(" %s No sink specified", human); + } else { + pa_source *s; + if (PA_INVALID_INDEX != u->preferred_sources[role_index] && (s = pa_idxset_get_by_index(u->core->sources, u->preferred_sources[role_index]))) + pa_log_debug(" %s %s (%s)", human, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION)), s->name); + else + pa_log_debug(" %s No source specified", human); + } +} + +static void dump_database(struct userdata *u) { + pa_datum key; + pa_bool_t done; + + pa_assert(u); + + done = !pa_database_first(u->database, &key, NULL); + + pa_log_debug("Dumping database"); + while (!done) { + char *name; + struct entry *e; + pa_datum next_key; + + done = !pa_database_next(u->database, &key, &next_key, NULL); + + name = pa_xstrndup(key.data, key.size); + + if ((e = read_entry(u, name))) { + pa_log_debug(" Got entry: %s", name); + pa_log_debug(" Description: %s", e->description); + pa_log_debug(" Priorities: None: %3u, Video: %3u, Music: %3u, Game: %3u, Event: %3u", + e->priority[ROLE_NONE], e->priority[ROLE_VIDEO], e->priority[ROLE_MUSIC], e->priority[ROLE_GAME], e->priority[ROLE_EVENT]); + pa_log_debug(" Phone: %3u, Anim: %3u, Prodtn: %3u, A11y: %3u", + e->priority[ROLE_PHONE], e->priority[ROLE_ANIMATION], e->priority[ROLE_PRODUCTION], e->priority[ROLE_A11Y]); + pa_xfree(e); + } + + pa_xfree(name); + + pa_datum_free(&key); + key = next_key; + } + + if (u->do_routing) { + pa_log_debug(" Highest priority devices per-role:"); + + pa_log_debug(" Sinks:"); + for (uint32_t role = ROLE_NONE; role < NUM_ROLES; ++role) { + char name[13]; + uint32_t len = PA_MIN(12u, strlen(role_names[role])); + strncpy(name, role_names[role], len); + for (int i = len+1; i < 12; ++i) name[i] = ' '; + name[len] = ':'; name[0] -= 32; name[12] = '\0'; + dump_database_helper(u, role, name, TRUE); + } + + pa_log_debug(" Sources:"); + for (uint32_t role = ROLE_NONE; role < NUM_ROLES; ++role) { + char name[13]; + uint32_t len = PA_MIN(12u, strlen(role_names[role])); + strncpy(name, role_names[role], len); + for (int i = len+1; i < 12; ++i) name[i] = ' '; + name[len] = ':'; name[0] -= 32; name[12] = '\0'; + dump_database_helper(u, role, name, FALSE); + } + } + + pa_log_debug("Completed database dump"); +} +#endif + +static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { + struct userdata *u = userdata; + + pa_assert(a); + pa_assert(e); + pa_assert(u); + + pa_assert(e == u->save_time_event); + u->core->mainloop->time_free(u->save_time_event); + u->save_time_event = NULL; + + pa_database_sync(u->database); + pa_log_info("Synced."); + +#ifdef DUMP_DATABASE + dump_database(u); +#endif +} + +static void notify_subscribers(struct userdata *u) { + + pa_native_connection *c; + uint32_t idx; + + pa_assert(u); + + for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) { + pa_tagstruct *t; + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION); + pa_tagstruct_putu32(t, 0); + pa_tagstruct_putu32(t, u->module->index); + pa_tagstruct_puts(t, u->module->name); + pa_tagstruct_putu32(t, SUBCOMMAND_EVENT); + + pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t); + } +} + +static void trigger_save(struct userdata *u) { + + pa_assert(u); + + notify_subscribers(u); + + if (u->save_time_event) + return; + + u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u); +} + +static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) { + + pa_assert(a); + pa_assert(b); + + if (strncmp(a->description, b->description, sizeof(a->description)) + || a->user_set_description != b->user_set_description + || strncmp(a->icon, b->icon, sizeof(a->icon))) + return FALSE; + + for (int i=0; i < NUM_ROLES; ++i) + if (a->priority[i] != b->priority[i]) + return FALSE; + + return TRUE; +} + +static char *get_name(const char *key, const char *prefix) { + char *t; + + if (strncmp(key, prefix, strlen(prefix))) + return NULL; + + t = pa_xstrdup(key + strlen(prefix)); + return t; +} + +static inline struct entry *load_or_initialize_entry(struct userdata *u, struct entry *entry, const char *name, const char *prefix) { + struct entry *old; + + pa_assert(u); + pa_assert(entry); + pa_assert(name); + pa_assert(prefix); + + if ((old = read_entry(u, name))) + *entry = *old; + else { + /* This is a new device, so make sure we write it's priority list correctly */ + role_indexes_t max_priority; + pa_datum key; + pa_bool_t done; + + pa_zero(max_priority); + done = !pa_database_first(u->database, &key, NULL); + + /* Find all existing devices with the same prefix so we calculate the current max priority for each role */ + while (!done) { + pa_datum next_key; + + done = !pa_database_next(u->database, &key, &next_key, NULL); + + if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) { + char *name2; + struct entry *e; + + name2 = pa_xstrndup(key.data, key.size); + + if ((e = read_entry(u, name2))) { + for (uint32_t i = 0; i < NUM_ROLES; ++i) { + max_priority[i] = PA_MAX(max_priority[i], e->priority[i]); + } + + pa_xfree(e); + } + + pa_xfree(name2); + } + pa_datum_free(&key); + key = next_key; + } + + /* Actually initialise our entry now we've calculated it */ + for (uint32_t i = 0; i < NUM_ROLES; ++i) { + entry->priority[i] = max_priority[i] + 1; + } + entry->user_set_description = FALSE; + } + + return old; +} + +static uint32_t get_role_index(const char* role) { + pa_assert(role); + + for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i) + if (strcmp(role, role_names[i]) == 0) + return i; + + return PA_INVALID_INDEX; +} + +static void update_highest_priority_device_indexes(struct userdata *u, const char *prefix, void *ignore_device) { + role_indexes_t *indexes, highest_priority_available; + pa_datum key; + pa_bool_t done, sink_mode; + + pa_assert(u); + pa_assert(prefix); + + sink_mode = (strcmp(prefix, "sink:") == 0); + + if (sink_mode) + indexes = &u->preferred_sinks; + else + indexes = &u->preferred_sources; + + for (uint32_t i = 0; i < NUM_ROLES; ++i) { + (*indexes)[i] = PA_INVALID_INDEX; + } + pa_zero(highest_priority_available); + + done = !pa_database_first(u->database, &key, NULL); + + /* Find all existing devices with the same prefix so we find the highest priority device for each role */ + while (!done) { + pa_datum next_key; + + done = !pa_database_next(u->database, &key, &next_key, NULL); + + if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) { + char *name, *device_name; + struct entry *e; + + name = pa_xstrndup(key.data, key.size); + device_name = get_name(name, prefix); + + if ((e = read_entry(u, name))) { + for (uint32_t i = 0; i < NUM_ROLES; ++i) { + if (!highest_priority_available[i] || e->priority[i] < highest_priority_available[i]) { + /* We've found a device with a higher priority than that we've currently got, + so see if it is currently available or not and update our list */ + uint32_t idx; + pa_bool_t found = FALSE; + + if (sink_mode) { + pa_sink *sink; + + PA_IDXSET_FOREACH(sink, u->core->sinks, idx) { + if ((pa_sink*) ignore_device == sink) + continue; + if (strcmp(sink->name, device_name) == 0) { + found = TRUE; + idx = sink->index; /* Is this needed? */ + break; + } + } + } else { + pa_source *source; + + PA_IDXSET_FOREACH(source, u->core->sources, idx) { + if ((pa_source*) ignore_device == source) + continue; + if (strcmp(source->name, device_name) == 0) { + found = TRUE; + idx = source->index; /* Is this needed? */ + break; + } + } + } + if (found) { + highest_priority_available[i] = e->priority[i]; + (*indexes)[i] = idx; + } + + } + } + + pa_xfree(e); + } + + pa_xfree(name); + pa_xfree(device_name); + } + + pa_datum_free(&key); + key = next_key; + } +} + + +static void route_sink_input(struct userdata *u, pa_sink_input *si) { + const char *role; + uint32_t role_index, device_index; + pa_sink *sink; + + pa_assert(u); + pa_assert(u->do_routing); + + if (si->save_sink) + return; + + /* Skip this if it is already in the process of being moved anyway */ + if (!si->sink) + return; + + /* It might happen that a stream and a sink are set up at the + same time, in which case we want to make sure we don't + interfere with that */ + if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si))) + return; + + if (!(role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE))) + role_index = get_role_index("none"); + else + role_index = get_role_index(role); + + if (PA_INVALID_INDEX == role_index) + return; + + device_index = u->preferred_sinks[role_index]; + if (PA_INVALID_INDEX == device_index) + return; + + if (!(sink = pa_idxset_get_by_index(u->core->sinks, device_index))) + return; + + if (si->sink != sink) + pa_sink_input_move_to(si, sink, FALSE); +} + +static pa_hook_result_t route_sink_inputs(struct userdata *u, pa_sink *ignore_sink) { + pa_sink_input *si; + uint32_t idx; + + pa_assert(u); + + if (!u->do_routing) + return PA_HOOK_OK; + + update_highest_priority_device_indexes(u, "sink:", ignore_sink); + + PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) { + route_sink_input(u, si); + } + + return PA_HOOK_OK; +} + +static void route_source_output(struct userdata *u, pa_source_output *so) { + const char *role; + uint32_t role_index, device_index; + pa_source *source; + + pa_assert(u); + pa_assert(u->do_routing); + + if (so->save_source) + return; + + if (so->direct_on_input) + return; + + /* Skip this if it is already in the process of being moved anyway */ + if (!so->source) + return; + + /* It might happen that a stream and a source are set up at the + same time, in which case we want to make sure we don't + interfere with that */ + if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so))) + return; + + if (!(role = pa_proplist_gets(so->proplist, PA_PROP_MEDIA_ROLE))) + role_index = get_role_index("none"); + else + role_index = get_role_index(role); + + if (PA_INVALID_INDEX == role_index) + return; + + device_index = u->preferred_sources[role_index]; + if (PA_INVALID_INDEX == device_index) + return; + + if (!(source = pa_idxset_get_by_index(u->core->sources, device_index))) + return; + + if (so->source != source) + pa_source_output_move_to(so, source, FALSE); +} + +static pa_hook_result_t route_source_outputs(struct userdata *u, pa_source* ignore_source) { + pa_source_output *so; + uint32_t idx; + + pa_assert(u); + + if (!u->do_routing) + return PA_HOOK_OK; + + update_highest_priority_device_indexes(u, "source:", ignore_source); + + PA_IDXSET_FOREACH(so, u->core->source_outputs, idx) { + route_source_output(u, so); + } + + return PA_HOOK_OK; +} + +static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { + struct userdata *u = userdata; + struct entry entry, *old = NULL; + char *name = NULL; + pa_datum key, data; + + pa_assert(c); + pa_assert(u); + + if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) && + t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW) && + t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE) && + + /*t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW) &&*/ + t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) && + /*t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW) &&*/ + t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE)) + return; + + pa_zero(entry); + entry.version = ENTRY_VERSION; + + if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) { + pa_sink_input *si; + + if (!u->do_routing) + return; + if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) + return; + + /* The role may change mid-stream, so we reroute */ + route_sink_input(u, si); + + return; + } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT) { + pa_source_output *so; + + if (!u->do_routing) + return; + if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) + return; + + /* The role may change mid-stream, so we reroute */ + route_source_output(u, so); + + return; + } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) { + pa_sink *sink; + + if (!(sink = pa_idxset_get_by_index(c->sinks, idx))) + return; + + name = pa_sprintf_malloc("sink:%s", sink->name); + + old = load_or_initialize_entry(u, &entry, name, "sink:"); + + if (!entry.user_set_description) + pa_strlcpy(entry.description, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)), sizeof(entry.description)); + else if (strncmp(entry.description, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)), sizeof(entry.description)) != 0) { + /* Warning: If two modules fight over the description, this could cause an infinite loop. + by changing the description here, we retrigger this subscription callback. The only thing stopping us from + looping is the fact that the string comparison will fail on the second iteration. If another module tries to manage + the description, this will fail... */ + pa_sink_set_description(sink, entry.description); + } + + pa_strlcpy(entry.icon, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME)), sizeof(entry.icon)); + + } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE) { + pa_source *source; + + pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE); + + if (!(source = pa_idxset_get_by_index(c->sources, idx))) + return; + + if (source->monitor_of) + return; + + name = pa_sprintf_malloc("source:%s", source->name); + + old = load_or_initialize_entry(u, &entry, name, "source:"); + + if (!entry.user_set_description) + pa_strlcpy(entry.description, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)), sizeof(entry.description)); + else if (strncmp(entry.description, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)), sizeof(entry.description)) != 0) { + /* Warning: If two modules fight over the description, this could cause an infinite loop. + by changing the description here, we retrigger this subscription callback. The only thing stopping us from + looping is the fact that the string comparison will fail on the second iteration. If another module tries to manage + the description, this will fail... */ + pa_source_set_description(source, entry.description); + } + + pa_strlcpy(entry.icon, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME)), sizeof(entry.icon)); + } + + pa_assert(name); + + if (old) { + + if (entries_equal(old, &entry)) { + pa_xfree(old); + pa_xfree(name); + + return; + } + + pa_xfree(old); + } + + key.data = name; + key.size = strlen(name); + + data.data = &entry; + data.size = sizeof(entry); + + pa_log_info("Storing device %s.", name); + + if (pa_database_set(u->database, &key, &data, TRUE) == 0) + trigger_save(u); + else + pa_log_warn("Could not save device");; + + pa_xfree(name); +} + +static pa_hook_result_t sink_new_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) { + char *name; + struct entry *e; + + pa_assert(c); + pa_assert(new_data); + pa_assert(u); + + name = pa_sprintf_malloc("sink:%s", new_data->name); + + if ((e = read_entry(u, name))) { + if (e->user_set_description && strncmp(e->description, pa_proplist_gets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION), sizeof(e->description)) != 0) { + pa_log_info("Restoring description for sink %s.", new_data->name); + pa_proplist_sets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION, e->description); + } + + pa_xfree(e); + } + + pa_xfree(name); + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) { + char *name; + struct entry *e; + + pa_assert(c); + pa_assert(new_data); + pa_assert(u); + + name = pa_sprintf_malloc("source:%s", new_data->name); + + if ((e = read_entry(u, name))) { + if (e->user_set_description && strncmp(e->description, pa_proplist_gets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION), sizeof(e->description)) != 0) { + /* NB, We cannot detect if we are a monitor here... this could mess things up a bit... */ + pa_log_info("Restoring description for source %s.", new_data->name); + pa_proplist_sets(new_data->proplist, PA_PROP_DEVICE_DESCRIPTION, e->description); + } + + pa_xfree(e); + } + + pa_xfree(name); + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) { + const char *role; + uint32_t role_index; + + pa_assert(c); + pa_assert(new_data); + pa_assert(u); + + if (!u->do_routing) + return PA_HOOK_OK; + + if (new_data->sink) + pa_log_debug("Not restoring device for stream because already set."); + else { + if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE))) + role_index = get_role_index("none"); + else + role_index = get_role_index(role); + + if (PA_INVALID_INDEX != role_index) { + uint32_t device_index; + + device_index = u->preferred_sinks[role_index]; + if (PA_INVALID_INDEX != device_index) { + pa_sink *sink; + + if ((sink = pa_idxset_get_by_index(u->core->sinks, device_index))) { + new_data->sink = sink; + new_data->save_sink = FALSE; + } + } + } + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) { + const char *role; + uint32_t role_index; + + pa_assert(c); + pa_assert(new_data); + pa_assert(u); + + if (!u->do_routing) + return PA_HOOK_OK; + + if (new_data->direct_on_input) + return PA_HOOK_OK; + + if (new_data->source) + pa_log_debug("Not restoring device for stream because already set."); + else { + if (!(role = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_ROLE))) + role_index = get_role_index("none"); + else + role_index = get_role_index(role); + + if (PA_INVALID_INDEX != role_index) { + uint32_t device_index; + + device_index = u->preferred_sources[role_index]; + if (PA_INVALID_INDEX != device_index) { + pa_source *source; + + if ((source = pa_idxset_get_by_index(u->core->sources, device_index))) { + new_data->source = source; + new_data->save_source = FALSE; + } + } + } + } + + return PA_HOOK_OK; +} + + +static pa_hook_result_t sink_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_sink *sink, struct userdata *u) { + pa_assert(c); + pa_assert(u); + pa_assert(u->core == c); + pa_assert(u->on_hotplug); + + notify_subscribers(u); + + return route_sink_inputs(u, NULL); +} + +static pa_hook_result_t source_put_hook_callback(pa_core *c, PA_GCC_UNUSED pa_source *source, struct userdata *u) { + pa_assert(c); + pa_assert(u); + pa_assert(u->core == c); + pa_assert(u->on_hotplug); + + notify_subscribers(u); + + return route_source_outputs(u, NULL); +} + +static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { + pa_assert(c); + pa_assert(sink); + pa_assert(u); + pa_assert(u->core == c); + pa_assert(u->on_rescue); + + /* There's no point in doing anything if the core is shut down anyway */ + if (c->state == PA_CORE_SHUTDOWN) + return PA_HOOK_OK; + + notify_subscribers(u); + + return route_sink_inputs(u, sink); +} + +static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { + pa_assert(c); + pa_assert(source); + pa_assert(u); + pa_assert(u->core == c); + pa_assert(u->on_rescue); + + /* There's no point in doing anything if the core is shut down anyway */ + if (c->state == PA_CORE_SHUTDOWN) + return PA_HOOK_OK; + + notify_subscribers(u); + + return route_source_outputs(u, source); +} + + +static void apply_entry(struct userdata *u, const char *name, struct entry *e) { + uint32_t idx; + char *n; + + pa_assert(u); + pa_assert(name); + pa_assert(e); + + if (!e->user_set_description) + return; + + if ((n = get_name(name, "sink:"))) { + pa_sink *s; + PA_IDXSET_FOREACH(s, u->core->sinks, idx) { + if (!pa_streq(s->name, n)) { + continue; + } + + pa_log_info("Setting description for sink %s to '%s'", s->name, e->description); + pa_sink_set_description(s, e->description); + } + pa_xfree(n); + } + else if ((n = get_name(name, "source:"))) { + pa_source *s; + PA_IDXSET_FOREACH(s, u->core->sources, idx) { + if (!pa_streq(s->name, n)) { + continue; + } + + if (s->monitor_of) { + pa_log_warn("Cowardly refusing to set the description for monitor source %s.", s->name); + continue; + } + + pa_log_info("Setting description for source %s to '%s'", s->name, e->description); + pa_source_set_description(s, e->description); + } + pa_xfree(n); + } +} + + +#define EXT_VERSION 1 + +static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) { + struct userdata *u; + uint32_t command; + pa_tagstruct *reply = NULL; + + pa_assert(p); + pa_assert(m); + pa_assert(c); + pa_assert(t); + + u = m->userdata; + + if (pa_tagstruct_getu32(t, &command) < 0) + goto fail; + + reply = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); + pa_tagstruct_putu32(reply, tag); + + switch (command) { + case SUBCOMMAND_TEST: { + if (!pa_tagstruct_eof(t)) + goto fail; + + pa_tagstruct_putu32(reply, EXT_VERSION); + break; + } + + case SUBCOMMAND_READ: { + pa_datum key; + pa_bool_t done; + + if (!pa_tagstruct_eof(t)) + goto fail; + + done = !pa_database_first(u->database, &key, NULL); + + while (!done) { + pa_datum next_key; + struct entry *e; + char *name; + + done = !pa_database_next(u->database, &key, &next_key, NULL); + + name = pa_xstrndup(key.data, key.size); + pa_datum_free(&key); + + if ((e = read_entry(u, name))) { + uint32_t idx; + char *devname; + pa_bool_t available = FALSE; + + if ((devname = get_name(name, "sink:"))) { + pa_sink* s; + PA_IDXSET_FOREACH(s, u->core->sinks, idx) { + if (strcmp(s->name, devname) == 0) { + available = TRUE; + break; + } + } + pa_xfree(devname); + } else if ((devname = get_name(name, "source:"))) { + pa_source* s; + PA_IDXSET_FOREACH(s, u->core->sources, idx) { + if (strcmp(s->name, devname) == 0) { + available = TRUE; + break; + } + } + pa_xfree(devname); + } + + pa_tagstruct_puts(reply, name); + pa_tagstruct_puts(reply, e->description); + pa_tagstruct_puts(reply, e->icon); + pa_tagstruct_put_boolean(reply, available); + pa_tagstruct_putu32(reply, NUM_ROLES); + + for (uint32_t i = ROLE_NONE; i < NUM_ROLES; ++i) { + pa_tagstruct_puts(reply, role_names[i]); + pa_tagstruct_putu32(reply, e->priority[i]); + } + + pa_xfree(e); + } + + pa_xfree(name); + + key = next_key; + } + + break; + } + + case SUBCOMMAND_RENAME: { + + struct entry *e; + const char *device, *description; + + if (pa_tagstruct_gets(t, &device) < 0 || + pa_tagstruct_gets(t, &description) < 0) + goto fail; + + if (!device || !*device || !description || !*description) + goto fail; + + if ((e = read_entry(u, device))) { + pa_datum key, data; + + pa_strlcpy(e->description, description, sizeof(e->description)); + e->user_set_description = TRUE; + + key.data = (char *) device; + key.size = strlen(device); + + data.data = e; + data.size = sizeof(*e); + + if (pa_database_set(u->database, &key, &data, TRUE) == 0) { + apply_entry(u, device, e); + + trigger_save(u); + } + else + pa_log_warn("Could not save device"); + + pa_xfree(e); + } + else + pa_log_warn("Could not rename device %s, no entry in database", device); + + break; + } + + case SUBCOMMAND_DELETE: + + while (!pa_tagstruct_eof(t)) { + const char *name; + pa_datum key; + + if (pa_tagstruct_gets(t, &name) < 0) + goto fail; + + key.data = (char*) name; + key.size = strlen(name); + + /** @todo: Reindex the priorities */ + pa_database_unset(u->database, &key); + } + + trigger_save(u); + + break; + + case SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING: { + + pa_bool_t enable; + + if (pa_tagstruct_get_boolean(t, &enable) < 0) + goto fail; + + if ((u->do_routing = enable)) { + /* Update our caches */ + update_highest_priority_device_indexes(u, "sink:", NULL); + update_highest_priority_device_indexes(u, "source:", NULL); + } + + break; + } + + case SUBCOMMAND_REORDER: { + + const char *role; + struct entry *e; + uint32_t role_index, n_devices; + pa_datum key, data; + pa_bool_t done, sink_mode = TRUE; + struct device_t { uint32_t prio; char *device; }; + struct device_t *device; + struct device_t **devices; + uint32_t i, idx, offset; + pa_hashmap *h; + /*void *state;*/ + pa_bool_t first; + + if (pa_tagstruct_gets(t, &role) < 0 || + pa_tagstruct_getu32(t, &n_devices) < 0 || + n_devices < 1) + goto fail; + + if (PA_INVALID_INDEX == (role_index = get_role_index(role))) + goto fail; + + /* Cycle through the devices given and make sure they exist */ + h = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + first = TRUE; + idx = 0; + for (i = 0; i < n_devices; ++i) { + const char *s; + if (pa_tagstruct_gets(t, &s) < 0) { + while ((device = pa_hashmap_steal_first(h))) { + pa_xfree(device->device); + pa_xfree(device); + } + + pa_hashmap_free(h, NULL, NULL); + pa_log_error("Protocol error on reorder"); + goto fail; + } + + /* Ensure this is a valid entry */ + if (!(e = read_entry(u, s))) { + while ((device = pa_hashmap_steal_first(h))) { + pa_xfree(device->device); + pa_xfree(device); + } + + pa_hashmap_free(h, NULL, NULL); + pa_log_error("Client specified an unknown device in it's reorder list."); + goto fail; + } + pa_xfree(e); + + if (first) { + first = FALSE; + sink_mode = (0 == strncmp("sink:", s, 5)); + } else if ((sink_mode && 0 != strncmp("sink:", s, 5)) + || (!sink_mode && 0 != strncmp("source:", s, 7))) + { + while ((device = pa_hashmap_steal_first(h))) { + pa_xfree(device->device); + pa_xfree(device); + } + + pa_hashmap_free(h, NULL, NULL); + pa_log_error("Attempted to reorder mixed devices (sinks and sources)"); + goto fail; + } + + /* Add the device to our hashmap. If it's alredy in it, free it now and carry on */ + device = pa_xnew(struct device_t, 1); + device->device = pa_xstrdup(s); + if (pa_hashmap_put(h, device->device, device) == 0) { + device->prio = idx; + idx++; + } else { + pa_xfree(device->device); + pa_xfree(device); + } + } + + /*pa_log_debug("Hashmap contents (received from client)"); + PA_HASHMAP_FOREACH(device, h, state) { + pa_log_debug(" - %s (%d)", device->device, device->prio); + }*/ + + /* Now cycle through our list and add all the devices. + This has the effect of addign in any in our DB, + not specified in the device list (and thus will be + tacked on at the end) */ + offset = idx; + done = !pa_database_first(u->database, &key, NULL); + + while (!done && idx < 256) { + pa_datum next_key; + + done = !pa_database_next(u->database, &key, &next_key, NULL); + + device = pa_xnew(struct device_t, 1); + device->device = pa_xstrndup(key.data, key.size); + if ((sink_mode && 0 == strncmp("sink:", device->device, 5)) + || (!sink_mode && 0 == strncmp("source:", device->device, 7))) { + + /* Add the device to our hashmap. If it's alredy in it, free it now and carry on */ + if (pa_hashmap_put(h, device->device, device) == 0 + && (e = read_entry(u, device->device))) { + /* We add offset on to the existing priorirty so that when we order, the + existing entries are always lower priority than the new ones. */ + device->prio = (offset + e->priority[role_index]); + pa_xfree(e); + } + else { + pa_xfree(device->device); + pa_xfree(device); + } + } else { + pa_xfree(device->device); + pa_xfree(device); + } + + pa_datum_free(&key); + + key = next_key; + } + + /*pa_log_debug("Hashmap contents (combined with database)"); + PA_HASHMAP_FOREACH(device, h, state) { + pa_log_debug(" - %s (%d)", device->device, device->prio); + }*/ + + /* Now we put all the entries in a simple list for sorting it. */ + n_devices = pa_hashmap_size(h); + devices = pa_xnew(struct device_t *, n_devices); + idx = 0; + while ((device = pa_hashmap_steal_first(h))) { + devices[idx++] = device; + } + pa_hashmap_free(h, NULL, NULL); + + /* Simple bubble sort */ + for (i = 0; i < n_devices; ++i) { + for (uint32_t j = i; j < n_devices; ++j) { + if (devices[i]->prio > devices[j]->prio) { + struct device_t *tmp; + tmp = devices[i]; + devices[i] = devices[j]; + devices[j] = tmp; + } + } + } + + /*pa_log_debug("Sorted device list"); + for (i = 0; i < n_devices; ++i) { + pa_log_debug(" - %s (%d)", devices[i]->device, devices[i]->prio); + }*/ + + /* Go through in order and write the new entry and cleanup our own list */ + idx = 1; + first = TRUE; + for (i = 0; i < n_devices; ++i) { + if ((e = read_entry(u, devices[i]->device))) { + if (e->priority[role_index] == idx) + idx++; + else { + e->priority[role_index] = idx; + + key.data = (char *) devices[i]->device; + key.size = strlen(devices[i]->device); + + data.data = e; + data.size = sizeof(*e); + + if (pa_database_set(u->database, &key, &data, TRUE) == 0) { + first = FALSE; + idx++; + } + } + + pa_xfree(e); + } + pa_xfree(devices[i]->device); + pa_xfree(devices[i]); + } + + if (!first) { + trigger_save(u); + + if (sink_mode) + route_sink_inputs(u, NULL); + else + route_source_outputs(u, NULL); + } + + break; + } + + case SUBCOMMAND_SUBSCRIBE: { + + pa_bool_t enabled; + + if (pa_tagstruct_get_boolean(t, &enabled) < 0 || + !pa_tagstruct_eof(t)) + goto fail; + + if (enabled) + pa_idxset_put(u->subscribed, c, NULL); + else + pa_idxset_remove_by_data(u->subscribed, c, NULL); + + break; + } + + default: + goto fail; + } + + pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply); + return 0; + + fail: + + if (reply) + pa_tagstruct_free(reply); + + return -1; +} + +static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) { + pa_assert(p); + pa_assert(c); + pa_assert(u); + + pa_idxset_remove_by_data(u->subscribed, c, NULL); + return PA_HOOK_OK; +} + +int pa__init(pa_module*m) { + pa_modargs *ma = NULL; + struct userdata *u; + char *fname; + pa_sink *sink; + pa_source *source; + uint32_t idx; + pa_bool_t do_routing = FALSE, on_hotplug = TRUE, on_rescue = TRUE; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; + } + + if (pa_modargs_get_value_boolean(ma, "do_routing", &do_routing) < 0 || + pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 || + pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) { + pa_log("on_hotplug= and on_rescue= expect boolean arguments"); + goto fail; + } + + m->userdata = u = pa_xnew0(struct userdata, 1); + u->core = m->core; + u->module = m; + u->do_routing = do_routing; + u->on_hotplug = on_hotplug; + u->on_rescue = on_rescue; + u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + + u->protocol = pa_native_protocol_get(m->core); + pa_native_protocol_install_ext(u->protocol, m, extension_cb); + + u->connection_unlink_hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_CONNECTION_UNLINK], PA_HOOK_NORMAL, (pa_hook_cb_t) connection_unlink_hook_cb, u); + + u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE|PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); + + /* Used to handle device description management */ + u->sink_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_new_hook_callback, u); + u->source_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_new_hook_callback, u); + + /* The following slots are used to deal with routing */ + /* A little bit later than module-stream-restore, but before module-intended-roles */ + u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY+5, (pa_hook_cb_t) sink_input_new_hook_callback, u); + u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY+5, (pa_hook_cb_t) source_output_new_hook_callback, u); + + if (on_hotplug) { + /* A little bit later than module-stream-restore, but before module-intended-roles */ + u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_put_hook_callback, u); + u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+5, (pa_hook_cb_t) source_put_hook_callback, u); + } + + if (on_rescue) { + /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, module-rescue-streams, ... */ + u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_unlink_hook_callback, u); + u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u); + } + + if (!(fname = pa_state_path("device-manager", TRUE))) + goto fail; + + if (!(u->database = pa_database_open(fname, TRUE))) { + pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno)); + pa_xfree(fname); + goto fail; + } + + pa_log_info("Sucessfully opened database file '%s'.", fname); + pa_xfree(fname); + + /* We cycle over all the available sinks so that they are added to our database if they are not in it yet */ + PA_IDXSET_FOREACH(sink, m->core->sinks, idx) + subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u); + + PA_IDXSET_FOREACH(source, m->core->sources, idx) + subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u); + + /* Perform the routing (if it's enabled) which will update our priority list cache too */ + for (uint32_t i = 0; i < NUM_ROLES; ++i) { + u->preferred_sinks[i] = u->preferred_sources[i] = PA_INVALID_INDEX; + } + + route_sink_inputs(u, NULL); + route_source_outputs(u, NULL); + +#ifdef DUMP_DATABASE + dump_database(u); +#endif + + pa_modargs_free(ma); + return 0; + +fail: + pa__done(m); + + if (ma) + pa_modargs_free(ma); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata* u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->subscription) + pa_subscription_free(u->subscription); + + if (u->sink_new_hook_slot) + pa_hook_slot_free(u->sink_new_hook_slot); + if (u->source_new_hook_slot) + pa_hook_slot_free(u->source_new_hook_slot); + + if (u->sink_input_new_hook_slot) + pa_hook_slot_free(u->sink_input_new_hook_slot); + if (u->source_output_new_hook_slot) + pa_hook_slot_free(u->source_output_new_hook_slot); + + if (u->sink_put_hook_slot) + pa_hook_slot_free(u->sink_put_hook_slot); + if (u->source_put_hook_slot) + pa_hook_slot_free(u->source_put_hook_slot); + + if (u->sink_unlink_hook_slot) + pa_hook_slot_free(u->sink_unlink_hook_slot); + if (u->source_unlink_hook_slot) + pa_hook_slot_free(u->source_unlink_hook_slot); + + if (u->save_time_event) + u->core->mainloop->time_free(u->save_time_event); + + if (u->database) + pa_database_close(u->database); + + if (u->protocol) { + pa_native_protocol_remove_ext(u->protocol, m); + pa_native_protocol_unref(u->protocol); + } + + if (u->subscribed) + pa_idxset_free(u->subscribed, NULL, NULL); + + pa_xfree(u); +} diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c new file mode 100755 index 00000000..3a28b497 --- /dev/null +++ b/src/modules/module-equalizer-sink.c @@ -0,0 +1,2157 @@ +/*** +This file is part of PulseAudio. + +This module is based off Lennart Poettering's LADSPA sink and swaps out +LADSPA functionality for a dbus-aware STFT OLA based digital equalizer. +All new work is published under Pulseaudio's original license. +Copyright 2009 Jason Newton <nevion@gmail.com> + +Original Author: +Copyright 2004-2008 Lennart Poettering + +PulseAudio 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. + +PulseAudio is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with PulseAudio; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <float.h> +#include <math.h> +#include <fftw3.h> +#include <string.h> + +#include <pulse/xmalloc.h> +#include <pulse/i18n.h> +#include <pulse/timeval.h> + +#include <pulsecore/core-rtclock.h> +#include <pulsecore/aupdate.h> +#include <pulsecore/core-error.h> +#include <pulsecore/namereg.h> +#include <pulsecore/sink.h> +#include <pulsecore/module.h> +#include <pulsecore/core-util.h> +#include <pulsecore/modargs.h> +#include <pulsecore/log.h> +#include <pulsecore/thread.h> +#include <pulsecore/thread-mq.h> +#include <pulsecore/rtpoll.h> +#include <pulsecore/sample-util.h> +#include <pulsecore/shared.h> +#include <pulsecore/idxset.h> +#include <pulsecore/strlist.h> +#include <pulsecore/database.h> +#include <pulsecore/protocol-dbus.h> +#include <pulsecore/dbus-util.h> + +#include <stdint.h> +#include <time.h> + + +//#undef __SSE2__ +#ifdef __SSE2__ +#include <xmmintrin.h> +#include <emmintrin.h> +#endif + + + +#include "module-equalizer-sink-symdef.h" + +PA_MODULE_AUTHOR("Jason Newton"); +PA_MODULE_DESCRIPTION(_("General Purpose Equalizer")); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE(_("sink=<sink to connect to> ")); + +#define MEMBLOCKQ_MAXLENGTH (16*1024*1024) + + +struct userdata { + pa_module *module; + pa_sink *sink; + pa_sink_input *sink_input; + char *name; + + size_t channels; + size_t fft_size;//length (res) of fft + size_t window_size;/* + *sliding window size + *effectively chooses R + */ + size_t R;/* the hop size between overlapping windows + * the latency of the filter, calculated from window_size + * based on constraints of COLA and window function + */ + //for twiddling with pulseaudio + size_t overlap_size;//window_size-R + size_t samples_gathered; + size_t input_buffer_max; + //message + float *W;//windowing function (time domain) + float *work_buffer, **input, **overlap_accum; + fftwf_complex *output_window; + fftwf_plan forward_plan, inverse_plan; + //size_t samplings; + + float **Xs; + float ***Hs;//thread updatable copies of the freq response filters (magintude based) + pa_aupdate **a_H; + pa_memchunk conv_buffer; + pa_memblockq *input_q; + pa_bool_t first_iteration; + + pa_dbus_protocol *dbus_protocol; + char *dbus_path; + pa_bool_t set_default; + + pa_database *database; + char **base_profiles; +}; + +static const char* const valid_modargs[] = { + "sink_name", + "sink_properties", + "master", + "format", + "rate", + "set_default", + "channels", + "channel_map", + NULL +}; + + +#define v_size 4 +#define SINKLIST "equalized_sinklist" +#define EQDB "equalizer_db" +#define EQ_STATE_DB "equalizer-state" +#define FILTER_SIZE (u->fft_size / 2 + 1) +#define CHANNEL_PROFILE_SIZE (FILTER_SIZE + 1) +#define FILTER_STATE_SIZE (CHANNEL_PROFILE_SIZE * u->channels) +static void dbus_init(struct userdata *u); +static void dbus_done(struct userdata *u); + +static void hanning_window(float *W, size_t window_size){ + //h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2 + for(size_t i=0; i < window_size;++i){ + W[i] = (float).5*(1-cos(2*M_PI*i/(window_size+1))); + } +} + +static void fix_filter(float *H, size_t fft_size){ + //divide out the fft gain + for(size_t i = 0; i < fft_size / 2 + 1; ++i){ + H[i] /= fft_size; + } +} + +static void interpolate(float *signal, size_t length, uint32_t *xs, float *ys, size_t n_points){ + //Note that xs must be monotonically increasing! + float x_range_lower, x_range_upper, c0; + pa_assert_se(n_points>=2); + pa_assert_se(xs[0] == 0); + pa_assert_se(xs[n_points - 1] == length - 1); + for(size_t x = 0, x_range_lower_i = 0; x < length-1; ++x){ + pa_assert(x_range_lower_i < n_points-1); + x_range_lower = (float) (xs[x_range_lower_i]); + x_range_upper = (float) (xs[x_range_lower_i+1]); + pa_assert_se(x_range_lower < x_range_upper); + pa_assert_se(x >= x_range_lower); + pa_assert_se(x <= x_range_upper); + //bilinear-interpolation of coefficients specified + c0 = (x-x_range_lower)/(x_range_upper-x_range_lower); + pa_assert_se(c0 >= 0&&c0 <= 1.0); + signal[x] = ((1.0f - c0) * ys[x_range_lower_i] + c0 * ys[x_range_lower_i + 1]); + while(x >= xs[x_range_lower_i + 1]){ + x_range_lower_i++; + } + } + signal[length-1]=ys[n_points-1]; +} + +static int is_monotonic(const uint32_t *xs,size_t length){ + if(length<2){ + return 1; + } + for(size_t i = 1; i < length; ++i){ + if(xs[i]<=xs[i-1]){ + return 0; + } + } + return 1; +} + +//ensure's memory allocated is a multiple of v_size +//and aligned +static void * alloc(size_t x,size_t s){ + size_t f = PA_ROUND_UP(x*s, sizeof(float)*v_size); + float *t; + pa_assert(f >= x*s); + t = fftwf_malloc(f); + memset(t, 0, f); + return t; +} + +static void alloc_input_buffers(struct userdata *u, size_t min_buffer_length){ + if(min_buffer_length <= u->input_buffer_max){ + return; + } + pa_assert(min_buffer_length >= u->window_size); + for(size_t c = 0; c < u->channels; ++c){ + float *tmp = alloc(min_buffer_length, sizeof(float)); + if(u->input[c]){ + if(!u->first_iteration){ + memcpy(tmp, u->input[c], u->overlap_size * sizeof(float)); + } + free(u->input[c]); + } + u->input[c] = tmp; + } + u->input_buffer_max = min_buffer_length; +} + +/* Called from I/O thread context */ +static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct userdata *u = PA_SINK(o)->userdata; + + switch (code) { + + case PA_SINK_MESSAGE_GET_LATENCY: { + //size_t fs=pa_frame_size(&u->sink->sample_spec); + + /* The sink is _put() before the sink input is, so let's + * make sure we don't access it in that time. Also, the + * sink input is first shut down, the sink second. */ + if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) || + !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) { + *((pa_usec_t*) data) = 0; + return 0; + } + + *((pa_usec_t*) data) = + /* Get the latency of the master sink */ + pa_sink_get_latency_within_thread(u->sink_input->sink) + + + /* Add the latency internal to our sink input on top */ + pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec); + // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec); + //+ pa_bytes_to_usec(u->latency * fs, ss) + //+ pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss); + return 0; + } + } + + return pa_sink_process_msg(o, code, data, offset, chunk); +} + + +/* Called from main context */ +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (!PA_SINK_IS_LINKED(state) || + !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input))) + return 0; + + pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED); + return 0; +} + +/* Called from I/O thread context */ +static void sink_request_rewind_cb(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) || + !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) + return; + + /* Just hand this one over to the master sink */ + pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes+pa_memblockq_get_length(u->input_q), TRUE, FALSE, FALSE); +} + +/* Called from I/O thread context */ +static void sink_update_requested_latency_cb(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) || + !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) + return; + + /* Just hand this one over to the master sink */ + pa_sink_input_set_requested_latency_within_thread( + u->sink_input, + pa_sink_get_requested_latency_within_thread(s)); +} + +/* Called from main context */ +static void sink_set_volume_cb(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) || + !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input))) + return; + + pa_sink_input_set_volume(u->sink_input, &s->real_volume, s->save_volume, TRUE); +} + +/* Called from main context */ +static void sink_set_mute_cb(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) || + !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input))) + return; + + pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted); +} + + +//reference implementation +static void dsp_logic( + float * restrict dst,//used as a temp array too, needs to be fft_length! + float * restrict src,/*input data w/ overlap at start, + *automatically cycled in routine + */ + float * restrict overlap, + const float X,//multipliar + const float * restrict H,//The freq. magnitude scalers filter + const float * restrict W,//The windowing function + fftwf_complex * restrict output_window,//The transformed window'd src + struct userdata *u){ + //use a linear-phase sliding STFT and overlap-add method (for each channel) + //zero padd the data + memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float)); + //window the data + for(size_t j = 0; j < u->window_size; ++j){ + dst[j] = X * W[j] * src[j]; + } + //Processing is done here! + //do fft + fftwf_execute_dft_r2c(u->forward_plan, dst, output_window); + //perform filtering + for(size_t j = 0; j < FILTER_SIZE; ++j){ + u->output_window[j][0] *= H[j]; + u->output_window[j][1] *= H[j]; + } + //inverse fft + fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst); + ////debug: tests overlaping add + ////and negates ALL PREVIOUS processing + ////yields a perfect reconstruction if COLA is held + //for(size_t j = 0; j < u->window_size; ++j){ + // u->work_buffer[j] = u->W[j] * u->input[c][j]; + //} + + //overlap add and preserve overlap component from this window (linear phase) + for(size_t j = 0; j < u->overlap_size; ++j){ + u->work_buffer[j] += overlap[j]; + overlap[j] = dst[u->R + j]; + } + ////debug: tests if basic buffering works + ////shouldn't modify the signal AT ALL (beyond roundoff) + //for(size_t j = 0; j < u->window_size;++j){ + // u->work_buffer[j] = u->input[c][j]; + //} + + //preseve the needed input for the next window's overlap + memmove(src, src + u->R, + (u->samples_gathered - u->R) * sizeof(float) + ); +} + +typedef float v4sf __attribute__ ((__aligned__(v_size * sizeof(float)))); +typedef union float_vector { + float f[v_size]; + v4sf v; +#ifdef __SSE2__ + __m128 m; +#endif +} float_vector_t; + +////regardless of sse enabled, the loops in here assume +////16 byte aligned addresses and memory allocations divisible by v_size +//void dsp_logic( +// float * restrict dst,//used as a temp array too, needs to be fft_length! +// float * restrict src,/*input data w/ overlap at start, +// *automatically cycled in routine +// */ +// float * restrict overlap,//The size of the overlap +// const float X,//multipliar +// const float * restrict H,//The freq. magnitude scalers filter +// const float * restrict W,//The windowing function +// fftwf_complex * restrict output_window,//The transformed window'd src +// struct userdata *u){//Collection of constants + //float_vector_t x = {X, X, X, X}; +// const size_t window_size = PA_ROUND_UP(u->window_size,v_size); +// const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2); +// //const size_t R = PA_ROUND_UP(u->R, v_size); +// const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size); +// overlap_size = PA_ROUND_UP(u->overlap_size, v_size); +// +// //assert(u->samples_gathered >= u->R); +// //zero out the bit beyond the real overlap so we don't add garbage +// for(size_t j = overlap_size; j > u->overlap_size; --j){ +// overlap[j-1] = 0; +// } +// //use a linear-phase sliding STFT and overlap-add method +// //zero padd the data +// memset(dst + u->window_size, 0, (u->fft_size - u->window_size)*sizeof(float)); +// //window the data +// for(size_t j = 0; j < window_size; j += v_size){ +// //dst[j] = W[j]*src[j]; +// float_vector_t *d = (float_vector_t*) (dst+j); +// float_vector_t *w = (float_vector_t*) (W+j); +// float_vector_t *s = (float_vector_t*) (src+j); +//#if __SSE2__ +// d->m = _mm_mul_ps(x->m, _mm_mul_ps(w->m, s->m)); +//#else +// d->v = x->v * w->v * s->v; +//#endif +// } +// //Processing is done here! +// //do fft +// fftwf_execute_dft_r2c(u->forward_plan, dst, output_window); +// +// +// //perform filtering - purely magnitude based +// for(size_t j = 0;j < fft_h; j+=v_size/2){ +// //output_window[j][0]*=H[j]; +// //output_window[j][1]*=H[j]; +// float_vector_t *d = (float_vector_t*)(output_window+j); +// float_vector_t h; +// h.f[0] = h.f[1] = H[j]; +// h.f[2] = h.f[3] = H[j+1]; +//#if __SSE2__ +// d->m = _mm_mul_ps(d->m, h.m); +//#else +// d->v = d->v*h->v; +//#endif +// } +// //inverse fft +// fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst); +// +// ////debug: tests overlaping add +// ////and negates ALL PREVIOUS processing +// ////yields a perfect reconstruction if COLA is held +// //for(size_t j = 0; j < u->window_size; ++j){ +// // dst[j] = W[j]*src[j]; +// //} +// +// //overlap add and preserve overlap component from this window (linear phase) +// for(size_t j = 0; j < overlap_size; j+=v_size){ +// //dst[j]+=overlap[j]; +// //overlap[j]+=dst[j+R]; +// float_vector_t *d = (float_vector_t*)(dst+j); +// float_vector_t *o = (float_vector_t*)(overlap+j); +//#if __SSE2__ +// d->m = _mm_add_ps(d->m, o->m); +// o->m = ((float_vector_t*)(dst+u->R+j))->m; +//#else +// d->v = d->v+o->v; +// o->v = ((float_vector_t*)(dst+u->R+j))->v; +//#endif +// } +// //memcpy(overlap, dst+u->R, u->overlap_size*sizeof(float)); +// +// //////debug: tests if basic buffering works +// //////shouldn't modify the signal AT ALL (beyond roundoff) +// //for(size_t j = 0; j < u->window_size; ++j){ +// // dst[j] = src[j]; +// //} +// +// //preseve the needed input for the next window's overlap +// memmove(src, src + u->R, +// u->overlap_size * sizeof(float) +// ); +//} + +static void process_samples(struct userdata *u, pa_memchunk *tchunk){ + size_t fs = pa_frame_size(&(u->sink->sample_spec)); + float *dst; + unsigned a_i; + float *H, X; + size_t iterations, offset; + pa_assert(u->samples_gathered >= u->window_size); + iterations = (u->samples_gathered - u->overlap_size) / u->R; + tchunk->index = 0; + tchunk->length = iterations * u->R * fs; + tchunk->memblock = pa_memblock_new(u->sink->core->mempool, tchunk->length); + dst = ((float*) pa_memblock_acquire(tchunk->memblock)); + for(size_t iter = 0; iter < iterations; ++iter){ + offset = iter * u->R * fs; + for(size_t c = 0;c < u->channels; c++) { + a_i = pa_aupdate_read_begin(u->a_H[c]); + X = u->Xs[c][a_i]; + H = u->Hs[c][a_i]; + dsp_logic( + u->work_buffer, + u->input[c], + u->overlap_accum[c], + X, + H, + u->W, + u->output_window, + u + ); + pa_aupdate_read_end(u->a_H[c]); + if(u->first_iteration){ + /* The windowing function will make the audio ramped in, as a cheap fix we can + * undo the windowing (for non-zero window values) + */ + for(size_t i = 0; i < u->overlap_size; ++i){ + u->work_buffer[i] = u->W[i] <= FLT_EPSILON ? u->work_buffer[i] : u->work_buffer[i] / u->W[i]; + } + } + pa_sample_clamp(PA_SAMPLE_FLOAT32NE, (uint8_t *) (dst + c) + offset, fs, u->work_buffer, sizeof(float), u->R); + } + if(u->first_iteration){ + u->first_iteration = FALSE; + } + u->samples_gathered -= u->R; + } + pa_memblock_release(tchunk->memblock); +} + +static void input_buffer(struct userdata *u, pa_memchunk *in){ + size_t fs = pa_frame_size(&(u->sink->sample_spec)); + size_t samples = in->length/fs; + float *src = (float*) ((uint8_t*) pa_memblock_acquire(in->memblock) + in->index); + pa_assert(u->samples_gathered + samples <= u->input_buffer_max); + for(size_t c = 0; c < u->channels; c++) { + //buffer with an offset after the overlap from previous + //iterations + pa_assert_se( + u->input[c] + u->samples_gathered + samples <= u->input[c] + u->input_buffer_max + ); + pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c] + u->samples_gathered, sizeof(float), src + c, fs, samples); + } + u->samples_gathered += samples; + pa_memblock_release(in->memblock); +} + +/* Called from I/O thread context */ +static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { + struct userdata *u; + size_t fs, target_samples; + struct timeval start, end; + pa_memchunk tchunk; + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + pa_assert(chunk); + pa_assert(u->sink); + fs = pa_frame_size(&(u->sink->sample_spec)); + target_samples = PA_ROUND_UP(nbytes / fs, u->R); + if(u->first_iteration){ + //allocate request_size + target_samples = PA_MAX(target_samples, u->window_size); + }else{ + //allocate request_size + overlap + target_samples += u->overlap_size; + alloc_input_buffers(u, target_samples); + } + alloc_input_buffers(u, target_samples); + chunk->memblock = NULL; + + /* Hmm, process any rewind request that might be queued up */ + pa_sink_process_rewind(u->sink, 0); + + //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested); + pa_rtclock_get(&start); + do{ + size_t input_remaining = target_samples - u->samples_gathered; + pa_assert(input_remaining > 0); + while(pa_memblockq_peek(u->input_q, &tchunk) < 0){ + //pa_sink_render(u->sink, input_remaining * fs, &tchunk); + pa_sink_render_full(u->sink, input_remaining * fs, &tchunk); + pa_assert(tchunk.memblock); + pa_memblockq_push(u->input_q, &tchunk); + pa_memblock_unref(tchunk.memblock); + } + pa_assert(tchunk.memblock); + tchunk.length = PA_MIN(input_remaining * fs, tchunk.length); + pa_memblockq_drop(u->input_q, tchunk.length); + //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs); + /* copy new input */ + //pa_rtclock_get(start); + input_buffer(u, &tchunk); + //pa_rtclock_get(&end); + //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC); + pa_memblock_unref(tchunk.memblock); + }while(u->samples_gathered < target_samples); + + pa_rtclock_get(&end); + pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC); + + pa_assert(u->fft_size >= u->window_size); + pa_assert(u->R < u->window_size); + /* set the H filter */ + pa_rtclock_get(&start); + /* process a block */ + process_samples(u, chunk); + pa_rtclock_get(&end); + pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC); + + pa_assert(chunk->memblock); + //pa_log_debug("gave %ld", chunk->length/fs); + //pa_log_debug("end pop"); + return 0; +} + +/* Called from main context */ +static void sink_input_volume_changed_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_volume_changed(u->sink, &i->volume); +} + +/* Called from main context */ +static void sink_input_mute_changed_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_mute_changed(u->sink, i->muted); +} + +static void reset_filter(struct userdata *u){ + size_t fs = pa_frame_size(&u->sink->sample_spec); + size_t max_request; + u->samples_gathered = 0; + for(size_t i = 0; i < u->channels; ++i){ + memset(u->overlap_accum[i], 0, u->overlap_size * sizeof(float)); + } + u->first_iteration = TRUE; + //set buffer size to max request, no overlap copy + max_request = PA_ROUND_UP(pa_sink_input_get_max_request(u->sink_input) / fs , u->R); + max_request = PA_MAX(max_request, u->window_size); + pa_sink_set_max_request_within_thread(u->sink, max_request * fs); +} + +/* Called from I/O thread context */ +static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { + struct userdata *u; + size_t amount = 0; + + pa_log_debug("Rewind callback!"); + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + if (u->sink->thread_info.rewind_nbytes > 0) { + size_t max_rewrite; + + //max_rewrite = nbytes; + max_rewrite = nbytes + pa_memblockq_get_length(u->input_q); + //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes); + amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite); + u->sink->thread_info.rewind_nbytes = 0; + + if (amount > 0) { + //invalidate the output q + pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE); + pa_log("Resetting filter"); + reset_filter(u); + } + } + + pa_sink_process_rewind(u->sink, amount); + pa_memblockq_rewind(u->input_q, nbytes); +} + +/* Called from I/O thread context */ +static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_memblockq_set_maxrewind(u->input_q, nbytes); + pa_sink_set_max_rewind_within_thread(u->sink, nbytes); +} + +/* Called from I/O thread context */ +static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) { + struct userdata *u; + size_t fs; + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + //if(u->first_iteration){ + // return; + //} + fs = pa_frame_size(&(u->sink->sample_spec)); + pa_sink_set_max_request_within_thread(u->sink, PA_ROUND_UP(nbytes / fs, u->R) * fs); +} + +/* Called from I/O thread context */ +static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency); +} + +/* Called from I/O thread context */ +static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency); +} + +/* Called from I/O thread context */ +static void sink_input_detach_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_detach_within_thread(u->sink); + + pa_sink_set_rtpoll(u->sink, NULL); +} + +/* Called from I/O thread context */ +static void sink_input_attach_cb(pa_sink_input *i) { + struct userdata *u; + size_t fs, max_request; + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll); + pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency); + + pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency); + fs = pa_frame_size(&u->sink->sample_spec); + //set buffer size to max request, no overlap copy + max_request = PA_ROUND_UP(pa_sink_input_get_max_request(u->sink_input) / fs , u->R); + max_request = PA_MAX(max_request, u->window_size); + pa_sink_set_max_request_within_thread(u->sink, max_request * fs); + pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i)); + pa_sink_attach_within_thread(u->sink); + if(u->set_default){ + pa_log_debug("Setting default sink to %s", u->sink->name); + pa_namereg_set_default_sink(u->module->core, u->sink); + } +} + +/* Called from main context */ +static void sink_input_kill_cb(pa_sink_input *i) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + /* The order here matters! We first kill the sink input, followed + * by the sink. That means the sink callbacks must be protected + * against an unconnected sink input! */ + pa_sink_input_unlink(u->sink_input); + pa_sink_unlink(u->sink); + + pa_sink_input_unref(u->sink_input); + u->sink_input = NULL; + + pa_sink_unref(u->sink); + u->sink = NULL; + + pa_module_unload_request(u->module, TRUE); +} + +/* Called from IO thread context */ +static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + /* If we are added for the first time, ask for a rewinding so that + * we are heard right-away. */ + if (PA_SINK_INPUT_IS_LINKED(state) && + i->thread_info.state == PA_SINK_INPUT_INIT) { + pa_log_debug("Requesting rewind due to state change."); + pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE); + } +} + +static void pack(char **strs, size_t len, char **packed, size_t *length){ + size_t t_len = 0; + size_t headers = (1+len) * sizeof(uint16_t); + size_t offset = sizeof(uint16_t); + for(size_t i = 0; i < len; ++i){ + t_len += strlen(strs[i]); + } + *length = headers + t_len; + *packed = pa_xmalloc0(*length); + ((uint16_t *) *packed)[0] = (uint16_t) len; + for(size_t i = 0; i < len; ++i){ + uint16_t l = strlen(strs[i]); + *((uint16_t *)(*packed + offset)) = l; + offset += sizeof(uint16_t); + memcpy(*packed + offset, strs[i], l); + offset += l; + } +} +static void unpack(char *str, size_t length, char ***strs, size_t *len){ + size_t offset = sizeof(uint16_t); + *len = ((uint16_t *)str)[0]; + *strs = pa_xnew(char *, *len); + for(size_t i = 0; i < *len; ++i){ + size_t l = *((uint16_t *)(str+offset)); + size_t e = PA_MIN(offset + l, length) - offset; + offset = PA_MIN(offset + sizeof(uint16_t), length); + (*strs)[i] = pa_xnew(char, e + 1); + memcpy((*strs)[i], str + offset, e); + (*strs)[i][e] = '\0'; + offset += l; + } +} +static void save_profile(struct userdata *u, size_t channel, char *name){ + unsigned a_i; + const size_t profile_size = CHANNEL_PROFILE_SIZE * sizeof(float); + float *H_n, *profile; + const float *H; + pa_datum key, data; + profile = pa_xnew0(float, profile_size); + a_i = pa_aupdate_read_begin(u->a_H[channel]); + profile[0] = u->Xs[a_i][channel]; + H = u->Hs[channel][a_i]; + H_n = profile + 1; + for(size_t i = 0 ; i <= FILTER_SIZE; ++i){ + H_n[i] = H[i] * u->fft_size; + //H_n[i] = H[i]; + } + pa_aupdate_read_end(u->a_H[channel]); + key.data=name; + key.size = strlen(key.data); + data.data = profile; + data.size = profile_size; + pa_database_set(u->database, &key, &data, TRUE); + pa_database_sync(u->database); + if(u->base_profiles[channel]){ + pa_xfree(u->base_profiles[channel]); + } + u->base_profiles[channel] = pa_xstrdup(name); +} + +static void save_state(struct userdata *u){ + unsigned a_i; + const size_t filter_state_size = FILTER_STATE_SIZE * sizeof(float); + float *H_n, *state; + float *H; + pa_datum key, data; + pa_database *database; + char *dbname; + char *state_name = u->name; + char *packed; + size_t packed_length; + + pack(u->base_profiles, u->channels, &packed, &packed_length); + state = (float *) pa_xmalloc0(filter_state_size + packed_length); + + for(size_t c = 0; c < u->channels; ++c){ + a_i = pa_aupdate_read_begin(u->a_H[c]); + state[c * CHANNEL_PROFILE_SIZE] = u->Xs[a_i][c]; + H = u->Hs[c][a_i]; + H_n = state + c * CHANNEL_PROFILE_SIZE + 1; + memcpy(H_n, H, FILTER_SIZE * sizeof(float)); + pa_aupdate_read_end(u->a_H[c]); + } + memcpy(((char *)state) + filter_state_size, packed, packed_length); + pa_xfree(packed); + + key.data = state_name; + key.size = strlen(key.data); + data.data = state; + data.size = filter_state_size + packed_length; + //thread safety for 0.9.17? + pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, FALSE)); + pa_assert_se(database = pa_database_open(dbname, TRUE)); + pa_xfree(dbname); + + pa_database_set(database, &key, &data, TRUE); + pa_database_sync(database); + pa_database_close(database); + pa_xfree(state); +} + +static void remove_profile(pa_core *c, char *name){ + pa_datum key; + pa_database *database; + key.data = name; + key.size = strlen(key.data); + pa_assert_se(database = pa_shared_get(c, EQDB)); + pa_database_unset(database, &key); + pa_database_sync(database); +} + +static const char* load_profile(struct userdata *u, size_t channel, char *name){ + unsigned a_i; + pa_datum key, value; + const size_t profile_size = CHANNEL_PROFILE_SIZE * sizeof(float); + key.data = name; + key.size = strlen(key.data); + if(pa_database_get(u->database, &key, &value) != NULL){ + if(value.size == profile_size){ + float *profile = (float *) value.data; + a_i = pa_aupdate_write_begin(u->a_H[channel]); + u->Xs[channel][a_i] = profile[0]; + memcpy(u->Hs[channel][a_i], profile + 1, FILTER_SIZE * sizeof(float)); + fix_filter(u->Hs[channel][a_i], u->fft_size); + pa_aupdate_write_end(u->a_H[channel]); + pa_xfree(u->base_profiles[channel]); + u->base_profiles[channel] = pa_xstrdup(name); + }else{ + return "incompatible size"; + } + pa_datum_free(&value); + }else{ + return "profile doesn't exist"; + } + return NULL; +} + +static void load_state(struct userdata *u){ + unsigned a_i; + float *H; + pa_datum key, value; + pa_database *database; + char *dbname; + char *state_name = u->name; + pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, FALSE)); + database = pa_database_open(dbname, FALSE); + pa_xfree(dbname); + if(!database){ + pa_log("No resume state"); + return; + } + + key.data = state_name; + key.size = strlen(key.data); + + if(pa_database_get(database, &key, &value) != NULL){ + if(value.size > FILTER_STATE_SIZE * sizeof(float) + sizeof(uint16_t)){ + float *state = (float *) value.data; + size_t n_profs; + char **names; + for(size_t c = 0; c < u->channels; ++c){ + a_i = pa_aupdate_write_begin(u->a_H[c]); + H = state + c * CHANNEL_PROFILE_SIZE + 1; + u->Xs[c][a_i] = state[c * CHANNEL_PROFILE_SIZE]; + memcpy(u->Hs[c][a_i], H, FILTER_SIZE * sizeof(float)); + pa_aupdate_write_end(u->a_H[c]); + } + //unpack(((char *)value.data) + FILTER_STATE_SIZE, value.size - FILTER_STATE_SIZE, &names, &n_profs); + //n_profs = PA_MIN(n_profs, u->channels); + //for(size_t c = 0; c < n_profs; ++c){ + // pa_xfree(u->base_profiles[c]); + // u->base_profiles[c] = names[c]; + //} + //pa_xfree(names); + } + pa_datum_free(&value); + }else{ + pa_log("resume state exists but is wrong size!"); + } + pa_database_close(database); +} + +/* Called from main context */ +static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + return u->sink != dest; +} + +/* Called from main context */ +static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + if (dest) { + pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq); + pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags); + } else + pa_sink_set_asyncmsgq(u->sink, NULL); +} + +int pa__init(pa_module*m) { + struct userdata *u; + pa_sample_spec ss; + pa_channel_map map; + pa_modargs *ma; + const char *z; + pa_sink *master; + pa_sink_input_new_data sink_input_data; + pa_sink_new_data sink_data; + size_t fs; + float *H; + unsigned a_i; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments."); + goto fail; + } + + if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) { + pa_log("Master sink not found, trying default"); + master = pa_namereg_get_default_sink(m->core); + if(!master){ + pa_log("no default sink found!"); + goto fail; + } + } + + ss = master->sample_spec; + ss.format = PA_SAMPLE_FLOAT32; + map = master->channel_map; + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { + pa_log("Invalid sample format specification or channel map"); + goto fail; + } + fs = pa_frame_size(&ss); + + u = pa_xnew0(struct userdata, 1); + u->module = m; + m->userdata = u; + + u->set_default = TRUE; + pa_modargs_get_value_boolean(ma, "set_default", &u->set_default); + + u->channels = ss.channels; + u->fft_size = pow(2, ceil(log(ss.rate)/log(2)));//probably unstable near corner cases of powers of 2 + pa_log_debug("fft size: %ld", u->fft_size); + u->window_size = 15999; + u->R = (u->window_size + 1) / 2; + u->overlap_size = u->window_size - u->R; + u->samples_gathered = 0; + u->input_buffer_max = 0; + u->a_H = pa_xnew0(pa_aupdate *, u->channels); + u->Xs = pa_xnew0(float *, u->channels); + u->Hs = pa_xnew0(float **, u->channels); + for(size_t c = 0; c < u->channels; ++c){ + u->Xs[c] = pa_xnew0(float, 2); + u->Hs[c] = pa_xnew0(float *, 2); + for(size_t i = 0; i < 2; ++i){ + u->Hs[c][i] = alloc(FILTER_SIZE, sizeof(float)); + } + } + u->W = alloc(u->window_size, sizeof(float)); + u->work_buffer = alloc(u->fft_size, sizeof(float)); + memset(u->work_buffer, 0, u->fft_size*sizeof(float)); + u->input = pa_xnew0(float *, u->channels); + u->overlap_accum = pa_xnew0(float *, u->channels); + for(size_t c = 0; c < u->channels; ++c){ + u->a_H[c] = pa_aupdate_new(); + u->input[c] = NULL; + u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float)); + memset(u->overlap_accum[c], 0, u->overlap_size*sizeof(float)); + } + u->output_window = alloc((FILTER_SIZE), sizeof(fftwf_complex)); + u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE); + u->inverse_plan = fftwf_plan_dft_c2r_1d(u->fft_size, u->output_window, u->work_buffer, FFTW_ESTIMATE); + + hanning_window(u->W, u->window_size); + u->first_iteration = TRUE; + + u->base_profiles = pa_xnew0(char *, u->channels); + for(size_t c = 0; c < u->channels; ++c){ + u->base_profiles[c] = pa_xstrdup("default"); + } + + /* Create sink */ + pa_sink_new_data_init(&sink_data); + sink_data.driver = __FILE__; + sink_data.module = m; + if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) + sink_data.name = pa_sprintf_malloc("%s.equalizer", master->name); + pa_sink_new_data_set_sample_spec(&sink_data, &ss); + pa_sink_new_data_set_channel_map(&sink_data, &map); + z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION); + pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "FFT based equalizer on %s",z? z: master->name); + pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name); + pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter"); + + if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) { + pa_log("Invalid properties"); + pa_sink_new_data_done(&sink_data); + goto fail; + } + + u->sink = pa_sink_new(m->core, &sink_data, + PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME| + (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY))); + pa_sink_new_data_done(&sink_data); + + if (!u->sink) { + pa_log("Failed to create sink."); + goto fail; + } + u->name=pa_xstrdup(u->sink->name); + u->sink->parent.process_msg = sink_process_msg_cb; + u->sink->set_state = sink_set_state_cb; + u->sink->update_requested_latency = sink_update_requested_latency_cb; + u->sink->request_rewind = sink_request_rewind_cb; + u->sink->set_volume = sink_set_volume_cb; + u->sink->set_mute = sink_set_mute_cb; + u->sink->userdata = u; + u->input_q = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, &u->sink->silence); + + pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq); + //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss)); + + /* Create sink input */ + pa_sink_input_new_data_init(&sink_input_data); + sink_input_data.driver = __FILE__; + sink_input_data.module = m; + sink_input_data.sink = master; + pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream"); + pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); + pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); + pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); + + pa_sink_input_new(&u->sink_input, m->core, &sink_input_data); + pa_sink_input_new_data_done(&sink_input_data); + + if (!u->sink_input) + goto fail; + + u->sink_input->pop = sink_input_pop_cb; + u->sink_input->process_rewind = sink_input_process_rewind_cb; + u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb; + u->sink_input->update_max_request = sink_input_update_max_request_cb; + u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb; + u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb; + u->sink_input->kill = sink_input_kill_cb; + u->sink_input->attach = sink_input_attach_cb; + u->sink_input->detach = sink_input_detach_cb; + u->sink_input->state_change = sink_input_state_change_cb; + u->sink_input->may_move_to = sink_input_may_move_to_cb; + u->sink_input->moving = sink_input_moving_cb; + u->sink_input->volume_changed = sink_input_volume_changed_cb; + u->sink_input->mute_changed = sink_input_mute_changed_cb; + + u->sink_input->userdata = u; + + pa_sink_put(u->sink); + pa_sink_input_put(u->sink_input); + + pa_modargs_free(ma); + + + dbus_init(u); + + //default filter to these + for(size_t c = 0; c< u->channels; ++c){ + a_i = pa_aupdate_write_begin(u->a_H[c]); + H = u->Hs[c][a_i]; + u->Xs[c][a_i] = 1.0f; + for(size_t i = 0; i < FILTER_SIZE; ++i){ + H[i] = 1.0 / sqrtf(2.0f); + } + fix_filter(H, u->fft_size); + pa_aupdate_write_end(u->a_H[c]); + } + //load old parameters + load_state(u); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + + pa__done(m); + + return -1; +} + +int pa__get_n_used(pa_module *m) { + struct userdata *u; + + pa_assert(m); + pa_assert_se(u = m->userdata); + + return pa_sink_linked_by(u->sink); +} + +void pa__done(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + save_state(u); + + dbus_done(u); + + for(size_t c = 0; c < u->channels; ++c){ + pa_xfree(u->base_profiles[c]); + } + pa_xfree(u->base_profiles); + + /* See comments in sink_input_kill_cb() above regarding + * destruction order! */ + + if (u->sink_input) + pa_sink_input_unlink(u->sink_input); + + if (u->sink) + pa_sink_unlink(u->sink); + + if (u->sink_input) + pa_sink_input_unref(u->sink_input); + + if (u->sink) + pa_sink_unref(u->sink); + + pa_memblockq_free(u->input_q); + + fftwf_destroy_plan(u->inverse_plan); + fftwf_destroy_plan(u->forward_plan); + pa_xfree(u->output_window); + for(size_t c=0; c < u->channels; ++c){ + pa_aupdate_free(u->a_H[c]); + pa_xfree(u->overlap_accum[c]); + pa_xfree(u->input[c]); + } + pa_xfree(u->a_H); + pa_xfree(u->overlap_accum); + pa_xfree(u->input); + pa_xfree(u->work_buffer); + pa_xfree(u->W); + for(size_t c = 0; c < u->channels; ++c){ + pa_xfree(u->Xs[c]); + for(size_t i = 0; i < 2; ++i){ + pa_xfree(u->Hs[c][i]); + } + pa_xfree(u->Hs[c]); + } + pa_xfree(u->Xs); + pa_xfree(u->Hs); + + pa_xfree(u->name); + + pa_xfree(u); +} + +/* + * DBus Routines and Callbacks + */ +#define EXTNAME "org.PulseAudio.Ext.Equalizing1" +#define MANAGER_PATH "/org/pulseaudio/equalizing1" +#define MANAGER_IFACE EXTNAME ".Manager" +#define EQUALIZER_IFACE EXTNAME ".Equalizer" +static void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u); +static void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u); +static void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u); +static void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u); +static void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u); +static void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u); +enum manager_method_index { + MANAGER_METHOD_REMOVE_PROFILE, + MANAGER_METHOD_MAX +}; + +pa_dbus_arg_info remove_profile_args[]={ + {"name", "s","in"}, +}; + +static pa_dbus_method_handler manager_methods[MANAGER_METHOD_MAX]={ + [MANAGER_METHOD_REMOVE_PROFILE]{ + .method_name="RemoveProfile", + .arguments=remove_profile_args, + .n_arguments=sizeof(remove_profile_args)/sizeof(pa_dbus_arg_info), + .receive_cb=manager_handle_remove_profile} +}; + +enum manager_handler_index { + MANAGER_HANDLER_REVISION, + MANAGER_HANDLER_EQUALIZED_SINKS, + MANAGER_HANDLER_PROFILES, + MANAGER_HANDLER_MAX +}; + +static pa_dbus_property_handler manager_handlers[MANAGER_HANDLER_MAX]={ + [MANAGER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=manager_get_revision,.set_cb=NULL}, + [MANAGER_HANDLER_EQUALIZED_SINKS]={.property_name="EqualizedSinks",.type="ao",.get_cb=manager_get_sinks,.set_cb=NULL}, + [MANAGER_HANDLER_PROFILES]={.property_name="Profiles",.type="as",.get_cb=manager_get_profiles,.set_cb=NULL} +}; + +pa_dbus_arg_info sink_args[]={ + {"sink", "o", NULL} +}; + +enum manager_signal_index{ + MANAGER_SIGNAL_SINK_ADDED, + MANAGER_SIGNAL_SINK_REMOVED, + MANAGER_SIGNAL_PROFILES_CHANGED, + MANAGER_SIGNAL_MAX +}; + +static pa_dbus_signal_info manager_signals[MANAGER_SIGNAL_MAX]={ + [MANAGER_SIGNAL_SINK_ADDED]={.name="SinkAdded", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)}, + [MANAGER_SIGNAL_SINK_REMOVED]={.name="SinkRemoved", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)}, + [MANAGER_SIGNAL_PROFILES_CHANGED]={.name="ProfilesChanged", .arguments=NULL, .n_arguments=0} +}; + +static pa_dbus_interface_info manager_info={ + .name=MANAGER_IFACE, + .method_handlers=manager_methods, + .n_method_handlers=MANAGER_METHOD_MAX, + .property_handlers=manager_handlers, + .n_property_handlers=MANAGER_HANDLER_MAX, + .get_all_properties_cb=manager_get_all, + .signals=manager_signals, + .n_signals=MANAGER_SIGNAL_MAX +}; + +enum equalizer_method_index { + EQUALIZER_METHOD_FILTER_POINTS, + EQUALIZER_METHOD_SEED_FILTER, + EQUALIZER_METHOD_SAVE_PROFILE, + EQUALIZER_METHOD_LOAD_PROFILE, + EQUALIZER_METHOD_SET_FILTER, + EQUALIZER_METHOD_GET_FILTER, + EQUALIZER_METHOD_SAVE_STATE, + EQUALIZER_METHOD_GET_PROFILE_NAME, + EQUALIZER_METHOD_MAX +}; + +enum equalizer_handler_index { + EQUALIZER_HANDLER_REVISION, + EQUALIZER_HANDLER_SAMPLERATE, + EQUALIZER_HANDLER_FILTERSAMPLERATE, + EQUALIZER_HANDLER_N_COEFS, + EQUALIZER_HANDLER_N_CHANNELS, + EQUALIZER_HANDLER_MAX +}; + +pa_dbus_arg_info filter_points_args[]={ + {"channel", "u","in"}, + {"xs", "au","in"}, + {"ys", "ad","out"}, + {"preamp", "d","out"} +}; +pa_dbus_arg_info seed_filter_args[]={ + {"channel", "u","in"}, + {"xs", "au","in"}, + {"ys", "ad","in"}, + {"preamp", "d","in"} +}; + +pa_dbus_arg_info set_filter_args[]={ + {"channel", "u","in"}, + {"ys", "ad","in"}, + {"preamp", "d","in"} +}; +pa_dbus_arg_info get_filter_args[]={ + {"channel", "u","in"}, + {"ys", "ad","out"}, + {"preamp", "d","out"} +}; + +pa_dbus_arg_info save_profile_args[]={ + {"channel", "u","in"}, + {"name", "s","in"} +}; +pa_dbus_arg_info load_profile_args[]={ + {"channel", "u","in"}, + {"name", "s","in"} +}; +pa_dbus_arg_info base_profile_name_args[]={ + {"channel", "u","in"}, + {"name", "s","out"} +}; + +static pa_dbus_method_handler equalizer_methods[EQUALIZER_METHOD_MAX]={ + [EQUALIZER_METHOD_SEED_FILTER]{ + .method_name="SeedFilter", + .arguments=seed_filter_args, + .n_arguments=sizeof(seed_filter_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_seed_filter}, + [EQUALIZER_METHOD_FILTER_POINTS]{ + .method_name="FilterAtPoints", + .arguments=filter_points_args, + .n_arguments=sizeof(filter_points_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_get_filter_points}, + [EQUALIZER_METHOD_SET_FILTER]{ + .method_name="SetFilter", + .arguments=set_filter_args, + .n_arguments=sizeof(set_filter_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_set_filter}, + [EQUALIZER_METHOD_GET_FILTER]{ + .method_name="GetFilter", + .arguments=get_filter_args, + .n_arguments=sizeof(get_filter_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_get_filter}, + [EQUALIZER_METHOD_SAVE_PROFILE]{ + .method_name="SaveProfile", + .arguments=save_profile_args, + .n_arguments=sizeof(save_profile_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_save_profile}, + [EQUALIZER_METHOD_LOAD_PROFILE]{ + .method_name="LoadProfile", + .arguments=load_profile_args, + .n_arguments=sizeof(load_profile_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_load_profile}, + [EQUALIZER_METHOD_SAVE_STATE]{ + .method_name="SaveState", + .arguments=NULL, + .n_arguments=0, + .receive_cb=equalizer_handle_save_state}, + [EQUALIZER_METHOD_GET_PROFILE_NAME]{ + .method_name="BaseProfile", + .arguments=base_profile_name_args, + .n_arguments=sizeof(base_profile_name_args)/sizeof(pa_dbus_arg_info), + .receive_cb=equalizer_handle_get_profile_name} +}; + +static pa_dbus_property_handler equalizer_handlers[EQUALIZER_HANDLER_MAX]={ + [EQUALIZER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=equalizer_get_revision,.set_cb=NULL}, + [EQUALIZER_HANDLER_SAMPLERATE]{.property_name="SampleRate",.type="u",.get_cb=equalizer_get_sample_rate,.set_cb=NULL}, + [EQUALIZER_HANDLER_FILTERSAMPLERATE]{.property_name="FilterSampleRate",.type="u",.get_cb=equalizer_get_filter_rate,.set_cb=NULL}, + [EQUALIZER_HANDLER_N_COEFS]{.property_name="NFilterCoefficients",.type="u",.get_cb=equalizer_get_n_coefs,.set_cb=NULL}, + [EQUALIZER_HANDLER_N_CHANNELS]{.property_name="NChannels",.type="u",.get_cb=equalizer_get_n_channels,.set_cb=NULL}, +}; + +enum equalizer_signal_index{ + EQUALIZER_SIGNAL_FILTER_CHANGED, + EQUALIZER_SIGNAL_SINK_RECONFIGURED, + EQUALIZER_SIGNAL_MAX +}; + +static pa_dbus_signal_info equalizer_signals[EQUALIZER_SIGNAL_MAX]={ + [EQUALIZER_SIGNAL_FILTER_CHANGED]={.name="FilterChanged", .arguments=NULL, .n_arguments=0}, + [EQUALIZER_SIGNAL_SINK_RECONFIGURED]={.name="SinkReconfigured", .arguments=NULL, .n_arguments=0}, +}; + +static pa_dbus_interface_info equalizer_info={ + .name=EQUALIZER_IFACE, + .method_handlers=equalizer_methods, + .n_method_handlers=EQUALIZER_METHOD_MAX, + .property_handlers=equalizer_handlers, + .n_property_handlers=EQUALIZER_HANDLER_MAX, + .get_all_properties_cb=equalizer_get_all, + .signals=equalizer_signals, + .n_signals=EQUALIZER_SIGNAL_MAX +}; + +void dbus_init(struct userdata *u){ + uint32_t dummy; + DBusMessage *signal = NULL; + pa_idxset *sink_list = NULL; + u->dbus_protocol=pa_dbus_protocol_get(u->sink->core); + u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index); + + pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &equalizer_info, u); + sink_list = pa_shared_get(u->sink->core, SINKLIST); + u->database = pa_shared_get(u->sink->core, EQDB); + if(sink_list == NULL){ + char *dbname; + sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func); + pa_shared_set(u->sink->core, SINKLIST, sink_list); + pa_assert_se(dbname = pa_state_path("equalizer-presets", FALSE)); + pa_assert_se(u->database = pa_database_open(dbname, TRUE)); + pa_xfree(dbname); + pa_shared_set(u->sink->core, EQDB, u->database); + pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core); + pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME); + } + pa_idxset_put(sink_list, u, &dummy); + + pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_ADDED].name))); + dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID); + pa_dbus_protocol_send_signal(u->dbus_protocol, signal); + dbus_message_unref(signal); +} + +void dbus_done(struct userdata *u){ + pa_idxset *sink_list; + uint32_t dummy; + + DBusMessage *signal = NULL; + pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_REMOVED].name))); + dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID); + pa_dbus_protocol_send_signal(u->dbus_protocol, signal); + dbus_message_unref(signal); + + pa_assert_se(sink_list=pa_shared_get(u->sink->core,SINKLIST)); + pa_idxset_remove_by_data(sink_list,u,&dummy); + if(pa_idxset_size(sink_list)==0){ + pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME); + pa_dbus_protocol_remove_interface(u->dbus_protocol, MANAGER_PATH, manager_info.name); + pa_shared_remove(u->sink->core, EQDB); + pa_database_close(u->database); + pa_shared_remove(u->sink->core, SINKLIST); + pa_xfree(sink_list); + } + pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, equalizer_info.name); + pa_xfree(u->dbus_path); + pa_dbus_protocol_unref(u->dbus_protocol); +} + +void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u) { + DBusError error; + pa_core *c = (pa_core *)_u; + DBusMessage *signal = NULL; + pa_dbus_protocol *dbus_protocol; + char *name; + pa_assert(conn); + pa_assert(msg); + pa_assert(c); + dbus_error_init(&error); + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + remove_profile(c,name); + pa_dbus_send_empty_reply(conn, msg); + + pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name))); + dbus_protocol = pa_dbus_protocol_get(c); + pa_dbus_protocol_send_signal(dbus_protocol, signal); + pa_dbus_protocol_unref(dbus_protocol); + dbus_message_unref(signal); +} + +void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){ + uint32_t rev=1; + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev); +} + +static void get_sinks(pa_core *u, char ***names, unsigned *n_sinks){ + void *iter = NULL; + struct userdata *sink_u = NULL; + uint32_t dummy; + pa_idxset *sink_list; + pa_assert(u); + pa_assert(names); + pa_assert(n_sinks); + + pa_assert_se(sink_list = pa_shared_get(u, SINKLIST)); + *n_sinks = (unsigned) pa_idxset_size(sink_list); + *names = *n_sinks > 0 ? pa_xnew0(char *,*n_sinks) : NULL; + for(uint32_t i = 0; i < *n_sinks; ++i){ + sink_u = (struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy); + (*names)[i] = pa_xstrdup(sink_u->dbus_path); + } +} + +void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u){ + unsigned n; + char **names = NULL; + pa_assert(conn); + pa_assert(msg); + pa_assert(_u); + + get_sinks((pa_core *) _u, &names, &n); + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, names, n); + for(unsigned i = 0; i < n; ++i){ + pa_xfree(names[i]); + } + pa_xfree(names); +} + +static void get_profiles(pa_core *c, char ***names, unsigned *n){ + char *name; + pa_database *database; + pa_datum key, next_key; + pa_strlist *head=NULL, *iter; + pa_bool_t done; + pa_assert_se(database = pa_shared_get(c, EQDB)); + + pa_assert(c); + pa_assert(names); + pa_assert(n); + done = !pa_database_first(database, &key, NULL); + *n = 0; + while(!done){ + done = !pa_database_next(database, &key, &next_key, NULL); + name=pa_xmalloc(key.size + 1); + memcpy(name, key.data, key.size); + name[key.size] = '\0'; + pa_datum_free(&key); + head = pa_strlist_prepend(head, name); + pa_xfree(name); + key = next_key; + (*n)++; + } + (*names) = *n > 0 ? pa_xnew0(char *, *n) : NULL; + iter=head; + for(unsigned i = 0; i < *n; ++i){ + (*names)[*n - 1 - i] = pa_xstrdup(pa_strlist_data(iter)); + iter = pa_strlist_next(iter); + } + pa_strlist_free(head); +} + +void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u){ + char **names; + unsigned n; + pa_assert(conn); + pa_assert(msg); + pa_assert(_u); + + get_profiles((pa_core *)_u, &names, &n); + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, names, n); + for(unsigned i = 0; i < n; ++i){ + pa_xfree(names[i]); + } + pa_xfree(names); +} + +void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){ + pa_core *c; + char **names = NULL; + unsigned n; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter, dict_iter; + uint32_t rev; + pa_assert(conn); + pa_assert(msg); + pa_assert_se(c = _u); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + rev = 1; + pa_dbus_append_basic_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev); + + get_sinks(c, &names, &n); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter,manager_handlers[MANAGER_HANDLER_EQUALIZED_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, names, n); + for(unsigned i = 0; i < n; ++i){ + pa_xfree(names[i]); + } + pa_xfree(names); + + get_profiles(c, &names, &n); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_PROFILES].property_name, DBUS_TYPE_STRING, names, n); + for(unsigned i = 0; i < n; ++i){ + pa_xfree(names[i]); + } + pa_xfree(names); + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} + +void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u) { + struct userdata *u=(struct userdata *) _u; + DBusError error; + DBusMessage *signal = NULL; + float *ys; + uint32_t *xs, channel, r_channel; + double *_ys, preamp; + unsigned x_npoints, y_npoints, a_i; + float *H; + pa_bool_t points_good = TRUE; + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + dbus_error_init(&error); + + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints, + DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &_ys, &y_npoints, + DBUS_TYPE_DOUBLE, &preamp, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + for(size_t i = 0; i < x_npoints; ++i){ + if(xs[i] >= FILTER_SIZE){ + points_good = FALSE; + break; + } + } + if(!is_monotonic(xs, x_npoints) || !points_good){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs must be monotonic and 0<=x<=%ld", u->fft_size / 2); + dbus_error_free(&error); + return; + }else if(x_npoints != y_npoints || x_npoints < 2 || x_npoints > FILTER_SIZE ){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE); + dbus_error_free(&error); + return; + }else if(xs[0] != 0 || xs[x_npoints - 1] != u->fft_size / 2){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs[0] must be 0 and xs[-1]=fft_size/2"); + dbus_error_free(&error); + return; + } + + ys = pa_xmalloc(x_npoints * sizeof(float)); + for(uint32_t i = 0; i < x_npoints; ++i){ + ys[i] = (float) _ys[i]; + } + r_channel = channel == u->channels ? 0 : channel; + a_i = pa_aupdate_write_begin(u->a_H[r_channel]); + H = u->Hs[r_channel][a_i]; + u->Xs[r_channel][a_i] = preamp; + interpolate(H, FILTER_SIZE, xs, ys, x_npoints); + fix_filter(H, u->fft_size); + if(channel == u->channels){ + for(size_t c = 1; c < u->channels; ++c){ + unsigned b_i = pa_aupdate_write_begin(u->a_H[c]); + float *H_p = u->Hs[c][b_i]; + u->Xs[c][b_i] = preamp; + memcpy(H_p, H, FILTER_SIZE * sizeof(float)); + pa_aupdate_write_end(u->a_H[c]); + } + } + pa_aupdate_write_end(u->a_H[r_channel]); + pa_xfree(ys); + + + pa_dbus_send_empty_reply(conn, msg); + + pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name))); + pa_dbus_protocol_send_signal(u->dbus_protocol, signal); + dbus_message_unref(signal); +} + +void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u) { + struct userdata *u = (struct userdata *) _u; + uint32_t *xs, channel, r_channel; + double *ys, preamp; + unsigned x_npoints, a_i; + float *H; + pa_bool_t points_good=TRUE; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusError error; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + dbus_error_init(&error); + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + + for(size_t i = 0; i < x_npoints; ++i){ + if(xs[i] >= FILTER_SIZE){ + points_good=FALSE; + break; + } + } + + if(x_npoints > FILTER_SIZE || !points_good){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs indices/length must be <= %ld!", FILTER_SIZE); + dbus_error_free(&error); + return; + } + + r_channel = channel == u->channels ? 0 : channel; + ys = pa_xmalloc(x_npoints * sizeof(double)); + a_i = pa_aupdate_read_begin(u->a_H[r_channel]); + H = u->Hs[r_channel][a_i]; + preamp = u->Xs[r_channel][a_i]; + for(uint32_t i = 0; i < x_npoints; ++i){ + ys[i] = H[xs[i]] * u->fft_size; + } + pa_aupdate_read_end(u->a_H[r_channel]); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + dbus_message_iter_init_append(reply, &msg_iter); + + pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, ys, x_npoints); + pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); + pa_xfree(ys); +} + +static void get_filter(struct userdata *u, size_t channel, double **H_, double *preamp){ + float *H; + unsigned a_i; + size_t r_channel = channel == u->channels ? 0 : channel; + *H_ = pa_xnew0(double, FILTER_SIZE); + a_i = pa_aupdate_read_begin(u->a_H[r_channel]); + H = u->Hs[r_channel][a_i]; + for(size_t i = 0;i < FILTER_SIZE; ++i){ + (*H_)[i] = H[i] * u->fft_size; + } + *preamp = u->Xs[r_channel][a_i]; + + pa_aupdate_read_end(u->a_H[r_channel]); +} + +void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + unsigned n_coefs; + uint32_t channel; + double *H_, preamp; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusError error; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(conn); + pa_assert(msg); + + dbus_error_init(&error); + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + + n_coefs = CHANNEL_PROFILE_SIZE; + pa_assert(conn); + pa_assert(msg); + get_filter(u, channel, &H_, &preamp); + pa_assert_se((reply = dbus_message_new_method_return(msg))); + dbus_message_iter_init_append(reply, &msg_iter); + + pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, H_, n_coefs); + pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); + pa_xfree(H_); +} + +static void set_filter(struct userdata *u, size_t channel, double *H_, double preamp){ + unsigned a_i; + size_t r_channel = channel == u->channels ? 0 : channel; + float *H; + //all channels + a_i = pa_aupdate_write_begin(u->a_H[r_channel]); + u->Xs[r_channel][a_i] = (float) preamp; + H = u->Hs[r_channel][a_i]; + for(size_t i = 0; i < FILTER_SIZE; ++i){ + H[i] = (float) H_[i]; + } + fix_filter(H, u->fft_size); + if(channel == u->channels){ + for(size_t c = 1; c < u->channels; ++c){ + unsigned b_i = pa_aupdate_write_begin(u->a_H[c]); + u->Xs[c][b_i] = u->Xs[r_channel][a_i]; + memcpy(u->Hs[c][b_i], u->Hs[r_channel][a_i], FILTER_SIZE * sizeof(float)); + pa_aupdate_write_end(u->a_H[c]); + } + } + pa_aupdate_write_end(u->a_H[r_channel]); +} + +void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + double *H, preamp; + uint32_t channel; + unsigned _n_coefs; + DBusMessage *signal = NULL; + DBusError error; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(conn); + pa_assert(msg); + + dbus_error_init(&error); + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &H, &_n_coefs, + DBUS_TYPE_DOUBLE, &preamp, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + if(_n_coefs != FILTER_SIZE){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE, _n_coefs); + return; + } + set_filter(u, channel, H, preamp); + + pa_dbus_send_empty_reply(conn, msg); + + pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name))); + pa_dbus_protocol_send_signal(u->dbus_protocol, signal); + dbus_message_unref(signal); +} + +void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u) { + struct userdata *u = (struct userdata *) _u; + char *name; + uint32_t channel, r_channel; + DBusMessage *signal = NULL; + DBusError error; + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + dbus_error_init(&error); + + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + r_channel = channel == u->channels ? 0 : channel; + save_profile(u, r_channel, name); + pa_dbus_send_empty_reply(conn, msg); + + pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name))); + pa_dbus_protocol_send_signal(u->dbus_protocol, signal); + dbus_message_unref(signal); +} + +void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u) { + struct userdata *u = (struct userdata *) _u; + char *name; + DBusError error; + uint32_t channel, r_channel; + const char *err_msg = NULL; + DBusMessage *signal = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + dbus_error_init(&error); + + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + r_channel = channel == u->channels ? 0 : channel; + + err_msg = load_profile(u, r_channel, name); + if(err_msg != NULL){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "error loading profile %s: %s", name, err_msg); + dbus_error_free(&error); + return; + } + if(channel == u->channels){ + for(uint32_t c = 1; c < u->channels; ++c){ + load_profile(u, c, name); + } + } + pa_dbus_send_empty_reply(conn, msg); + + pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name))); + pa_dbus_protocol_send_signal(u->dbus_protocol, signal); + dbus_message_unref(signal); +} + +void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u) { + struct userdata *u = (struct userdata *) _u; + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + save_state(u); + pa_dbus_send_empty_reply(conn, msg); +} + +void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u = (struct userdata *) _u; + DBusError error; + uint32_t channel, r_channel; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + dbus_error_init(&error); + + if(!dbus_message_get_args(msg, &error, + DBUS_TYPE_UINT32, &channel, + DBUS_TYPE_INVALID)){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); + dbus_error_free(&error); + return; + } + if(channel > u->channels){ + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel); + dbus_error_free(&error); + return; + } + r_channel = channel == u->channels ? 0 : channel; + pa_assert(u->base_profiles[r_channel]); + pa_dbus_send_basic_value_reply(conn,msg, DBUS_TYPE_STRING, &u->base_profiles[r_channel]); +} + +void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){ + uint32_t rev=1; + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev); +} + +void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + uint32_t channels; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(conn); + pa_assert(msg); + + channels = (uint32_t) u->channels; + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &channels); +} + +void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + uint32_t n_coefs; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(conn); + pa_assert(msg); + + n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE; + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs); +} + +void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + uint32_t rate; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(conn); + pa_assert(msg); + + rate = (uint32_t) u->sink->sample_spec.rate; + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &rate); +} + +void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + uint32_t fft_size; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(conn); + pa_assert(msg); + + fft_size = (uint32_t) u->fft_size; + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &fft_size); +} + +void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){ + struct userdata *u; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter, dict_iter; + uint32_t rev, n_coefs, rate, fft_size, channels; + pa_assert_se(u = (struct userdata *) _u); + pa_assert(msg); + + rev = 1; + n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE; + rate = (uint32_t) u->sink->sample_spec.rate; + fft_size = (uint32_t) u->fft_size; + channels = (uint32_t) u->channels; + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_SAMPLERATE].property_name, DBUS_TYPE_UINT32, &rate); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_FILTERSAMPLERATE].property_name, DBUS_TYPE_UINT32, &fft_size); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_CHANNELS].property_name, DBUS_TYPE_UINT32, &channels); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + dbus_message_unref(reply); +} diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 29c3ddab..bb0182b0 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -102,7 +102,7 @@ struct userdata { static const char* const valid_modargs[] = { "source", "sink", - "latency", + "latency_msec", "format", "rate", "channels", diff --git a/src/modules/module-position-event-sounds.c b/src/modules/module-position-event-sounds.c index 7221b14f..ee4c8c88 100644 --- a/src/modules/module-position-event-sounds.c +++ b/src/modules/module-position-event-sounds.c @@ -74,7 +74,7 @@ static int parse_pos(const char *pos, double *f) { } static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *data, struct userdata *u) { - const char *hpos, *vpos, *role; + const char *hpos, *vpos, *role, *id; double f; char t[PA_CVOLUME_SNPRINT_MAX]; pa_cvolume v; @@ -87,6 +87,22 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_i if (!pa_streq(role, "event")) return PA_HOOK_OK; + if ((id = pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID))) { + + /* The test sounds should never be positioned in space, since + * they might be trigered themselves to configure the speakers + * in space, which we don't want to mess up. */ + + if (pa_startswith(id, "audio-channel-")) + return PA_HOOK_OK; + + if (pa_streq(id, "audio-volume-change")) + return PA_HOOK_OK; + + if (pa_streq(id, "audio-test-signal")) + return PA_HOOK_OK; + } + if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS))) hpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_HPOS); diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 9b6f9143..788f458b 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -2,6 +2,7 @@ This file is part of PulseAudio. Copyright 2008 Lennart Poettering + Copyright 2009 Tanu Kaskinen PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -51,6 +52,11 @@ #include <pulsecore/pstream-util.h> #include <pulsecore/database.h> +#ifdef HAVE_DBUS +#include <pulsecore/dbus-util.h> +#include <pulsecore/protocol-dbus.h> +#endif + #include "module-stream-restore-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); @@ -100,6 +106,12 @@ struct userdata { pa_native_protocol *protocol; pa_idxset *subscribed; + +#ifdef HAVE_DBUS + pa_dbus_protocol *dbus_protocol; + pa_hashmap *dbus_entries; + uint32_t next_index; /* For generating object paths for entries. */ +#endif }; #define ENTRY_VERSION 3 @@ -123,6 +135,835 @@ enum { SUBCOMMAND_EVENT }; +static struct entry *read_entry(struct userdata *u, const char *name); +static void apply_entry(struct userdata *u, const char *name, struct entry *e); +static void trigger_save(struct userdata *u); + +#ifdef HAVE_DBUS + +#define OBJECT_PATH "/org/pulseaudio/stream_restore1" +#define ENTRY_OBJECT_NAME "entry" +#define INTERFACE_STREAM_RESTORE "org.PulseAudio.Ext.StreamRestore1" +#define INTERFACE_ENTRY INTERFACE_STREAM_RESTORE ".RestoreEntry" + +#define DBUS_INTERFACE_REVISION 0 + +struct dbus_entry { + struct userdata *userdata; + + char *entry_name; + uint32_t index; + char *object_path; +}; + +static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); + +static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); + +static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata); + +enum property_handler_index { + PROPERTY_HANDLER_INTERFACE_REVISION, + PROPERTY_HANDLER_ENTRIES, + PROPERTY_HANDLER_MAX +}; + +enum entry_property_handler_index { + ENTRY_PROPERTY_HANDLER_INDEX, + ENTRY_PROPERTY_HANDLER_NAME, + ENTRY_PROPERTY_HANDLER_DEVICE, + ENTRY_PROPERTY_HANDLER_VOLUME, + ENTRY_PROPERTY_HANDLER_MUTE, + ENTRY_PROPERTY_HANDLER_MAX +}; + +static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { + [PROPERTY_HANDLER_INTERFACE_REVISION] = { .property_name = "InterfaceRevision", .type = "u", .get_cb = handle_get_interface_revision, .set_cb = NULL }, + [PROPERTY_HANDLER_ENTRIES] = { .property_name = "Entries", .type = "ao", .get_cb = handle_get_entries, .set_cb = NULL } +}; + +static pa_dbus_property_handler entry_property_handlers[ENTRY_PROPERTY_HANDLER_MAX] = { + [ENTRY_PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_entry_get_index, .set_cb = NULL }, + [ENTRY_PROPERTY_HANDLER_NAME] = { .property_name = "Name", .type = "s", .get_cb = handle_entry_get_name, .set_cb = NULL }, + [ENTRY_PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "s", .get_cb = handle_entry_get_device, .set_cb = handle_entry_set_device }, + [ENTRY_PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "a(uu)", .get_cb = handle_entry_get_volume, .set_cb = handle_entry_set_volume }, + [ENTRY_PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_entry_get_mute, .set_cb = handle_entry_set_mute } +}; + +enum method_handler_index { + METHOD_HANDLER_ADD_ENTRY, + METHOD_HANDLER_GET_ENTRY_BY_NAME, + METHOD_HANDLER_MAX +}; + +enum entry_method_handler_index { + ENTRY_METHOD_HANDLER_REMOVE, + ENTRY_METHOD_HANDLER_MAX +}; + +static pa_dbus_arg_info add_entry_args[] = { { "name", "s", "in" }, + { "device", "s", "in" }, + { "volume", "a(uu)", "in" }, + { "mute", "b", "in" }, + { "entry", "o", "out" } }; +static pa_dbus_arg_info get_entry_by_name_args[] = { { "name", "s", "in" }, { "entry", "o", "out" } }; + +static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { + [METHOD_HANDLER_ADD_ENTRY] = { + .method_name = "AddEntry", + .arguments = add_entry_args, + .n_arguments = sizeof(add_entry_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_add_entry }, + [METHOD_HANDLER_GET_ENTRY_BY_NAME] = { + .method_name = "GetEntryByName", + .arguments = get_entry_by_name_args, + .n_arguments = sizeof(get_entry_by_name_args) / sizeof(pa_dbus_arg_info), + .receive_cb = handle_get_entry_by_name } +}; + +static pa_dbus_method_handler entry_method_handlers[ENTRY_METHOD_HANDLER_MAX] = { + [ENTRY_METHOD_HANDLER_REMOVE] = { + .method_name = "Remove", + .arguments = NULL, + .n_arguments = 0, + .receive_cb = handle_entry_remove } +}; + +enum signal_index { + SIGNAL_NEW_ENTRY, + SIGNAL_ENTRY_REMOVED, + SIGNAL_MAX +}; + +enum entry_signal_index { + ENTRY_SIGNAL_DEVICE_UPDATED, + ENTRY_SIGNAL_VOLUME_UPDATED, + ENTRY_SIGNAL_MUTE_UPDATED, + ENTRY_SIGNAL_MAX +}; + +static pa_dbus_arg_info new_entry_args[] = { { "entry", "o", NULL } }; +static pa_dbus_arg_info entry_removed_args[] = { { "entry", "o", NULL } }; + +static pa_dbus_arg_info entry_device_updated_args[] = { { "device", "s", NULL } }; +static pa_dbus_arg_info entry_volume_updated_args[] = { { "volume", "a(uu)", NULL } }; +static pa_dbus_arg_info entry_mute_updated_args[] = { { "muted", "b", NULL } }; + +static pa_dbus_signal_info signals[SIGNAL_MAX] = { + [SIGNAL_NEW_ENTRY] = { .name = "NewEntry", .arguments = new_entry_args, .n_arguments = 1 }, + [SIGNAL_ENTRY_REMOVED] = { .name = "EntryRemoved", .arguments = entry_removed_args, .n_arguments = 1 } +}; + +static pa_dbus_signal_info entry_signals[ENTRY_SIGNAL_MAX] = { + [ENTRY_SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = entry_device_updated_args, .n_arguments = 1 }, + [ENTRY_SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = entry_volume_updated_args, .n_arguments = 1 }, + [ENTRY_SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = entry_mute_updated_args, .n_arguments = 1 } +}; + +static pa_dbus_interface_info stream_restore_interface_info = { + .name = INTERFACE_STREAM_RESTORE, + .method_handlers = method_handlers, + .n_method_handlers = METHOD_HANDLER_MAX, + .property_handlers = property_handlers, + .n_property_handlers = PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_get_all, + .signals = signals, + .n_signals = SIGNAL_MAX +}; + +static pa_dbus_interface_info entry_interface_info = { + .name = INTERFACE_ENTRY, + .method_handlers = entry_method_handlers, + .n_method_handlers = ENTRY_METHOD_HANDLER_MAX, + .property_handlers = entry_property_handlers, + .n_property_handlers = ENTRY_PROPERTY_HANDLER_MAX, + .get_all_properties_cb = handle_entry_get_all, + .signals = entry_signals, + .n_signals = ENTRY_SIGNAL_MAX +}; + +static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_name) { + struct dbus_entry *de; + + pa_assert(u); + pa_assert(entry_name); + pa_assert(*entry_name); + + de = pa_xnew(struct dbus_entry, 1); + de->userdata = u; + de->entry_name = pa_xstrdup(entry_name); + de->index = u->next_index++; + de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index); + + pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, u) >= 0); + + return de; +} + +static void dbus_entry_free(struct dbus_entry *de) { + pa_assert(de); + + pa_assert_se(pa_dbus_protocol_remove_interface(de->userdata->dbus_protocol, de->object_path, entry_interface_info.name) >= 0); + + pa_xfree(de->entry_name); + pa_xfree(de->object_path); +} + +/* Reads an array [(UInt32, UInt32)] from the iterator. The struct items are + * are a channel position and a volume value, respectively. The result is + * stored in the map and vol arguments. The iterator must point to a "a(uu)" + * element. If the data is invalid, an error reply is sent and a negative + * number is returned. In case of a failure we make no guarantees about the + * state of map and vol. In case of an empty array the channels field of both + * map and vol are set to 0. This function calls dbus_message_iter_next(iter) + * before returning. */ +static int get_volume_arg(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, pa_channel_map *map, pa_cvolume *vol) { + DBusMessageIter array_iter; + DBusMessageIter struct_iter; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a(uu)")); + pa_assert(map); + pa_assert(vol); + + pa_channel_map_init(map); + pa_cvolume_init(vol); + + map->channels = 0; + vol->channels = 0; + + dbus_message_iter_recurse(iter, &array_iter); + + while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) { + dbus_uint32_t chan_pos; + dbus_uint32_t chan_vol; + + dbus_message_iter_recurse(&array_iter, &struct_iter); + + dbus_message_iter_get_basic(&struct_iter, &chan_pos); + + if (chan_pos >= PA_CHANNEL_POSITION_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid channel position: %u", chan_pos); + return -1; + } + + pa_assert_se(dbus_message_iter_next(&struct_iter)); + dbus_message_iter_get_basic(&struct_iter, &chan_vol); + + if (chan_vol > PA_VOLUME_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", chan_vol); + return -1; + } + + if (map->channels < PA_CHANNELS_MAX) { + map->map[map->channels] = chan_pos; + vol->values[map->channels] = chan_vol; + } + ++map->channels; + ++vol->channels; + + dbus_message_iter_next(&array_iter); + } + + if (map->channels > PA_CHANNELS_MAX) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too many channels: %u. The maximum is %u.", map->channels, PA_CHANNELS_MAX); + return -1; + } + + dbus_message_iter_next(iter); + + return 0; +} + +static void append_volume(DBusMessageIter *iter, struct entry *e) { + DBusMessageIter array_iter; + DBusMessageIter struct_iter; + unsigned i; + + pa_assert(iter); + pa_assert(e); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "(uu)", &array_iter)); + + if (!e->volume_valid) { + pa_assert_se(dbus_message_iter_close_container(iter, &array_iter)); + return; + } + + for (i = 0; i < e->channel_map.channels; ++i) { + pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)); + + pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->channel_map.map[i])); + pa_assert_se(dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &e->volume.values[i])); + + pa_assert_se(dbus_message_iter_close_container(&array_iter, &struct_iter)); + } + + pa_assert_se(dbus_message_iter_close_container(iter, &array_iter)); +} + +static void append_volume_variant(DBusMessageIter *iter, struct entry *e) { + DBusMessageIter variant_iter; + + pa_assert(iter); + pa_assert(e); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(uu)", &variant_iter)); + + append_volume(&variant_iter, e); + + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); +} + +static void send_new_entry_signal(struct dbus_entry *entry) { + DBusMessage *signal; + + pa_assert(entry); + + pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID)); + pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal); + dbus_message_unref(signal); +} + +static void send_entry_removed_signal(struct dbus_entry *entry) { + DBusMessage *signal; + + pa_assert(entry); + + pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID)); + pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal); + dbus_message_unref(signal); +} + +static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) { + DBusMessage *signal; + const char *device; + + pa_assert(de); + pa_assert(e); + + device = e->device_valid ? e->device : ""; + + pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID)); + pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal); + dbus_message_unref(signal); +} + +static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) { + DBusMessage *signal; + DBusMessageIter msg_iter; + + pa_assert(de); + pa_assert(e); + + pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name)); + dbus_message_iter_init_append(signal, &msg_iter); + append_volume(&msg_iter, e); + pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal); + dbus_message_unref(signal); +} + +static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) { + DBusMessage *signal; + dbus_bool_t muted; + + pa_assert(de); + pa_assert(e); + + pa_assert(e->muted_valid); + + muted = e->muted; + + pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID)); + pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal); + dbus_message_unref(signal); +} + +static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) { + dbus_uint32_t interface_revision = DBUS_INTERFACE_REVISION; + + pa_assert(conn); + pa_assert(msg); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &interface_revision); +} + +/* The caller frees the array, but not the strings. */ +static const char **get_entries(struct userdata *u, unsigned *n) { + const char **entries; + unsigned i = 0; + void *state = NULL; + struct dbus_entry *de; + + pa_assert(u); + pa_assert(n); + + *n = pa_hashmap_size(u->dbus_entries); + + if (*n == 0) + return NULL; + + entries = pa_xnew(const char *, *n); + + PA_HASHMAP_FOREACH(de, u->dbus_entries, state) + entries[i++] = de->object_path; + + return entries; +} + +static void handle_get_entries(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct userdata *u = userdata; + const char **entries; + unsigned n; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + entries = get_entries(u, &n); + + pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, entries, n); + + pa_xfree(entries); +} + +static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct userdata *u = userdata; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + dbus_uint32_t interface_revision; + const char **entries; + unsigned n_entries; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + interface_revision = DBUS_INTERFACE_REVISION; + entries = get_entries(u, &n_entries); + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INTERFACE_REVISION].property_name, DBUS_TYPE_UINT32, &interface_revision); + pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ENTRIES].property_name, DBUS_TYPE_OBJECT_PATH, entries, n_entries); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(entries); +} + +static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct userdata *u = userdata; + DBusMessageIter msg_iter; + const char *name = NULL; + const char *device = NULL; + pa_channel_map map; + pa_cvolume vol; + dbus_bool_t muted = FALSE; + dbus_bool_t apply_immediately = FALSE; + pa_datum key; + pa_datum value; + struct dbus_entry *dbus_entry = NULL; + struct entry *e = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + pa_assert_se(dbus_message_iter_init(msg, &msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &name); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &device); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + if (get_volume_arg(conn, msg, &msg_iter, &map, &vol) < 0) + return; + + dbus_message_iter_get_basic(&msg_iter, &muted); + + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &apply_immediately); + + if (!*name) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "An empty string was given as the entry name."); + return; + } + + if ((dbus_entry = pa_hashmap_get(u->dbus_entries, name))) { + pa_bool_t mute_updated = FALSE; + pa_bool_t volume_updated = FALSE; + pa_bool_t device_updated = FALSE; + + pa_assert_se(e = read_entry(u, name)); + mute_updated = e->muted != muted; + e->muted = muted; + e->muted_valid = TRUE; + + volume_updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol); + e->volume = vol; + e->channel_map = map; + e->volume_valid = !!map.channels; + + device_updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device); + pa_strlcpy(e->device, device, sizeof(e->device)); + e->device_valid = !!device[0]; + + if (mute_updated) + send_mute_updated_signal(dbus_entry, e); + if (volume_updated) + send_volume_updated_signal(dbus_entry, e); + if (device_updated) + send_device_updated_signal(dbus_entry, e); + + } else { + dbus_entry = dbus_entry_new(u, name); + pa_assert(pa_hashmap_put(u->dbus_entries, dbus_entry->entry_name, dbus_entry) >= 0); + + e->muted_valid = TRUE; + e->volume_valid = !!map.channels; + e->device_valid = !!device[0]; + e->muted = muted; + e->volume = vol; + e->channel_map = map; + pa_strlcpy(e->device, device, sizeof(e->device)); + + send_new_entry_signal(dbus_entry); + } + + key.data = (char *) name; + key.size = strlen(name); + + value.data = e; + value.size = sizeof(struct entry); + + pa_assert_se(pa_database_set(u->database, &key, &value, TRUE) == 0); + if (apply_immediately) + apply_entry(u, name, e); + + trigger_save(u); + + pa_dbus_send_empty_reply(conn, msg); + + pa_xfree(e); +} + +static void handle_get_entry_by_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct userdata *u = userdata; + const char *name; + struct dbus_entry *de; + + pa_assert(conn); + pa_assert(msg); + pa_assert(u); + + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)); + + if (!(de = pa_hashmap_get(u->dbus_entries, name))) { + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "No such stream restore entry."); + return; + } + + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &de->object_path); +} + +static void handle_entry_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &de->index); +} + +static void handle_entry_get_name(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &de->entry_name); +} + +static void handle_entry_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + struct entry *e; + const char *device; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + device = e->device_valid ? e->device : ""; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &device); + + pa_xfree(e); +} + +static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + struct dbus_entry *de = userdata; + const char *device; + struct entry *e; + pa_bool_t updated; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(de); + + dbus_message_iter_get_basic(iter, &device); + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + updated = (e->device_valid != !!device[0]) || !pa_streq(e->device, device); + + if (updated) { + pa_datum key; + pa_datum value; + + pa_strlcpy(e->device, device, sizeof(e->device)); + e->device_valid = !!device[0]; + + key.data = de->entry_name; + key.size = strlen(de->entry_name); + value.data = e; + value.size = sizeof(struct entry); + pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0); + + send_device_updated_signal(de, e); + trigger_save(de->userdata); + } + + pa_dbus_send_empty_reply(conn, msg); + + pa_xfree(e); +} + +static void handle_entry_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + DBusMessage *reply; + DBusMessageIter msg_iter; + struct entry *e; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + pa_assert_se(reply = dbus_message_new_method_return(msg)); + + dbus_message_iter_init_append(reply, &msg_iter); + append_volume_variant(&msg_iter, e); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + pa_xfree(e); +} + +static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + struct dbus_entry *de = userdata; + pa_channel_map map; + pa_cvolume vol; + struct entry *e = NULL; + pa_bool_t updated = FALSE; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(de); + + if (get_volume_arg(conn, msg, iter, &map, &vol) < 0) + return; + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + updated = (e->volume_valid != !!map.channels) || !pa_cvolume_equal(&e->volume, &vol); + + if (updated) { + pa_datum key; + pa_datum value; + + e->volume = vol; + e->channel_map = map; + e->volume_valid = !!map.channels; + + key.data = de->entry_name; + key.size = strlen(de->entry_name); + value.data = e; + value.size = sizeof(struct entry); + pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0); + + send_volume_updated_signal(de, e); + trigger_save(de->userdata); + } + + pa_dbus_send_empty_reply(conn, msg); + + pa_xfree(e); +} + +static void handle_entry_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + struct entry *e; + dbus_bool_t mute; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + mute = e->muted_valid ? e->muted : FALSE; + + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &mute); + + pa_xfree(e); +} + +static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { + struct dbus_entry *de = userdata; + dbus_bool_t mute; + struct entry *e; + pa_bool_t updated; + + pa_assert(conn); + pa_assert(msg); + pa_assert(iter); + pa_assert(de); + + dbus_message_iter_get_basic(iter, &mute); + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + updated = !e->muted_valid || e->muted != mute; + + if (updated) { + pa_datum key; + pa_datum value; + + e->muted = mute; + e->muted_valid = TRUE; + + key.data = de->entry_name; + key.size = strlen(de->entry_name); + value.data = e; + value.size = sizeof(struct entry); + pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0); + + send_mute_updated_signal(de, e); + trigger_save(de->userdata); + } + + pa_dbus_send_empty_reply(conn, msg); + + pa_xfree(e); +} + +static void handle_entry_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + struct entry *e; + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + const char *device; + dbus_bool_t mute; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + pa_assert_se(e = read_entry(de->userdata, de->entry_name)); + + device = e->device_valid ? e->device : ""; + mute = e->muted_valid ? e->muted : FALSE; + + pa_assert_se((reply = dbus_message_new_method_return(msg))); + + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &de->index); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_NAME].property_name, DBUS_TYPE_STRING, &de->entry_name); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_STRING, &device); + + pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &entry_property_handlers[ENTRY_PROPERTY_HANDLER_VOLUME].property_name)); + append_volume_variant(&dict_entry_iter, e); + + pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)); + + pa_dbus_append_basic_variant_dict_entry(&dict_iter, entry_property_handlers[ENTRY_PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &mute); + + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + + pa_assert_se(dbus_connection_send(conn, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(e); +} + +static void handle_entry_remove(DBusConnection *conn, DBusMessage *msg, void *userdata) { + struct dbus_entry *de = userdata; + pa_datum key; + + pa_assert(conn); + pa_assert(msg); + pa_assert(de); + + key.data = de->entry_name; + key.size = strlen(de->entry_name); + + pa_assert_se(pa_database_unset(de->userdata->database, &key) == 0); + + send_entry_removed_signal(de); + trigger_save(de->userdata); + + pa_assert_se(pa_hashmap_remove(de->userdata->dbus_entries, de->entry_name)); + dbus_entry_free(de); + + pa_dbus_send_empty_reply(conn, msg); +} + +#endif /* HAVE_DBUS */ + static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { struct userdata *u = userdata; @@ -163,7 +1004,7 @@ static char *get_name(pa_proplist *p, const char *prefix) { return t; } -static struct entry* read_entry(struct userdata *u, const char *name) { +static struct entry *read_entry(struct userdata *u, const char *name) { pa_datum key, data; struct entry *e; @@ -281,10 +1122,21 @@ static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) { static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; - struct entry entry, *old; - char *name; + struct entry entry, *old = NULL; + char *name = NULL; pa_datum key, data; + /* These are only used when D-Bus is enabled, but in order to reduce ifdef + * clutter these are defined here unconditionally. */ + pa_bool_t created_new_entry = TRUE; + pa_bool_t device_updated = FALSE; + pa_bool_t volume_updated = FALSE; + pa_bool_t mute_updated = FALSE; + +#ifdef HAVE_DBUS + struct dbus_entry *de = NULL; +#endif + pa_assert(c); pa_assert(u); @@ -306,24 +1158,34 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(name = get_name(sink_input->proplist, "sink-input"))) return; - if ((old = read_entry(u, name))) + if ((old = read_entry(u, name))) { entry = *old; + created_new_entry = FALSE; + } if (sink_input->save_volume) { entry.channel_map = sink_input->channel_map; pa_sink_input_get_volume(sink_input, &entry.volume, FALSE); entry.volume_valid = TRUE; + + volume_updated = !created_new_entry + && (!old->volume_valid + || !pa_channel_map_equal(&entry.channel_map, &old->channel_map) + || !pa_cvolume_equal(&entry.volume, &old->volume)); } if (sink_input->save_muted) { entry.muted = pa_sink_input_get_mute(sink_input); entry.muted_valid = TRUE; + + mute_updated = !created_new_entry && (!old->muted_valid || entry.muted != old->muted); } if (sink_input->save_sink) { pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device)); entry.device_valid = TRUE; + device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device)); if (sink_input->sink->card) { pa_strlcpy(entry.card, sink_input->sink->card->name, sizeof(entry.card)); entry.card_valid = TRUE; @@ -341,13 +1203,17 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(name = get_name(source_output->proplist, "source-output"))) return; - if ((old = read_entry(u, name))) + if ((old = read_entry(u, name))) { entry = *old; + created_new_entry = FALSE; + } if (source_output->save_source) { pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device)); entry.device_valid = source_output->save_source; + device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device)); + if (source_output->source->card) { pa_strlcpy(entry.card, source_output->source->card->name, sizeof(entry.card)); entry.card_valid = TRUE; @@ -376,6 +1242,23 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_database_set(u->database, &key, &data, TRUE); +#ifdef HAVE_DBUS + if (created_new_entry) { + de = dbus_entry_new(u, name); + pa_hashmap_put(u->dbus_entries, de->entry_name, de); + send_new_entry_signal(de); + } else { + pa_assert((de = pa_hashmap_get(u->dbus_entries, name))); + + if (device_updated) + send_device_updated_signal(de, &entry); + if (volume_updated) + send_volume_updated_signal(de, &entry); + if (mute_updated) + send_mute_updated_signal(de, &entry); + } +#endif + pa_xfree(name); trigger_save(u); @@ -889,14 +1772,27 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio mode != PA_UPDATE_SET) goto fail; - if (mode == PA_UPDATE_SET) + if (mode == PA_UPDATE_SET) { +#ifdef HAVE_DBUS + struct dbus_entry *de; + void *state = NULL; + + PA_HASHMAP_FOREACH(de, u->dbus_entries, state) { + send_entry_removed_signal(de); + dbus_entry_free(pa_hashmap_remove(u->dbus_entries, de->entry_name)); + } +#endif pa_database_clear(u->database); + } while (!pa_tagstruct_eof(t)) { const char *name, *device; pa_bool_t muted; struct entry entry; pa_datum key, data; +#ifdef HAVE_DBUS + struct entry *old; +#endif pa_zero(entry); entry.version = ENTRY_VERSION; @@ -928,6 +1824,10 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio !pa_namereg_is_valid_name(entry.device)) goto fail; +#ifdef HAVE_DBUS + old = read_entry(u, name); +#endif + key.data = (char*) name; key.size = strlen(name); @@ -938,9 +1838,40 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)), name); - if (pa_database_set(u->database, &key, &data, mode == PA_UPDATE_REPLACE) == 0) + if (pa_database_set(u->database, &key, &data, mode == PA_UPDATE_REPLACE) == 0) { +#ifdef HAVE_DBUS + struct dbus_entry *de; + + if (old) { + pa_assert_se((de = pa_hashmap_get(u->dbus_entries, name))); + + if ((old->device_valid != entry.device_valid) + || (entry.device_valid && !pa_streq(entry.device, old->device))) + send_device_updated_signal(de, &entry); + + if ((old->volume_valid != entry.volume_valid) + || (entry.volume_valid && (!pa_cvolume_equal(&entry.volume, &old->volume) + || !pa_channel_map_equal(&entry.channel_map, &old->channel_map)))) + send_volume_updated_signal(de, &entry); + + if (!old->muted_valid || (entry.muted != old->muted)) + send_mute_updated_signal(de, &entry); + + } else { + de = dbus_entry_new(u, name); + pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de)); + send_new_entry_signal(de); + } +#endif + if (apply_immediately) apply_entry(u, name, &entry); + } + +#ifdef HAVE_DBUS + if (old) + pa_xfree(old); +#endif } trigger_save(u); @@ -953,10 +1884,20 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio while (!pa_tagstruct_eof(t)) { const char *name; pa_datum key; +#ifdef HAVE_DBUS + struct dbus_entry *de; +#endif if (pa_tagstruct_gets(t, &name) < 0) goto fail; +#ifdef HAVE_DBUS + if ((de = pa_hashmap_get(u->dbus_entries, name))) { + send_entry_removed_signal(de); + dbus_entry_free(pa_hashmap_remove(u->dbus_entries, name)); + } +#endif + key.data = (char*) name; key.size = strlen(name); @@ -1015,6 +1956,10 @@ int pa__init(pa_module*m) { pa_source_output *so; uint32_t idx; pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE; +#ifdef HAVE_DBUS + pa_datum key; + pa_bool_t done; +#endif pa_assert(m); @@ -1085,6 +2030,34 @@ int pa__init(pa_module*m) { pa_log_info("Sucessfully opened database file '%s'.", fname); pa_xfree(fname); +#ifdef HAVE_DBUS + u->dbus_protocol = pa_dbus_protocol_get(u->core); + u->dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, OBJECT_PATH, &stream_restore_interface_info, u) >= 0); + pa_assert_se(pa_dbus_protocol_register_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0); + + /* Create the initial dbus entries. */ + done = !pa_database_first(u->database, &key, NULL); + while (!done) { + pa_datum next_key; + char *name; + struct dbus_entry *de; + + done = !pa_database_next(u->database, &key, &next_key, NULL); + + name = pa_xstrndup(key.data, key.size); + pa_datum_free(&key); + + de = dbus_entry_new(u, name); + pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) >= 0); + + pa_xfree(name); + + key = next_key; + } +#endif + PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx) subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u); @@ -1103,6 +2076,16 @@ fail: return -1; } +#ifdef HAVE_DBUS +static void free_dbus_entry_cb(void *p, void *userdata) { + struct dbus_entry *de = p; + + pa_assert(de); + + dbus_entry_free(de); +} +#endif + void pa__done(pa_module*m) { struct userdata* u; @@ -1111,6 +2094,19 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) return; +#ifdef HAVE_DBUS + if (u->dbus_protocol) { + pa_assert(u->dbus_entries); + + pa_assert_se(pa_dbus_protocol_unregister_extension(u->dbus_protocol, INTERFACE_STREAM_RESTORE) >= 0); + pa_assert_se(pa_dbus_protocol_remove_interface(u->dbus_protocol, OBJECT_PATH, stream_restore_interface_info.name) >= 0); + + pa_hashmap_free(u->dbus_entries, free_dbus_entry_cb, NULL); + + pa_dbus_protocol_unref(u->dbus_protocol); + } +#endif + if (u->subscription) pa_subscription_free(u->subscription); diff --git a/src/modules/reserve-wrap.c b/src/modules/reserve-wrap.c index 6086fc99..4be19c73 100644 --- a/src/modules/reserve-wrap.c +++ b/src/modules/reserve-wrap.c @@ -137,7 +137,7 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name) #ifdef HAVE_DBUS if (!(r->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { - pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message); + pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message); /* We don't treat this as error here because we want allow PA * to run even when no session bus is available. */ @@ -154,10 +154,10 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name) NULL)) < 0) { if (k == -EBUSY) { - pa_log_error("Device '%s' already locked.", device_name); + pa_log_debug("Device '%s' already locked.", device_name); goto fail; } else { - pa_log_warn("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k)); + pa_log_debug("Failed to acquire reservation lock on device '%s': %s", device_name, pa_cstrerror(-k)); return r; } } @@ -280,7 +280,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha #ifdef HAVE_DBUS if (!(w->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { - pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message); + pa_log_debug("Unable to contact D-Bus session bus: %s: %s", error.name, error.message); /* We don't treat this as error here because we want allow PA * to run even when no session bus is available. */ @@ -294,7 +294,7 @@ pa_reserve_monitor_wrapper* pa_reserve_monitor_wrapper_get(pa_core *c, const cha change_cb, NULL)) < 0) { - pa_log_warn("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k)); + pa_log_debug("Failed to create watch on device '%s': %s", device_name, pa_cstrerror(-k)); goto fail; } diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c index 4aa4ba1f..62c06f6a 100644 --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@ -57,6 +57,7 @@ static const pa_client_conf default_conf = { .default_sink = NULL, .default_source = NULL, .default_server = NULL, + .default_dbus_server = NULL, .autospawn = TRUE, .disable_shm = FALSE, .cookie_file = NULL, @@ -81,6 +82,7 @@ void pa_client_conf_free(pa_client_conf *c) { pa_xfree(c->default_sink); pa_xfree(c->default_source); pa_xfree(c->default_server); + pa_xfree(c->default_dbus_server); pa_xfree(c->cookie_file); pa_xfree(c); } @@ -97,6 +99,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) { { "default-sink", pa_config_parse_string, &c->default_sink, NULL }, { "default-source", pa_config_parse_string, &c->default_source, NULL }, { "default-server", pa_config_parse_string, &c->default_server, NULL }, + { "default-dbus-server", pa_config_parse_string, &c->default_dbus_server, NULL }, { "autospawn", pa_config_parse_bool, &c->autospawn, NULL }, { "cookie-file", pa_config_parse_string, &c->cookie_file, NULL }, { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h index ab97dc6a..618216f4 100644 --- a/src/pulse/client-conf.h +++ b/src/pulse/client-conf.h @@ -22,12 +22,13 @@ USA. ***/ +#include <pulsecore/macro.h> #include <pulsecore/native-common.h> /* A structure containing configuration data for PulseAudio clients. */ typedef struct pa_client_conf { - char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *cookie_file; + char *daemon_binary, *extra_arguments, *default_sink, *default_source, *default_server, *default_dbus_server, *cookie_file; pa_bool_t autospawn, disable_shm; uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; pa_bool_t cookie_valid; /* non-zero, when cookie is valid */ diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in index 6c8d371c..e03096e0 100644 --- a/src/pulse/client.conf.in +++ b/src/pulse/client.conf.in @@ -22,6 +22,7 @@ ; default-sink = ; default-source = ; default-server = +; default-dbus-server = ; autospawn = yes ; daemon-binary = @PA_BINARY@ diff --git a/src/pulse/context.c b/src/pulse/context.c index 23ae30ce..7468d0a9 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -128,6 +128,9 @@ static void reset_callbacks(pa_context *c) { c->event_callback = NULL; c->event_userdata = NULL; + c->ext_device_manager.callback = NULL; + c->ext_device_manager.userdata = NULL; + c->ext_stream_restore.callback = NULL; c->ext_stream_restore.userdata = NULL; } @@ -1434,6 +1437,8 @@ void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t if (!strcmp(name, "module-stream-restore")) pa_ext_stream_restore_command(c, tag, t); + else if (!strcmp(name, "module-device-manager")) + pa_ext_device_manager_command(c, tag, t); else pa_log(_("Received message for unknown extension '%s'"), name); diff --git a/src/pulse/def.h b/src/pulse/def.h index e839bd92..5d0a0b4b 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -110,6 +110,8 @@ typedef enum pa_operation_state { /** Some special flags for contexts. */ typedef enum pa_context_flags { + PA_CONTEXT_NOFLAGS = 0x0000U, + /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */ PA_CONTEXT_NOAUTOSPAWN = 0x0001U, /**< Disabled autospawning of the PulseAudio daemon if required */ PA_CONTEXT_NOFAIL = 0x0002U @@ -140,6 +142,9 @@ typedef enum pa_stream_direction { /** Some special flags for stream connections. */ typedef enum pa_stream_flags { + PA_STREAM_NOFLAGS = 0x0000U, + /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */ + PA_STREAM_START_CORKED = 0x0001U, /**< Create the stream corked, requiring an explicit * pa_stream_cork() call to uncork it. */ @@ -688,6 +693,9 @@ typedef enum pa_seek_mode { /** Special sink flags. */ typedef enum pa_sink_flags { + PA_SINK_NOFLAGS = 0x0000U, + /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */ + PA_SINK_HW_VOLUME_CTRL = 0x0001U, /**< Supports hardware volume control */ @@ -775,6 +783,9 @@ static inline int PA_SINK_IS_OPENED(pa_sink_state_t x) { /** Special source flags. */ typedef enum pa_source_flags { + PA_SOURCE_NOFLAGS = 0x0000U, + /**< Flag to pass when no specific options are needed (used to avoid casting) \since 0.9.19 */ + PA_SOURCE_HW_VOLUME_CTRL = 0x0001U, /**< Supports hardware volume control */ diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c new file mode 100644 index 00000000..138ed838 --- /dev/null +++ b/src/pulse/ext-device-manager.c @@ -0,0 +1,440 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + Copyright 2009 Colin Guthrie + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <pulse/context.h> +#include <pulse/gccmacro.h> +#include <pulse/xmalloc.h> + +#include <pulsecore/macro.h> +#include <pulsecore/pstream-util.h> + +#include "internal.h" +#include "operation.h" +#include "fork-detect.h" + +#include "ext-device-manager.h" + +enum { + SUBCOMMAND_TEST, + SUBCOMMAND_READ, + SUBCOMMAND_RENAME, + SUBCOMMAND_DELETE, + SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING, + SUBCOMMAND_REORDER, + SUBCOMMAND_SUBSCRIBE, + SUBCOMMAND_EVENT +}; + +static void ext_device_manager_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + uint32_t version = PA_INVALID_INDEX; + + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t, FALSE) < 0) + goto finish; + + } else if (pa_tagstruct_getu32(t, &version) < 0 || + !pa_tagstruct_eof(t)) { + + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + + if (o->callback) { + pa_ext_device_manager_test_cb_t cb = (pa_ext_device_manager_test_cb_t) o->callback; + cb(o->context, version, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +pa_operation *pa_ext_device_manager_test( + pa_context *c, + pa_ext_device_manager_test_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o; + pa_tagstruct *t; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_TEST); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_manager_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +static void ext_device_manager_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + int eol = 1; + + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t, FALSE) < 0) + goto finish; + + eol = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + pa_ext_device_manager_info i; + pa_bool_t available; + + memset(&i, 0, sizeof(i)); + available = FALSE; + + if (pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_gets(t, &i.icon) < 0 || + pa_tagstruct_get_boolean(t, &available) < 0 || + pa_tagstruct_getu32(t, &i.n_role_priorities) < 0) { + + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + i.available = (uint8_t)available; + + if (i.n_role_priorities > 0) { + uint32_t j; + i.role_priorities = pa_xnew0(pa_ext_device_manager_role_priority_info, i.n_role_priorities+1); + + for (j = 0; j < i.n_role_priorities; j++) { + + if (pa_tagstruct_gets(t, &i.role_priorities[j].role) < 0 || + pa_tagstruct_getu32(t, &i.role_priorities[j].priority) < 0) { + + pa_context_fail(o->context, PA_ERR_PROTOCOL); + pa_xfree(i.role_priorities); + goto finish; + } + } + + /* Terminate with an extra NULL entry, just to make sure */ + i.role_priorities[j].role = NULL; + i.role_priorities[j].priority = 0; + } + + if (o->callback) { + pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback; + cb(o->context, &i, 0, o->userdata); + } + + pa_xfree(i.role_priorities); + } + } + + if (o->callback) { + pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +pa_operation *pa_ext_device_manager_read( + pa_context *c, + pa_ext_device_manager_read_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o; + pa_tagstruct *t; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_READ); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_manager_read_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation *pa_ext_device_manager_set_device_description( + pa_context *c, + const char* device, + const char* description, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(device); + pa_assert(description); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_RENAME); + + pa_tagstruct_puts(t, device); + pa_tagstruct_puts(t, description); + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation *pa_ext_device_manager_delete( + pa_context *c, + const char *const s[], + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + const char *const *k; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(s); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_DELETE); + + for (k = s; *k; k++) { + if (!*k || !**k) + goto fail; + + pa_tagstruct_puts(t, *k); + } + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; + +fail: + if (o) { + pa_operation_cancel(o); + pa_operation_unref(o); + } + + if (t) + pa_tagstruct_free(t); + + pa_context_set_error(c, PA_ERR_INVALID); + return NULL; +} + +pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING); + pa_tagstruct_put_boolean(t, !!enable); + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation *pa_ext_device_manager_reorder_devices_for_role( + pa_context *c, + const char* role, + const char** devices, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag, i; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + pa_assert(role); + pa_assert(devices); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_REORDER); + pa_tagstruct_puts(t, role); + + i = 0; while (devices[i]) i++; + pa_tagstruct_putu32(t, i); + + i = 0; + while (devices[i]) + pa_tagstruct_puts(t, devices[i++]); + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation *pa_ext_device_manager_subscribe( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o; + pa_tagstruct *t; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE); + pa_tagstruct_put_boolean(t, enable); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +void pa_ext_device_manager_set_subscribe_cb( + pa_context *c, + pa_ext_device_manager_subscribe_cb_t cb, + void *userdata) { + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + if (pa_detect_fork()) + return; + + c->ext_device_manager.callback = cb; + c->ext_device_manager.userdata = userdata; +} + +void pa_ext_device_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t) { + uint32_t subcommand; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(t); + + if (pa_tagstruct_getu32(t, &subcommand) < 0 || + !pa_tagstruct_eof(t)) { + + pa_context_fail(c, PA_ERR_PROTOCOL); + return; + } + + if (subcommand != SUBCOMMAND_EVENT) { + pa_context_fail(c, PA_ERR_PROTOCOL); + return; + } + + if (c->ext_device_manager.callback) + c->ext_device_manager.callback(c, c->ext_device_manager.userdata); +} diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h new file mode 100644 index 00000000..13538f0c --- /dev/null +++ b/src/pulse/ext-device-manager.h @@ -0,0 +1,128 @@ +#ifndef foopulseextdevicemanagerhfoo +#define foopulseextdevicemanagerhfoo + +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + Copyright 2009 Colin Guthrie + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <pulse/context.h> +#include <pulse/version.h> + +/** \file + * + * Routines for controlling module-device-manager + */ + +PA_C_DECL_BEGIN + +typedef struct pa_ext_device_manager_role_priority_info { + const char *role; + uint32_t priority; +} pa_ext_device_manager_role_priority_info; + +/** Stores information about one device in the device database that is + * maintained by module-device-manager. \since 0.9.19 */ +typedef struct pa_ext_device_manager_info { + const char *name; /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */ + const char *description; /**< The description of the device when it was last seen, if applicable and saved */ + const char *icon; /**< The icon given to the device */ + uint8_t available; /**< Is the device currently available? */ + uint32_t n_role_priorities; /**< How many role priorities do we have? */ + pa_ext_device_manager_role_priority_info *role_priorities; /**< An array of role priority structures or NULL */ +} pa_ext_device_manager_info; + +/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.19 */ +typedef void (*pa_ext_device_manager_test_cb_t)( + pa_context *c, + uint32_t version, + void *userdata); + +/** Test if this extension module is available in the server. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_test( + pa_context *c, + pa_ext_device_manager_test_cb_t cb, + void *userdata); + +/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.19 */ +typedef void (*pa_ext_device_manager_read_cb_t)( + pa_context *c, + const pa_ext_device_manager_info *info, + int eol, + void *userdata); + +/** Read all entries from the device database. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_read( + pa_context *c, + pa_ext_device_manager_read_cb_t cb, + void *userdata); + +/** Sets the description for a device. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_set_device_description( + pa_context *c, + const char* device, + const char* description, + pa_context_success_cb_t cb, + void *userdata); + +/** Delete entries from the device database. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_delete( + pa_context *c, + const char *const s[], + pa_context_success_cb_t cb, + void *userdata); + +/** Enable the role-based device-priority routing mode. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata); + +/** Prefer a given device in the priority list. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_reorder_devices_for_role( + pa_context *c, + const char* role, + const char** devices, + pa_context_success_cb_t cb, + void *userdata); + +/** Subscribe to changes in the device database. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_subscribe( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata); + +/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.19 */ +typedef void (*pa_ext_device_manager_subscribe_cb_t)( + pa_context *c, + void *userdata); + +/** Set the subscription callback that is called when + * pa_ext_device_manager_subscribe() was called. \since 0.9.19 */ +void pa_ext_device_manager_set_subscribe_cb( + pa_context *c, + pa_ext_device_manager_subscribe_cb_t cb, + void *userdata); + +PA_C_DECL_END + +#endif diff --git a/src/pulse/internal.h b/src/pulse/internal.h index e069c9e9..b371bfc2 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -28,6 +28,7 @@ #include <pulse/stream.h> #include <pulse/operation.h> #include <pulse/subscribe.h> +#include <pulse/ext-device-manager.h> #include <pulse/ext-stream-restore.h> #include <pulsecore/socket-client.h> @@ -102,6 +103,10 @@ struct pa_context { /* Extension specific data */ struct { + pa_ext_device_manager_subscribe_cb_t callback; + void *userdata; + } ext_device_manager; + struct { pa_ext_stream_restore_subscribe_cb_t callback; void *userdata; } ext_stream_restore; @@ -283,6 +288,7 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta #define PA_FAIL_RETURN_NULL(context, error) \ PA_FAIL_RETURN_ANY(context, error, NULL) +void pa_ext_device_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t); void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t); pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m); diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c index 048b241a..faa98b79 100644 --- a/src/pulse/proplist.c +++ b/src/pulse/proplist.c @@ -681,3 +681,32 @@ int pa_proplist_isempty(pa_proplist *p) { return pa_hashmap_isempty(MAKE_HASHMAP(p)); } + +int pa_proplist_equal(pa_proplist *a, pa_proplist *b) { + const void *key = NULL; + struct property *a_prop = NULL; + struct property *b_prop = NULL; + void *state = NULL; + + pa_assert(a); + pa_assert(b); + + if (a == b) + return 1; + + if (pa_proplist_size(a) != pa_proplist_size(b)) + return 0; + + while ((a_prop = pa_hashmap_iterate(MAKE_HASHMAP(a), &state, &key))) { + if (!(b_prop = pa_hashmap_get(MAKE_HASHMAP(b), key))) + return 0; + + if (a_prop->nbytes != b_prop->nbytes) + return 0; + + if (memcmp(a_prop->value, b_prop->value, a_prop->nbytes) != 0) + return 0; + } + + return 1; +} diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h index 8dff8df4..aae05346 100644 --- a/src/pulse/proplist.h +++ b/src/pulse/proplist.h @@ -358,7 +358,7 @@ char *pa_proplist_to_string_sep(pa_proplist *p, const char *sep); * readable string. \since 0.9.15 */ pa_proplist *pa_proplist_from_string(const char *str); - /** Returns 1 if an entry for the specified key is existant in the +/** Returns 1 if an entry for the specified key is existant in the * property list. \since 0.9.11 */ int pa_proplist_contains(pa_proplist *p, const char *key); @@ -375,6 +375,10 @@ unsigned pa_proplist_size(pa_proplist *t); /** Returns 0 when the proplist is empty, positive otherwise \since 0.9.15 */ int pa_proplist_isempty(pa_proplist *t); +/** Return non-zero when a and b have the same keys and values. + * \since 0.9.16 */ +int pa_proplist_equal(pa_proplist *a, pa_proplist *b); + PA_C_DECL_END #endif diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 8e98e857..27e09cbc 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2678,6 +2678,28 @@ char *pa_replace(const char*s, const char*a, const char *b) { return pa_strbuf_tostring_free(sb); } +char *pa_escape(const char *p, const char *chars) { + const char *s; + const char *c; + pa_strbuf *buf = pa_strbuf_new(); + + for (s = p; *s; ++s) { + if (*s == '\\') + pa_strbuf_putc(buf, '\\'); + else if (chars) { + for (c = chars; *c; ++c) { + if (*s == *c) { + pa_strbuf_putc(buf, '\\'); + break; + } + } + } + pa_strbuf_putc(buf, *s); + } + + return pa_strbuf_tostring_free(buf); +} + char *pa_unescape(char *p) { char *s, *d; pa_bool_t escaped = FALSE; diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 84752d4d..9986b14a 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -224,6 +224,13 @@ unsigned pa_ncpus(void); char *pa_replace(const char*s, const char*a, const char *b); +/* Escapes p by inserting backslashes in front of backslashes. chars is a + * regular (ie. NULL-terminated) string containing additional characters that + * should be escaped. chars can be NULL. The caller has to free the returned + * string. */ +char *pa_escape(const char *p, const char *chars); + +/* Does regular backslash unescaping. Returns the argument p. */ char *pa_unescape(char *p); char *pa_realpath(const char *path); diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index c1002f93..bfcea4f6 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -52,6 +52,13 @@ typedef enum pa_suspend_cause { #include <pulsecore/sink-input.h> #include <pulsecore/msgobject.h> +typedef enum pa_server_type { + PA_SERVER_TYPE_UNSET, + PA_SERVER_TYPE_USER, + PA_SERVER_TYPE_SYSTEM, + PA_SERVER_TYPE_NONE +} pa_server_type_t; + typedef enum pa_core_state { PA_CORE_STARTUP, PA_CORE_RUNNING, @@ -161,6 +168,8 @@ struct pa_core { pa_resample_method_t resample_method; int realtime_priority; + pa_server_type_t server_type; + /* hooks */ pa_hook hooks[PA_CORE_HOOK_MAX]; }; diff --git a/src/pulsecore/cpu-arm.h b/src/pulsecore/cpu-arm.h index 3ccd0708..a87cb63b 100644 --- a/src/pulsecore/cpu-arm.h +++ b/src/pulsecore/cpu-arm.h @@ -5,7 +5,7 @@ This file is part of PulseAudio. Copyright 2004-2006 Lennart Poettering - Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk> + Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk> PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/pulsecore/cpu-x86.h b/src/pulsecore/cpu-x86.h index b40eb5ce..f6484c59 100644 --- a/src/pulsecore/cpu-x86.h +++ b/src/pulsecore/cpu-x86.h @@ -5,7 +5,7 @@ This file is part of PulseAudio. Copyright 2004-2006 Lennart Poettering - Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk> + Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk> PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c index 4e6148f0..e3700ea5 100644 --- a/src/pulsecore/dbus-util.c +++ b/src/pulsecore/dbus-util.c @@ -28,6 +28,7 @@ #include <pulse/rtclock.h> #include <pulse/timeval.h> +#include <pulse/utf8.h> #include <pulse/xmalloc.h> #include <pulsecore/core-rtclock.h> @@ -290,6 +291,31 @@ pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, pa_bool return pconn; } +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new_from_existing( + pa_mainloop_api *m, + pa_bool_t use_rtclock, + DBusConnection *conn) { + pa_dbus_wrap_connection *pconn; + + pa_assert(m); + pa_assert(conn); + + pconn = pa_xnew(pa_dbus_wrap_connection, 1); + pconn->mainloop = m; + pconn->connection = dbus_connection_ref(conn); + pconn->use_rtclock = use_rtclock; + + dbus_connection_set_exit_on_disconnect(conn, FALSE); + dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL); + dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, pconn, NULL); + dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, pconn, NULL); + dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL); + + pconn->dispatch_event = pconn->mainloop->defer_new(pconn->mainloop, dispatch_cb, conn); + + return pconn; +} + void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* c) { pa_assert(c); @@ -422,3 +448,329 @@ void pa_dbus_free_pending_list(pa_dbus_pending **p) { pa_dbus_pending_free(i); } } + +void pa_dbus_send_error(DBusConnection *c, DBusMessage *in_reply_to, const char *name, const char *format, ...) { + va_list ap; + char *message; + DBusMessage *reply = NULL; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(name); + pa_assert(format); + + va_start(ap, format); + message = pa_vsprintf_malloc(format, ap); + va_end(ap); + pa_assert_se((reply = dbus_message_new_error(in_reply_to, name, message))); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(message); +} + +void pa_dbus_send_empty_reply(DBusConnection *c, DBusMessage *in_reply_to) { + DBusMessage *reply = NULL; + + pa_assert(c); + pa_assert(in_reply_to); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +void pa_dbus_send_basic_value_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data) { + DBusMessage *reply = NULL; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + pa_assert_se(dbus_message_append_args(reply, type, data, DBUS_TYPE_INVALID)); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +static const char *signature_from_basic_type(int type) { + switch (type) { + case DBUS_TYPE_BOOLEAN: return DBUS_TYPE_BOOLEAN_AS_STRING; + case DBUS_TYPE_BYTE: return DBUS_TYPE_BYTE_AS_STRING; + case DBUS_TYPE_INT16: return DBUS_TYPE_INT16_AS_STRING; + case DBUS_TYPE_UINT16: return DBUS_TYPE_UINT16_AS_STRING; + case DBUS_TYPE_INT32: return DBUS_TYPE_INT32_AS_STRING; + case DBUS_TYPE_UINT32: return DBUS_TYPE_UINT32_AS_STRING; + case DBUS_TYPE_INT64: return DBUS_TYPE_INT64_AS_STRING; + case DBUS_TYPE_UINT64: return DBUS_TYPE_UINT64_AS_STRING; + case DBUS_TYPE_DOUBLE: return DBUS_TYPE_DOUBLE_AS_STRING; + case DBUS_TYPE_STRING: return DBUS_TYPE_STRING_AS_STRING; + case DBUS_TYPE_OBJECT_PATH: return DBUS_TYPE_OBJECT_PATH_AS_STRING; + case DBUS_TYPE_SIGNATURE: return DBUS_TYPE_SIGNATURE_AS_STRING; + default: pa_assert_not_reached(); + } +} + +void pa_dbus_send_basic_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data) { + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter variant_iter; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, + DBUS_TYPE_VARIANT, + signature_from_basic_type(type), + &variant_iter)); + pa_assert_se(dbus_message_iter_append_basic(&variant_iter, type, data)); + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &variant_iter)); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +/* Note: returns sizeof(char*) for strings, object paths and signatures. */ +static unsigned basic_type_size(int type) { + switch (type) { + case DBUS_TYPE_BOOLEAN: return sizeof(dbus_bool_t); + case DBUS_TYPE_BYTE: return 1; + case DBUS_TYPE_INT16: return sizeof(dbus_int16_t); + case DBUS_TYPE_UINT16: return sizeof(dbus_uint16_t); + case DBUS_TYPE_INT32: return sizeof(dbus_int32_t); + case DBUS_TYPE_UINT32: return sizeof(dbus_uint32_t); + case DBUS_TYPE_INT64: return sizeof(dbus_int64_t); + case DBUS_TYPE_UINT64: return sizeof(dbus_uint64_t); + case DBUS_TYPE_DOUBLE: return sizeof(double); + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: return sizeof(char*); + default: pa_assert_not_reached(); + } +} + +void pa_dbus_send_basic_array_variant_reply( + DBusConnection *c, + DBusMessage *in_reply_to, + int item_type, + void *array, + unsigned n) { + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_dbus_append_basic_array_variant(&msg_iter, item_type, array, n); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +void pa_dbus_send_proplist_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, pa_proplist *proplist) { + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(proplist); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_dbus_append_proplist_variant(&msg_iter, proplist); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +void pa_dbus_append_basic_array(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { + DBusMessageIter array_iter; + unsigned i; + unsigned item_size; + + pa_assert(iter); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + item_size = basic_type_size(item_type); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, signature_from_basic_type(item_type), &array_iter)); + + for (i = 0; i < n; ++i) + pa_assert_se(dbus_message_iter_append_basic(&array_iter, item_type, &((uint8_t*) array)[i * item_size])); + + pa_assert_se(dbus_message_iter_close_container(iter, &array_iter)); +}; + +void pa_dbus_append_basic_variant(DBusMessageIter *iter, int type, void *data) { + DBusMessageIter variant_iter; + + pa_assert(iter); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, signature_from_basic_type(type), &variant_iter)); + pa_assert_se(dbus_message_iter_append_basic(&variant_iter, type, data)); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); +} + +void pa_dbus_append_basic_array_variant(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { + DBusMessageIter variant_iter; + char *array_signature; + + pa_assert(iter); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + array_signature = pa_sprintf_malloc("a%c", *signature_from_basic_type(item_type)); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, array_signature, &variant_iter)); + pa_dbus_append_basic_array(&variant_iter, item_type, array, n); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); + + pa_xfree(array_signature); +} + +void pa_dbus_append_basic_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, int type, void *data) { + DBusMessageIter dict_entry_iter; + + pa_assert(dict_iter); + pa_assert(key); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_dbus_append_basic_variant(&dict_entry_iter, type, data); + pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); +} + +void pa_dbus_append_basic_array_variant_dict_entry( + DBusMessageIter *dict_iter, + const char *key, + int item_type, + const void *array, + unsigned n) { + DBusMessageIter dict_entry_iter; + + pa_assert(dict_iter); + pa_assert(key); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_dbus_append_basic_array_variant(&dict_entry_iter, item_type, array, n); + pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); +} + +void pa_dbus_append_proplist(DBusMessageIter *iter, pa_proplist *proplist) { + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + DBusMessageIter array_iter; + void *state = NULL; + const char *key; + + pa_assert(iter); + pa_assert(proplist); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{say}", &dict_iter)); + + while ((key = pa_proplist_iterate(proplist, &state))) { + const void *value = NULL; + size_t nbytes; + + pa_assert_se(pa_proplist_get(proplist, key, &value, &nbytes) >= 0); + + pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + + pa_assert_se(dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_ARRAY, "y", &array_iter)); + pa_assert_se(dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, &value, nbytes)); + pa_assert_se(dbus_message_iter_close_container(&dict_entry_iter, &array_iter)); + + pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)); + } + + pa_assert_se(dbus_message_iter_close_container(iter, &dict_iter)); +} + +void pa_dbus_append_proplist_variant(DBusMessageIter *iter, pa_proplist *proplist) { + DBusMessageIter variant_iter; + + pa_assert(iter); + pa_assert(proplist); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{say}", &variant_iter)); + pa_dbus_append_proplist(&variant_iter, proplist); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); +} + +void pa_dbus_append_proplist_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, pa_proplist *proplist) { + DBusMessageIter dict_entry_iter; + + pa_assert(dict_iter); + pa_assert(key); + pa_assert(proplist); + + pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_dbus_append_proplist_variant(&dict_entry_iter, proplist); + pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); +} + +pa_proplist *pa_dbus_get_proplist_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter) { + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + pa_proplist *proplist = NULL; + const char *key = NULL; + const uint8_t *value = NULL; + int value_length = 0; + + pa_assert(c); + pa_assert(msg); + pa_assert(iter); + pa_assert(pa_streq(dbus_message_iter_get_signature(iter), "a{say}")); + + proplist = pa_proplist_new(); + + dbus_message_iter_recurse(iter, &dict_iter); + + while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(&dict_iter, &dict_entry_iter); + + dbus_message_iter_get_basic(&dict_entry_iter, &key); + dbus_message_iter_next(&dict_entry_iter); + + if (strlen(key) <= 0 || !pa_ascii_valid(key)) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Invalid property list key: '%s'.", key); + goto fail; + } + + dbus_message_iter_get_fixed_array(&dict_entry_iter, &value, &value_length); + + pa_assert(value_length >= 0); + + pa_assert_se(pa_proplist_set(proplist, key, value, value_length) >= 0); + + dbus_message_iter_next(&dict_iter); + } + + dbus_message_iter_next(iter); + + return proplist; + +fail: + if (proplist) + pa_proplist_free(proplist); + + return NULL; +} diff --git a/src/pulsecore/dbus-util.h b/src/pulsecore/dbus-util.h index 9ff298d8..f35e66cb 100644 --- a/src/pulsecore/dbus-util.h +++ b/src/pulsecore/dbus-util.h @@ -26,11 +26,16 @@ #include <pulsecore/llist.h> #include <pulse/mainloop-api.h> +#include <pulse/proplist.h> /* A wrap connection is not shared or refcounted, it is available in client side */ typedef struct pa_dbus_wrap_connection pa_dbus_wrap_connection; pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, pa_bool_t use_rtclock, DBusBusType type, DBusError *error); +pa_dbus_wrap_connection* pa_dbus_wrap_connection_new_from_existing( + pa_mainloop_api *mainloop, + pa_bool_t use_rtclock, + DBusConnection *conn); void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* conn); DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *conn); @@ -60,4 +65,42 @@ void pa_dbus_sync_pending_list(pa_dbus_pending **p); /* Free up a list of pa_dbus_pending_call objects */ void pa_dbus_free_pending_list(pa_dbus_pending **p); +/* Sends an error message as the reply to the given message. */ +void pa_dbus_send_error( + DBusConnection *c, + DBusMessage *in_reply_to, + const char *name, + const char *format, ...) PA_GCC_PRINTF_ATTR(4, 5); + +void pa_dbus_send_empty_reply(DBusConnection *c, DBusMessage *in_reply_to); +void pa_dbus_send_basic_value_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data); +void pa_dbus_send_basic_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data); +void pa_dbus_send_basic_array_variant_reply( + DBusConnection *c, + DBusMessage *in_reply_to, + int item_type, + void *array, + unsigned n); +void pa_dbus_send_proplist_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, pa_proplist *proplist); + +void pa_dbus_append_basic_array(DBusMessageIter *iter, int item_type, const void *array, unsigned n); +void pa_dbus_append_basic_array_variant(DBusMessageIter *iter, int item_type, const void *array, unsigned n); +void pa_dbus_append_basic_variant(DBusMessageIter *iter, int type, void *data); +void pa_dbus_append_basic_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, int type, void *data); +void pa_dbus_append_basic_array_variant_dict_entry( + DBusMessageIter *dict_iter, + const char *key, + int item_type, + const void *array, + unsigned n); +void pa_dbus_append_proplist(DBusMessageIter *iter, pa_proplist *proplist); +void pa_dbus_append_proplist_variant(DBusMessageIter *iter, pa_proplist *proplist); +void pa_dbus_append_proplist_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, pa_proplist *proplist); + +/* Returns a new proplist that the caller has to free. If the proplist contains + * invalid keys, an error reply is sent and NULL is returned. The iterator must + * point to "a{say}" element. This function calls dbus_message_iter_next(iter) + * before returning. */ +pa_proplist *pa_dbus_get_proplist_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter); + #endif diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index f38b17c6..eac4a59b 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -54,7 +54,7 @@ * stored in SHM and our OS does not commit the memory before we use * it for the first time. */ #define PA_MEMPOOL_SLOTS_MAX 1024 -#define PA_MEMPOOL_SLOT_SIZE (64*1024) +#define PA_MEMPOOL_SLOT_SIZE (128*1024) #define PA_MEMEXPORT_SLOTS_MAX 128 diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index c7d734d9..e78cdb9a 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -415,3 +415,13 @@ int pa_modargs_get_proplist(pa_modargs *ma, const char *name, pa_proplist *p, pa return 0; } + +const char *pa_modargs_iterate(pa_modargs *ma, void **state) { + pa_hashmap *map = (pa_hashmap*) ma; + struct entry *e; + + if (!(e = pa_hashmap_iterate(map, state, NULL))) + return NULL; + + return e->key; +} diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h index b3125b10..1ed66e9a 100644 --- a/src/pulsecore/modargs.h +++ b/src/pulsecore/modargs.h @@ -60,4 +60,13 @@ int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *s int pa_modargs_get_proplist(pa_modargs *ma, const char *name, pa_proplist *p, pa_update_mode_t m); +/* Iterate through the module argument list. The user should allocate a + * state variable of type void* and initialize it with NULL. A pointer + * to this variable should then be passed to pa_modargs_iterate() + * which should be called in a loop until it returns NULL which + * signifies EOL. On each invication this function will return the + * key string for the next entry. The keys in the argument list do not + * have any particular order. */ +const char *pa_modargs_iterate(pa_modargs *ma, void **state); + #endif diff --git a/src/pulsecore/protocol-dbus.c b/src/pulsecore/protocol-dbus.c new file mode 100644 index 00000000..5c1127be --- /dev/null +++ b/src/pulsecore/protocol-dbus.c @@ -0,0 +1,1134 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dbus/dbus.h> + +#include <pulse/xmalloc.h> + +#include <pulsecore/core-util.h> +#include <pulsecore/dbus-util.h> +#include <pulsecore/hashmap.h> +#include <pulsecore/idxset.h> +#include <pulsecore/shared.h> +#include <pulsecore/strbuf.h> + +#include "protocol-dbus.h" + +struct pa_dbus_protocol { + PA_REFCNT_DECLARE; + + pa_core *core; + pa_hashmap *objects; /* Object path -> struct object_entry */ + pa_hashmap *connections; /* DBusConnection -> struct connection_entry */ + pa_idxset *extensions; /* Strings */ + + pa_hook hooks[PA_DBUS_PROTOCOL_HOOK_MAX]; +}; + +struct object_entry { + char *path; + pa_hashmap *interfaces; /* Interface name -> struct interface_entry */ + char *introspection; +}; + +struct connection_entry { + DBusConnection *connection; + pa_client *client; + + pa_bool_t listening_for_all_signals; + + /* Contains object paths. If this is empty, then signals from all objects + * are accepted. Only used when listening_for_all_signals == TRUE. */ + pa_idxset *all_signals_objects; + + /* Signal name -> idxset. The idxsets contain object paths. If an idxset is + * empty, then that signal is accepted from all objects. Only used when + * listening_for_all_signals == FALSE. */ + pa_hashmap *listening_signals; +}; + +struct interface_entry { + char *name; + pa_hashmap *method_handlers; + pa_hashmap *method_signatures; /* Derived from method_handlers. Contains only "in" arguments. */ + pa_hashmap *property_handlers; + pa_dbus_receive_cb_t get_all_properties_cb; + pa_dbus_signal_info *signals; + unsigned n_signals; + void *userdata; +}; + +char *pa_get_dbus_address_from_server_type(pa_server_type_t server_type) { + char *address = NULL; + char *runtime_path = NULL; + char *escaped_path = NULL; + + switch (server_type) { + case PA_SERVER_TYPE_USER: + pa_assert_se((runtime_path = pa_runtime_path(PA_DBUS_SOCKET_NAME))); + pa_assert_se((escaped_path = dbus_address_escape_value(runtime_path))); + address = pa_sprintf_malloc("unix:path=%s", escaped_path); + break; + + case PA_SERVER_TYPE_SYSTEM: + pa_assert_se((escaped_path = dbus_address_escape_value(PA_DBUS_SYSTEM_SOCKET_PATH))); + address = pa_sprintf_malloc("unix:path=%s", escaped_path); + break; + + case PA_SERVER_TYPE_NONE: + address = pa_xnew0(char, 1); + break; + + default: + pa_assert_not_reached(); + } + + pa_xfree(runtime_path); + pa_xfree(escaped_path); + + return address; +} + +static pa_dbus_protocol *dbus_protocol_new(pa_core *c) { + pa_dbus_protocol *p; + unsigned i; + + pa_assert(c); + + p = pa_xnew(pa_dbus_protocol, 1); + PA_REFCNT_INIT(p); + p->core = pa_core_ref(c); + p->objects = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + p->connections = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + p->extensions = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + for (i = 0; i < PA_DBUS_PROTOCOL_HOOK_MAX; ++i) + pa_hook_init(&p->hooks[i], p); + + pa_assert_se(pa_shared_set(c, "dbus-protocol", p) >= 0); + + return p; +} + +pa_dbus_protocol* pa_dbus_protocol_get(pa_core *c) { + pa_dbus_protocol *p; + + if ((p = pa_shared_get(c, "dbus-protocol"))) + return pa_dbus_protocol_ref(p); + + return dbus_protocol_new(c); +} + +pa_dbus_protocol* pa_dbus_protocol_ref(pa_dbus_protocol *p) { + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) >= 1); + + PA_REFCNT_INC(p); + + return p; +} + +void pa_dbus_protocol_unref(pa_dbus_protocol *p) { + unsigned i; + + pa_assert(p); + pa_assert(PA_REFCNT_VALUE(p) >= 1); + + if (PA_REFCNT_DEC(p) > 0) + return; + + pa_assert(pa_hashmap_isempty(p->objects)); + pa_assert(pa_hashmap_isempty(p->connections)); + pa_assert(pa_idxset_isempty(p->extensions)); + + pa_hashmap_free(p->objects, NULL, NULL); + pa_hashmap_free(p->connections, NULL, NULL); + pa_idxset_free(p->extensions, NULL, NULL); + + for (i = 0; i < PA_DBUS_PROTOCOL_HOOK_MAX; ++i) + pa_hook_done(&p->hooks[i]); + + pa_assert_se(pa_shared_remove(p->core, "dbus-protocol") >= 0); + + pa_core_unref(p->core); + + pa_xfree(p); +} + +static void update_introspection(struct object_entry *oe) { + pa_strbuf *buf; + void *interfaces_state = NULL; + struct interface_entry *iface_entry = NULL; + + pa_assert(oe); + + buf = pa_strbuf_new(); + pa_strbuf_puts(buf, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); + pa_strbuf_puts(buf, "<node>\n"); + + PA_HASHMAP_FOREACH(iface_entry, oe->interfaces, interfaces_state) { + pa_dbus_method_handler *method_handler; + pa_dbus_property_handler *property_handler; + void *handlers_state = NULL; + unsigned i; + unsigned j; + + pa_strbuf_printf(buf, " <interface name=\"%s\">\n", iface_entry->name); + + PA_HASHMAP_FOREACH(method_handler, iface_entry->method_handlers, handlers_state) { + pa_strbuf_printf(buf, " <method name=\"%s\">\n", method_handler->method_name); + + for (i = 0; i < method_handler->n_arguments; ++i) + pa_strbuf_printf(buf, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n", + method_handler->arguments[i].name, + method_handler->arguments[i].type, + method_handler->arguments[i].direction); + + pa_strbuf_puts(buf, " </method>\n"); + } + + handlers_state = NULL; + + PA_HASHMAP_FOREACH(property_handler, iface_entry->property_handlers, handlers_state) + pa_strbuf_printf(buf, " <property name=\"%s\" type=\"%s\" access=\"%s\"/>\n", + property_handler->property_name, + property_handler->type, + property_handler->get_cb ? (property_handler->set_cb ? "readwrite" : "read") : "write"); + + for (i = 0; i < iface_entry->n_signals; ++i) { + pa_strbuf_printf(buf, " <signal name=\"%s\">\n", iface_entry->signals[i].name); + + for (j = 0; j < iface_entry->signals[i].n_arguments; ++j) + pa_strbuf_printf(buf, " <arg name=\"%s\" type=\"%s\"/>\n", iface_entry->signals[i].arguments[j].name, + iface_entry->signals[i].arguments[j].type); + + pa_strbuf_puts(buf, " </signal>\n"); + } + + pa_strbuf_puts(buf, " </interface>\n"); + } + + pa_strbuf_puts(buf, " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" + " <method name=\"Introspect\">\n" + " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" + " </method>\n" + " </interface>\n" + " <interface name=\"" DBUS_INTERFACE_PROPERTIES "\">\n" + " <method name=\"Get\">\n" + " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"value\" type=\"v\" direction=\"out\"/>\n" + " </method>\n" + " <method name=\"Set\">\n" + " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"value\" type=\"v\" direction=\"in\"/>\n" + " </method>\n" + " <method name=\"GetAll\">\n" + " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" + " <arg name=\"props\" type=\"a{sv}\" direction=\"out\"/>\n" + " </method>\n" + " </interface>\n"); + + pa_strbuf_puts(buf, "</node>\n"); + + pa_xfree(oe->introspection); + oe->introspection = pa_strbuf_tostring_free(buf); +} + +/* Return value of find_handler() and its subfunctions. */ +enum find_result_t { + /* The received message is a valid .Get call. */ + FOUND_GET_PROPERTY, + + /* The received message is a valid .Set call. */ + FOUND_SET_PROPERTY, + + /* The received message is a valid .GetAll call. */ + FOUND_GET_ALL, + + /* The received message is a valid method call. */ + FOUND_METHOD, + + /* The interface of the received message hasn't been registered for the + * destination object. */ + NO_SUCH_INTERFACE, + + /* No property handler was found for the received .Get or .Set call. */ + NO_SUCH_PROPERTY, + + /* The interface argument of a property call didn't match any registered + * interface. */ + NO_SUCH_PROPERTY_INTERFACE, + + /* The received message called .Get or .Set for a property whose access + * mode doesn't match the call. */ + PROPERTY_ACCESS_DENIED, + + /* The new value signature of a .Set call didn't match the expexted + * signature. */ + INVALID_PROPERTY_SIG, + + /* No method handler was found for the received message. */ + NO_SUCH_METHOD, + + /* The signature of the received message didn't match the expected + * signature. Despite the name, this can also be returned for a property + * call if its message signature is invalid. */ + INVALID_METHOD_SIG +}; + +/* Data for resolving the correct reaction to a received message. */ +struct call_info { + DBusMessage *message; /* The received message. */ + struct object_entry *obj_entry; + const char *interface; /* Destination interface name (extracted from the message). */ + struct interface_entry *iface_entry; + + const char *property; /* Property name (extracted from the message). */ + const char *property_interface; /* The interface argument of a property call is stored here. */ + pa_dbus_property_handler *property_handler; + const char *expected_property_sig; /* Property signature from the introspection data. */ + const char *property_sig; /* The signature of the new value in the received .Set message. */ + DBusMessageIter variant_iter; /* Iterator pointing to the beginning of the new value variant of a .Set call. */ + + const char *method; /* Method name (extracted from the message). */ + pa_dbus_method_handler *method_handler; + const char *expected_method_sig; /* Method signature from the introspection data. */ + const char *method_sig; /* The signature of the received message. */ +}; + +/* Called when call_info->property has been set and the property interface has + * not been given. In case of a Set call, call_info->property_sig is also set, + * which is checked against the expected value in this function. */ +static enum find_result_t find_handler_by_property(struct call_info *call_info) { + void *state = NULL; + + pa_assert(call_info); + + PA_HASHMAP_FOREACH(call_info->iface_entry, call_info->obj_entry->interfaces, state) { + if ((call_info->property_handler = pa_hashmap_get(call_info->iface_entry->property_handlers, call_info->property))) { + if (pa_streq(call_info->method, "Get")) + return call_info->property_handler->get_cb ? FOUND_GET_PROPERTY : PROPERTY_ACCESS_DENIED; + + else if (pa_streq(call_info->method, "Set")) { + call_info->expected_property_sig = call_info->property_handler->type; + + if (pa_streq(call_info->property_sig, call_info->expected_property_sig)) + return call_info->property_handler->set_cb ? FOUND_SET_PROPERTY : PROPERTY_ACCESS_DENIED; + else + return INVALID_PROPERTY_SIG; + + } else + pa_assert_not_reached(); + } + } + + return NO_SUCH_PROPERTY; +} + +static enum find_result_t find_handler_by_method(struct call_info *call_info) { + void *state = NULL; + + pa_assert(call_info); + + PA_HASHMAP_FOREACH(call_info->iface_entry, call_info->obj_entry->interfaces, state) { + if ((call_info->method_handler = pa_hashmap_get(call_info->iface_entry->method_handlers, call_info->method))) { + call_info->expected_method_sig = pa_hashmap_get(call_info->iface_entry->method_signatures, call_info->method); + + if (pa_streq(call_info->method_sig, call_info->expected_method_sig)) + return FOUND_METHOD; + else + return INVALID_METHOD_SIG; + } + } + + return NO_SUCH_METHOD; +} + +static enum find_result_t find_handler_from_properties_call(struct call_info *call_info) { + pa_assert(call_info); + + if (pa_streq(call_info->method, "GetAll")) { + call_info->expected_method_sig = "s"; + if (!pa_streq(call_info->method_sig, call_info->expected_method_sig)) + return INVALID_METHOD_SIG; + + pa_assert_se(dbus_message_get_args(call_info->message, NULL, + DBUS_TYPE_STRING, &call_info->property_interface, + DBUS_TYPE_INVALID)); + + if (*call_info->property_interface) { + if ((call_info->iface_entry = pa_hashmap_get(call_info->obj_entry->interfaces, call_info->property_interface))) + return FOUND_GET_ALL; + else + return NO_SUCH_PROPERTY_INTERFACE; + + } else { + pa_assert_se(call_info->iface_entry = pa_hashmap_first(call_info->obj_entry->interfaces)); + return FOUND_GET_ALL; + } + + } else if (pa_streq(call_info->method, "Get")) { + call_info->expected_method_sig = "ss"; + if (!pa_streq(call_info->method_sig, call_info->expected_method_sig)) + return INVALID_METHOD_SIG; + + pa_assert_se(dbus_message_get_args(call_info->message, NULL, + DBUS_TYPE_STRING, &call_info->property_interface, + DBUS_TYPE_STRING, &call_info->property, + DBUS_TYPE_INVALID)); + + if (*call_info->property_interface) { + if (!(call_info->iface_entry = pa_hashmap_get(call_info->obj_entry->interfaces, call_info->property_interface))) + return NO_SUCH_PROPERTY_INTERFACE; + else if ((call_info->property_handler = + pa_hashmap_get(call_info->iface_entry->property_handlers, call_info->property))) + return FOUND_GET_PROPERTY; + else + return NO_SUCH_PROPERTY; + + } else + return find_handler_by_property(call_info); + + } else if (pa_streq(call_info->method, "Set")) { + DBusMessageIter msg_iter; + + call_info->expected_method_sig = "ssv"; + if (!pa_streq(call_info->method_sig, call_info->expected_method_sig)) + return INVALID_METHOD_SIG; + + pa_assert_se(dbus_message_iter_init(call_info->message, &msg_iter)); + + dbus_message_iter_get_basic(&msg_iter, &call_info->property_interface); + pa_assert_se(dbus_message_iter_next(&msg_iter)); + dbus_message_iter_get_basic(&msg_iter, &call_info->property); + pa_assert_se(dbus_message_iter_next(&msg_iter)); + + dbus_message_iter_recurse(&msg_iter, &call_info->variant_iter); + + call_info->property_sig = dbus_message_iter_get_signature(&call_info->variant_iter); + + if (*call_info->property_interface) { + if (!(call_info->iface_entry = pa_hashmap_get(call_info->obj_entry->interfaces, call_info->property_interface))) + return NO_SUCH_PROPERTY_INTERFACE; + + else if ((call_info->property_handler = + pa_hashmap_get(call_info->iface_entry->property_handlers, call_info->property))) { + call_info->expected_property_sig = call_info->property_handler->type; + + if (pa_streq(call_info->property_sig, call_info->expected_property_sig)) + return FOUND_SET_PROPERTY; + else + return INVALID_PROPERTY_SIG; + + } else + return NO_SUCH_PROPERTY; + + } else + return find_handler_by_property(call_info); + + } else + pa_assert_not_reached(); +} + +static enum find_result_t find_handler(struct call_info *call_info) { + pa_assert(call_info); + + if (call_info->interface) { + if (pa_streq(call_info->interface, DBUS_INTERFACE_PROPERTIES)) + return find_handler_from_properties_call(call_info); + + else if (!(call_info->iface_entry = pa_hashmap_get(call_info->obj_entry->interfaces, call_info->interface))) + return NO_SUCH_INTERFACE; + + else if ((call_info->method_handler = pa_hashmap_get(call_info->iface_entry->method_handlers, call_info->method))) + return FOUND_METHOD; + + else + return NO_SUCH_METHOD; + + } else { /* The method call doesn't contain an interface. */ + if (pa_streq(call_info->method, "Get") || pa_streq(call_info->method, "Set") || pa_streq(call_info->method, "GetAll")) { + if (find_handler_by_method(call_info) == FOUND_METHOD) + /* The object has a method named Get, Set or GetAll in some other interface than .Properties. */ + return FOUND_METHOD; + else + /* Assume this is a .Properties call. */ + return find_handler_from_properties_call(call_info); + + } else /* This is not a .Properties call. */ + return find_handler_by_method(call_info); + } +} + +static DBusHandlerResult handle_message_cb(DBusConnection *connection, DBusMessage *message, void *user_data) { + pa_dbus_protocol *p = user_data; + struct call_info call_info; + + pa_assert(connection); + pa_assert(message); + pa_assert(p); + pa_assert(p->objects); + + if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + pa_log_debug("Received message: destination = %s, interface = %s, member = %s", + dbus_message_get_path(message), + dbus_message_get_interface(message), + dbus_message_get_member(message)); + + call_info.message = message; + pa_assert_se(call_info.obj_entry = pa_hashmap_get(p->objects, dbus_message_get_path(message))); + call_info.interface = dbus_message_get_interface(message); + pa_assert_se(call_info.method = dbus_message_get_member(message)); + pa_assert_se(call_info.method_sig = dbus_message_get_signature(message)); + + if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") || + (!dbus_message_get_interface(message) && dbus_message_has_member(message, "Introspect"))) { + pa_dbus_send_basic_value_reply(connection, message, DBUS_TYPE_STRING, &call_info.obj_entry->introspection); + goto finish; + } + + switch (find_handler(&call_info)) { + case FOUND_GET_PROPERTY: + call_info.property_handler->get_cb(connection, message, call_info.iface_entry->userdata); + break; + + case FOUND_SET_PROPERTY: + call_info.property_handler->set_cb(connection, message, &call_info.variant_iter, call_info.iface_entry->userdata); + break; + + case FOUND_METHOD: + call_info.method_handler->receive_cb(connection, message, call_info.iface_entry->userdata); + break; + + case FOUND_GET_ALL: + if (call_info.iface_entry->get_all_properties_cb) + call_info.iface_entry->get_all_properties_cb(connection, message, call_info.iface_entry->userdata); + else { + DBusMessage *dummy_reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + + pa_assert_se(dummy_reply = dbus_message_new_method_return(message)); + dbus_message_iter_init_append(dummy_reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); + pa_assert_se(dbus_connection_send(connection, dummy_reply, NULL)); + dbus_message_unref(dummy_reply); + } + break; + + case PROPERTY_ACCESS_DENIED: + pa_dbus_send_error(connection, message, DBUS_ERROR_ACCESS_DENIED, + "%s access denied for property %s", call_info.method, call_info.property); + break; + + case NO_SUCH_METHOD: + pa_dbus_send_error(connection, message, DBUS_ERROR_UNKNOWN_METHOD, "No such method: %s", call_info.method); + break; + + case NO_SUCH_PROPERTY: + pa_dbus_send_error(connection, message, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "No such property: %s", call_info.property); + break; + + case INVALID_METHOD_SIG: + pa_dbus_send_error(connection, message, DBUS_ERROR_INVALID_ARGS, + "Invalid signature for method %s: '%s'. Expected '%s'.", + call_info.method, call_info.method_sig, call_info.expected_method_sig); + break; + + case INVALID_PROPERTY_SIG: + pa_dbus_send_error(connection, message, DBUS_ERROR_INVALID_ARGS, + "Invalid signature for property %s: '%s'. Expected '%s'.", + call_info.property, call_info.property_sig, call_info.expected_property_sig); + + default: + pa_assert_not_reached(); + } + +finish: + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusObjectPathVTable vtable = { + .unregister_function = NULL, + .message_function = handle_message_cb, + .dbus_internal_pad1 = NULL, + .dbus_internal_pad2 = NULL, + .dbus_internal_pad3 = NULL, + .dbus_internal_pad4 = NULL +}; + +static void register_object(pa_dbus_protocol *p, struct object_entry *obj_entry) { + struct connection_entry *conn_entry; + void *state = NULL; + + pa_assert(p); + pa_assert(obj_entry); + + PA_HASHMAP_FOREACH(conn_entry, p->connections, state) + pa_assert_se(dbus_connection_register_object_path(conn_entry->connection, obj_entry->path, &vtable, p)); +} + +static pa_dbus_arg_info *copy_args(const pa_dbus_arg_info *src, unsigned n) { + pa_dbus_arg_info *dst; + unsigned i; + + if (n == 0) + return NULL; + + pa_assert(src); + + dst = pa_xnew0(pa_dbus_arg_info, n); + + for (i = 0; i < n; ++i) { + dst[i].name = pa_xstrdup(src[i].name); + dst[i].type = pa_xstrdup(src[i].type); + dst[i].direction = pa_xstrdup(src[i].direction); + } + + return dst; +} + +static pa_hashmap *create_method_handlers(const pa_dbus_interface_info *info) { + pa_hashmap *handlers; + unsigned i; + + pa_assert(info); + pa_assert(info->method_handlers || info->n_method_handlers == 0); + + handlers = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + for (i = 0; i < info->n_method_handlers; ++i) { + pa_dbus_method_handler *h = pa_xnew(pa_dbus_method_handler, 1); + h->method_name = pa_xstrdup(info->method_handlers[i].method_name); + h->arguments = copy_args(info->method_handlers[i].arguments, info->method_handlers[i].n_arguments); + h->n_arguments = info->method_handlers[i].n_arguments; + h->receive_cb = info->method_handlers[i].receive_cb; + + pa_hashmap_put(handlers, h->method_name, h); + } + + return handlers; +} + +static pa_hashmap *extract_method_signatures(pa_hashmap *method_handlers) { + pa_hashmap *signatures = NULL; + pa_dbus_method_handler *handler = NULL; + void *state = NULL; + pa_strbuf *sig_buf = NULL; + unsigned i = 0; + + pa_assert(method_handlers); + + signatures = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + PA_HASHMAP_FOREACH(handler, method_handlers, state) { + sig_buf = pa_strbuf_new(); + + for (i = 0; i < handler->n_arguments; ++i) { + if (pa_streq(handler->arguments[i].direction, "in")) + pa_strbuf_puts(sig_buf, handler->arguments[i].type); + } + + pa_hashmap_put(signatures, handler->method_name, pa_strbuf_tostring_free(sig_buf)); + } + + return signatures; +} + +static pa_hashmap *create_property_handlers(const pa_dbus_interface_info *info) { + pa_hashmap *handlers; + unsigned i = 0; + + pa_assert(info); + pa_assert(info->property_handlers || info->n_property_handlers == 0); + + handlers = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + for (i = 0; i < info->n_property_handlers; ++i) { + pa_dbus_property_handler *h = pa_xnew(pa_dbus_property_handler, 1); + h->property_name = pa_xstrdup(info->property_handlers[i].property_name); + h->type = pa_xstrdup(info->property_handlers[i].type); + h->get_cb = info->property_handlers[i].get_cb; + h->set_cb = info->property_handlers[i].set_cb; + + pa_hashmap_put(handlers, h->property_name, h); + } + + return handlers; +} + +static pa_dbus_signal_info *copy_signals(const pa_dbus_interface_info *info) { + pa_dbus_signal_info *dst; + unsigned i; + + pa_assert(info); + + if (info->n_signals == 0) + return NULL; + + pa_assert(info->signals); + + dst = pa_xnew(pa_dbus_signal_info, info->n_signals); + + for (i = 0; i < info->n_signals; ++i) { + dst[i].name = pa_xstrdup(info->signals[i].name); + dst[i].arguments = copy_args(info->signals[i].arguments, info->signals[i].n_arguments); + dst[i].n_arguments = info->signals[i].n_arguments; + } + + return dst; +} + +int pa_dbus_protocol_add_interface(pa_dbus_protocol *p, + const char *path, + const pa_dbus_interface_info *info, + void *userdata) { + struct object_entry *obj_entry; + struct interface_entry *iface_entry; + pa_bool_t obj_entry_created = FALSE; + + pa_assert(p); + pa_assert(path); + pa_assert(info); + pa_assert(info->name); + pa_assert(info->method_handlers || info->n_method_handlers == 0); + pa_assert(info->property_handlers || info->n_property_handlers == 0); + pa_assert(info->get_all_properties_cb || info->n_property_handlers == 0); + pa_assert(info->signals || info->n_signals == 0); + + if (!(obj_entry = pa_hashmap_get(p->objects, path))) { + obj_entry = pa_xnew(struct object_entry, 1); + obj_entry->path = pa_xstrdup(path); + obj_entry->interfaces = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + obj_entry->introspection = NULL; + + pa_hashmap_put(p->objects, path, obj_entry); + obj_entry_created = TRUE; + } + + if (pa_hashmap_get(obj_entry->interfaces, info->name) != NULL) + goto fail; /* The interface was already registered. */ + + iface_entry = pa_xnew(struct interface_entry, 1); + iface_entry->name = pa_xstrdup(info->name); + iface_entry->method_handlers = create_method_handlers(info); + iface_entry->method_signatures = extract_method_signatures(iface_entry->method_handlers); + iface_entry->property_handlers = create_property_handlers(info); + iface_entry->get_all_properties_cb = info->get_all_properties_cb; + iface_entry->signals = copy_signals(info); + iface_entry->n_signals = info->n_signals; + iface_entry->userdata = userdata; + pa_hashmap_put(obj_entry->interfaces, iface_entry->name, iface_entry); + + update_introspection(obj_entry); + + if (obj_entry_created) + register_object(p, obj_entry); + + pa_log_debug("Interface %s added for object %s", iface_entry->name, obj_entry->path); + + return 0; + +fail: + if (obj_entry_created) { + pa_hashmap_remove(p->objects, path); + pa_xfree(obj_entry); + } + + return -1; +} + +static void unregister_object(pa_dbus_protocol *p, struct object_entry *obj_entry) { + struct connection_entry *conn_entry; + void *state = NULL; + + pa_assert(p); + pa_assert(obj_entry); + + PA_HASHMAP_FOREACH(conn_entry, p->connections, state) + pa_assert_se(dbus_connection_unregister_object_path(conn_entry->connection, obj_entry->path)); +} + +static void method_handler_free_cb(void *p, void *userdata) { + pa_dbus_method_handler *h = p; + unsigned i; + + pa_assert(h); + + pa_xfree((char *) h->method_name); + + for (i = 0; i < h->n_arguments; ++i) { + pa_xfree((char *) h->arguments[i].name); + pa_xfree((char *) h->arguments[i].type); + pa_xfree((char *) h->arguments[i].direction); + } + + pa_xfree((pa_dbus_arg_info *) h->arguments); +} + +static void method_signature_free_cb(void *p, void *userdata) { + pa_assert(p); + + pa_xfree(p); +} + +static void property_handler_free_cb(void *p, void *userdata) { + pa_dbus_property_handler *h = p; + + pa_assert(h); + + pa_xfree((char *) h->property_name); + pa_xfree((char *) h->type); + + pa_xfree(h); +} + +int pa_dbus_protocol_remove_interface(pa_dbus_protocol *p, const char* path, const char* interface) { + struct object_entry *obj_entry; + struct interface_entry *iface_entry; + unsigned i; + + pa_assert(p); + pa_assert(path); + pa_assert(interface); + + if (!(obj_entry = pa_hashmap_get(p->objects, path))) + return -1; + + if (!(iface_entry = pa_hashmap_remove(obj_entry->interfaces, interface))) + return -1; + + update_introspection(obj_entry); + + pa_log_debug("Interface %s removed from object %s", iface_entry->name, obj_entry->path); + + pa_xfree(iface_entry->name); + pa_hashmap_free(iface_entry->method_handlers, method_handler_free_cb, NULL); + pa_hashmap_free(iface_entry->method_signatures, method_signature_free_cb, NULL); + pa_hashmap_free(iface_entry->property_handlers, property_handler_free_cb, NULL); + + for (i = 0; i < iface_entry->n_signals; ++i) { + unsigned j; + + pa_xfree((char *) iface_entry->signals[i].name); + + for (j = 0; j < iface_entry->signals[i].n_arguments; ++j) { + pa_xfree((char *) iface_entry->signals[i].arguments[j].name); + pa_xfree((char *) iface_entry->signals[i].arguments[j].type); + pa_assert(iface_entry->signals[i].arguments[j].direction == NULL); + } + + pa_xfree((pa_dbus_arg_info *) iface_entry->signals[i].arguments); + } + + pa_xfree(iface_entry->signals); + pa_xfree(iface_entry); + + if (pa_hashmap_isempty(obj_entry->interfaces)) { + unregister_object(p, obj_entry); + + pa_hashmap_remove(p->objects, path); + pa_xfree(obj_entry->path); + pa_hashmap_free(obj_entry->interfaces, NULL, NULL); + pa_xfree(obj_entry->introspection); + pa_xfree(obj_entry); + } + + return 0; +} + +static void register_all_objects(pa_dbus_protocol *p, DBusConnection *conn) { + struct object_entry *obj_entry; + void *state = NULL; + + pa_assert(p); + pa_assert(conn); + + PA_HASHMAP_FOREACH(obj_entry, p->objects, state) + pa_assert_se(dbus_connection_register_object_path(conn, obj_entry->path, &vtable, p)); +} + +int pa_dbus_protocol_register_connection(pa_dbus_protocol *p, DBusConnection *conn, pa_client *client) { + struct connection_entry *conn_entry; + + pa_assert(p); + pa_assert(conn); + pa_assert(client); + + if (pa_hashmap_get(p->connections, conn)) + return -1; /* The connection was already registered. */ + + register_all_objects(p, conn); + + conn_entry = pa_xnew(struct connection_entry, 1); + conn_entry->connection = dbus_connection_ref(conn); + conn_entry->client = client; + conn_entry->listening_for_all_signals = FALSE; + conn_entry->all_signals_objects = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + conn_entry->listening_signals = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + pa_hashmap_put(p->connections, conn, conn_entry); + + return 0; +} + +static void unregister_all_objects(pa_dbus_protocol *p, DBusConnection *conn) { + struct object_entry *obj_entry; + void *state = NULL; + + pa_assert(p); + pa_assert(conn); + + PA_HASHMAP_FOREACH(obj_entry, p->objects, state) + pa_assert_se(dbus_connection_unregister_object_path(conn, obj_entry->path)); +} + +static void free_listened_object_name_cb(void *p, void *userdata) { + pa_assert(p); + + pa_xfree(p); +} + +static void free_listening_signals_idxset_cb(void *p, void *userdata) { + pa_idxset *set = p; + + pa_assert(set); + + pa_idxset_free(set, free_listened_object_name_cb, NULL); +} + +int pa_dbus_protocol_unregister_connection(pa_dbus_protocol *p, DBusConnection *conn) { + struct connection_entry *conn_entry; + + pa_assert(p); + pa_assert(conn); + + if (!(conn_entry = pa_hashmap_remove(p->connections, conn))) + return -1; + + unregister_all_objects(p, conn); + + dbus_connection_unref(conn_entry->connection); + pa_idxset_free(conn_entry->all_signals_objects, free_listened_object_name_cb, NULL); + pa_hashmap_free(conn_entry->listening_signals, free_listening_signals_idxset_cb, NULL); + pa_xfree(conn_entry); + + return 0; +} + +pa_client *pa_dbus_protocol_get_client(pa_dbus_protocol *p, DBusConnection *conn) { + struct connection_entry *conn_entry; + + pa_assert(p); + pa_assert(conn); + + if (!(conn_entry = pa_hashmap_get(p->connections, conn))) + return NULL; + + return conn_entry->client; +} + +void pa_dbus_protocol_add_signal_listener( + pa_dbus_protocol *p, + DBusConnection *conn, + const char *signal, + char **objects, + unsigned n_objects) { + struct connection_entry *conn_entry; + pa_idxset *object_set; + char *object_path; + unsigned i; + + pa_assert(p); + pa_assert(conn); + pa_assert(objects || n_objects == 0); + + pa_assert_se((conn_entry = pa_hashmap_get(p->connections, conn))); + + /* all_signals_objects will either be emptied or replaced with new objects, + * so we empty it here unconditionally. If listening_for_all_signals is + * currently FALSE, the idxset is empty already. */ + while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL))) + pa_xfree(object_path); + + if (signal) { + conn_entry->listening_for_all_signals = FALSE; + + /* Replace the old object list with a new one. */ + if ((object_set = pa_hashmap_remove(conn_entry->listening_signals, signal))) + pa_idxset_free(object_set, free_listened_object_name_cb, NULL); + object_set = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + + for (i = 0; i < n_objects; ++i) + pa_idxset_put(object_set, pa_xstrdup(objects[i]), NULL); + + pa_hashmap_put(conn_entry->listening_signals, signal, object_set); + + } else { + conn_entry->listening_for_all_signals = TRUE; + + /* We're not interested in individual signals anymore, so let's empty + * listening_signals. */ + while ((object_set = pa_hashmap_steal_first(conn_entry->listening_signals))) + pa_idxset_free(object_set, free_listened_object_name_cb, NULL); + + for (i = 0; i < n_objects; ++i) + pa_idxset_put(conn_entry->all_signals_objects, pa_xstrdup(objects[i]), NULL); + } +} + +void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal) { + struct connection_entry *conn_entry; + pa_idxset *object_set; + + pa_assert(p); + pa_assert(conn); + + pa_assert_se((conn_entry = pa_hashmap_get(p->connections, conn))); + + if (signal) { + if ((object_set = pa_hashmap_get(conn_entry->listening_signals, signal))) + pa_idxset_free(object_set, free_listened_object_name_cb, NULL); + + } else { + char *object_path; + + conn_entry->listening_for_all_signals = FALSE; + + while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL))) + pa_xfree(object_path); + + while ((object_set = pa_hashmap_steal_first(conn_entry->listening_signals))) + pa_idxset_free(object_set, free_listened_object_name_cb, NULL); + } +} + +void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal) { + struct connection_entry *conn_entry; + void *state = NULL; + pa_idxset *object_set; + DBusMessage *signal_copy; + char *signal_string; + + pa_assert(p); + pa_assert(signal); + pa_assert(dbus_message_get_type(signal) == DBUS_MESSAGE_TYPE_SIGNAL); + pa_assert_se(dbus_message_get_interface(signal)); + pa_assert_se(dbus_message_get_member(signal)); + + signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal), dbus_message_get_member(signal)); + + PA_HASHMAP_FOREACH(conn_entry, p->connections, state) { + if ((conn_entry->listening_for_all_signals /* Case 1: listening for all signals */ + && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal), NULL) + || pa_idxset_isempty(conn_entry->all_signals_objects))) + + || (!conn_entry->listening_for_all_signals /* Case 2: not listening for all signals */ + && (object_set = pa_hashmap_get(conn_entry->listening_signals, signal_string)) + && (pa_idxset_get_by_data(object_set, dbus_message_get_path(signal), NULL) + || pa_idxset_isempty(object_set)))) { + + pa_assert_se(signal_copy = dbus_message_copy(signal)); + pa_assert_se(dbus_connection_send(conn_entry->connection, signal_copy, NULL)); + dbus_message_unref(signal_copy); + } + } + + pa_xfree(signal_string); +} + +const char **pa_dbus_protocol_get_extensions(pa_dbus_protocol *p, unsigned *n) { + const char **extensions; + const char *ext_name; + void *state = NULL; + unsigned i = 0; + + pa_assert(p); + pa_assert(n); + + *n = pa_idxset_size(p->extensions); + + if (*n <= 0) + return NULL; + + extensions = pa_xnew(const char *, *n); + + while ((ext_name = pa_idxset_iterate(p->extensions, &state, NULL))) + extensions[i++] = ext_name; + + return extensions; +} + +int pa_dbus_protocol_register_extension(pa_dbus_protocol *p, const char *name) { + char *internal_name; + + pa_assert(p); + pa_assert(name); + + internal_name = pa_xstrdup(name); + + if (pa_idxset_put(p->extensions, internal_name, NULL) < 0) { + pa_xfree(internal_name); + return -1; + } + + pa_hook_fire(&p->hooks[PA_DBUS_PROTOCOL_HOOK_EXTENSION_REGISTERED], internal_name); + + return 0; +} + +int pa_dbus_protocol_unregister_extension(pa_dbus_protocol *p, const char *name) { + char *internal_name; + + pa_assert(p); + pa_assert(name); + + if (!(internal_name = pa_idxset_remove_by_data(p->extensions, name, NULL))) + return -1; + + pa_hook_fire(&p->hooks[PA_DBUS_PROTOCOL_HOOK_EXTENSION_UNREGISTERED], internal_name); + + pa_xfree(internal_name); + + return 0; +} + +pa_hook_slot *pa_dbus_protocol_hook_connect( + pa_dbus_protocol *p, + pa_dbus_protocol_hook_t hook, + pa_hook_priority_t prio, + pa_hook_cb_t cb, + void *data) { + pa_assert(p); + pa_assert(hook < PA_DBUS_PROTOCOL_HOOK_MAX); + pa_assert(cb); + + return pa_hook_connect(&p->hooks[hook], prio, cb, data); +} diff --git a/src/pulsecore/protocol-dbus.h b/src/pulsecore/protocol-dbus.h new file mode 100644 index 00000000..6d100f7c --- /dev/null +++ b/src/pulsecore/protocol-dbus.h @@ -0,0 +1,217 @@ +#ifndef fooprotocoldbushfoo +#define fooprotocoldbushfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio 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. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <dbus/dbus.h> + +#include <pulsecore/core.h> +#include <pulsecore/macro.h> + +#define PA_DBUS_DEFAULT_PORT 24883 +#define PA_DBUS_SOCKET_NAME "dbus-socket" + +#define PA_DBUS_SYSTEM_SOCKET_PATH PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_DBUS_SOCKET_NAME + +#define PA_DBUS_CORE_INTERFACE "org.PulseAudio.Core1" +#define PA_DBUS_CORE_OBJECT_PATH "/org/pulseaudio/core1" + +#define PA_DBUS_ERROR_NO_SUCH_PROPERTY PA_DBUS_CORE_INTERFACE ".NoSuchPropertyError" +#define PA_DBUS_ERROR_NOT_FOUND PA_DBUS_CORE_INTERFACE ".NotFoundError" + +/* Returns the default address of the server type in the escaped form. For + * PA_SERVER_TYPE_NONE an empty string is returned. The caller frees the + * string. */ +char *pa_get_dbus_address_from_server_type(pa_server_type_t server_type); + +typedef struct pa_dbus_protocol pa_dbus_protocol; + +/* This function either creates a new pa_dbus_protocol object, or if one + * already exists, increases the reference count. */ +pa_dbus_protocol* pa_dbus_protocol_get(pa_core *c); + +pa_dbus_protocol* pa_dbus_protocol_ref(pa_dbus_protocol *p); +void pa_dbus_protocol_unref(pa_dbus_protocol *p); + +/* Called when a received message needs handling. Completely ignoring the + * message isn't a good idea; if you can't handle the message, reply with an + * error. + * + * The message signature is already checked against the introspection data, so + * you don't have to do that yourself. + * + * All messages are method calls. */ +typedef void (*pa_dbus_receive_cb_t)(DBusConnection *conn, DBusMessage *msg, void *userdata); + +/* A specialized version of pa_dbus_receive_cb_t: the additional iterator + * argument points to the element inside the new value variant. + * + * The new value signature is checked against the introspection data, so you + * don't have to do that yourself. */ +typedef void (*pa_dbus_set_property_cb_t)(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); + +typedef struct pa_dbus_arg_info { + const char *name; + const char *type; + const char *direction; /* NULL for signal arguments. */ +} pa_dbus_arg_info; + +typedef struct pa_dbus_signal_info { + const char *name; + const pa_dbus_arg_info *arguments; /* NULL, if the signal has no args. */ + unsigned n_arguments; +} pa_dbus_signal_info; + +typedef struct pa_dbus_method_handler { + const char *method_name; + const pa_dbus_arg_info *arguments; /* NULL, if the method has no args. */ + unsigned n_arguments; + pa_dbus_receive_cb_t receive_cb; +} pa_dbus_method_handler; + +typedef struct pa_dbus_property_handler { + const char *property_name; + const char *type; + + /* The access mode for the property is determined by checking whether + * get_cb or set_cb is NULL. */ + pa_dbus_receive_cb_t get_cb; + pa_dbus_set_property_cb_t set_cb; +} pa_dbus_property_handler; + +typedef struct pa_dbus_interface_info { + const char* name; + const pa_dbus_method_handler *method_handlers; /* NULL, if the interface has no methods. */ + unsigned n_method_handlers; + const pa_dbus_property_handler *property_handlers; /* NULL, if the interface has no properties. */ + unsigned n_property_handlers; + const pa_dbus_receive_cb_t get_all_properties_cb; /* May be NULL, in which case GetAll returns an error. */ + const pa_dbus_signal_info *signals; /* NULL, if the interface has no signals. */ + unsigned n_signals; +} pa_dbus_interface_info; + + +/* The following functions may only be called from the main thread. */ + +/* Registers the given interface to the given object path. It doesn't matter + * whether or not the object has already been registered; if it is, then its + * interface set is extended. + * + * Introspection requests are handled automatically. + * + * Userdata is passed to all the callbacks. + * + * Fails and returns a negative number if the object already has the interface + * registered. */ +int pa_dbus_protocol_add_interface(pa_dbus_protocol *p, const char *path, const pa_dbus_interface_info *info, void *userdata); + +/* Returns a negative number if the given object doesn't have the given + * interface registered. */ +int pa_dbus_protocol_remove_interface(pa_dbus_protocol *p, const char* path, const char* interface); + +/* Fails and returns a negative number if the connection is already + * registered. */ +int pa_dbus_protocol_register_connection(pa_dbus_protocol *p, DBusConnection *conn, pa_client *client); + +/* Returns a negative number if the connection isn't registered. */ +int pa_dbus_protocol_unregister_connection(pa_dbus_protocol *p, DBusConnection *conn); + +/* Returns NULL if the connection isn't registered. */ +pa_client *pa_dbus_protocol_get_client(pa_dbus_protocol *p, DBusConnection *conn); + +/* Enables signal receiving for the given connection. The connection must have + * been registered earlier. The signal string must contain both the signal + * interface and the signal name, concatenated using a period as the separator. + * + * If the signal argument is NULL, all signals will be sent to the connection, + * otherwise calling this function only adds the given signal to the list of + * signals that will be delivered to the connection. + * + * The objects argument is a list of object paths. If the list is not empty, + * only signals from the given objects are delivered. If this function is + * called multiple time for the same connection and signal, the latest call + * always replaces the previous object list. */ +void pa_dbus_protocol_add_signal_listener( + pa_dbus_protocol *p, + DBusConnection *conn, + const char *signal, + char **objects, + unsigned n_objects); + +/* Disables the delivery of the signal for the given connection. The connection + * must have been registered. If signal is NULL, all signals are disabled. If + * signal is non-NULL and _add_signal_listener() was previously called with + * NULL signal (causing all signals to be enabled), this function doesn't do + * anything. Also, if the signal wasn't enabled before, this function doesn't + * do anything in that case either. */ +void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal); + +/* Sends the given signal to all interested clients. By default no signals are + * sent - clients have to explicitly to request signals by calling + * .Core1.ListenForSignal. That method's handler then calls + * pa_dbus_protocol_add_signal_listener(). */ +void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal); + +/* Returns an array of extension identifier strings. The strings pointers point + * to the internal copies, so don't free the strings. The caller must free the + * array, however. Also, do not save the returned pointer or any of the string + * pointers, because the contained strings may be freed at any time. If you + * need to save the array, copy it. */ +const char **pa_dbus_protocol_get_extensions(pa_dbus_protocol *p, unsigned *n); + +/* Modules that want to provide a D-Bus interface for clients should register + * an identifier that the clients can use to check whether the additional + * functionality is available. + * + * This function registers the extension with the given name. It is recommended + * that the name follows the D-Bus interface naming convention, so that the + * names remain unique in case there will be at some point in the future + * extensions that aren't included with the main PulseAudio source tree. For + * in-tree extensions the convention is to use the org.PulseAudio.Ext + * namespace. + * + * It is suggested that the name contains a version number, and whenever the + * extension interface is modified in non-backwards compatible way, the version + * number is incremented. + * + * Fails and returns a negative number if the extension is already registered. + */ +int pa_dbus_protocol_register_extension(pa_dbus_protocol *p, const char *name); + +/* Returns a negative number if the extension isn't registered. */ +int pa_dbus_protocol_unregister_extension(pa_dbus_protocol *p, const char *name); + +/* All hooks have the pa_dbus_protocol object as hook data. */ +typedef enum pa_dbus_protocol_hook { + PA_DBUS_PROTOCOL_HOOK_EXTENSION_REGISTERED, /* Extension name as call data. */ + PA_DBUS_PROTOCOL_HOOK_EXTENSION_UNREGISTERED, /* Extension name as call data. */ + PA_DBUS_PROTOCOL_HOOK_MAX +} pa_dbus_protocol_hook_t; + +pa_hook_slot *pa_dbus_protocol_hook_connect( + pa_dbus_protocol *p, + pa_dbus_protocol_hook_t hook, + pa_hook_priority_t prio, + pa_hook_cb_t cb, + void *data); + +#endif diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c index 62f3397e..745c7de0 100644 --- a/src/pulsecore/svolume_mmx.c +++ b/src/pulsecore/svolume_mmx.c @@ -152,7 +152,7 @@ pa_volume_s16ne_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi " emms \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp) - : "r" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } @@ -228,7 +228,7 @@ pa_volume_s16re_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi " emms \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp) - : "r" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } diff --git a/src/pulsecore/svolume_sse.c b/src/pulsecore/svolume_sse.c index 5276bda4..1cc4e0aa 100644 --- a/src/pulsecore/svolume_sse.c +++ b/src/pulsecore/svolume_sse.c @@ -149,7 +149,7 @@ pa_volume_s16ne_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, uns "8: \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp) - : "r" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } @@ -237,7 +237,7 @@ pa_volume_s16re_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, uns "8: \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp) - : "r" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } |