Release 0.10.0

This commit is contained in:
Lars Immisch
2023-04-16 00:08:27 +02:00
parent cbca6be937
commit 6b17f924e4
15 changed files with 1021 additions and 895 deletions
+3 -1
View File
@@ -419,7 +419,9 @@ table.footnote td {
}
dl {
margin: 0;
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding: 0;
}
+26 -29
View File
@@ -4,7 +4,7 @@
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@@ -222,7 +222,7 @@ table.modindextable td {
/* -- general body styles --------------------------------------------------- */
div.body {
min-width: 450px;
min-width: 360px;
max-width: 800px;
}
@@ -237,16 +237,6 @@ a.headerlink {
visibility: hidden;
}
a.brackets:before,
span.brackets > a:before{
content: "[";
}
a.brackets:after,
span.brackets > a:after {
content: "]";
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
@@ -335,12 +325,16 @@ p.sidebar-title {
font-weight: bold;
}
nav.contents,
aside.topic,
div.admonition, div.topic, blockquote {
clear: left;
}
/* -- topics ---------------------------------------------------------------- */
nav.contents,
aside.topic,
div.topic {
border: 1px solid #ccc;
padding: 7px;
@@ -379,6 +373,8 @@ div.body p.centered {
div.sidebar > :last-child,
aside.sidebar > :last-child,
nav.contents > :last-child,
aside.topic > :last-child,
div.topic > :last-child,
div.admonition > :last-child {
margin-bottom: 0;
@@ -386,6 +382,8 @@ div.admonition > :last-child {
div.sidebar::after,
aside.sidebar::after,
nav.contents::after,
aside.topic::after,
div.topic::after,
div.admonition::after,
blockquote::after {
@@ -428,10 +426,6 @@ table.docutils td, table.docutils th {
border-bottom: 1px solid #aaa;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
@@ -615,19 +609,26 @@ ul.simple p {
margin-bottom: 0;
}
dl.footnote > dt,
dl.citation > dt {
aside.footnote > span,
div.citation > span {
float: left;
margin-right: 0.5em;
}
dl.footnote > dd,
dl.citation > dd {
aside.footnote > span:last-of-type,
div.citation > span:last-of-type {
padding-right: 0.5em;
}
aside.footnote > p {
margin-left: 2em;
}
div.citation > p {
margin-left: 4em;
}
aside.footnote > p:last-of-type,
div.citation > p:last-of-type {
margin-bottom: 0em;
}
dl.footnote > dd:after,
dl.citation > dd:after {
aside.footnote > p:last-of-type:after,
div.citation > p:last-of-type:after {
content: "";
clear: both;
}
@@ -644,10 +645,6 @@ dl.field-list > dt {
padding-right: 5px;
}
dl.field-list > dt:after {
content: ":";
}
dl.field-list > dd {
padding-left: 0.5em;
margin-top: 0em;
+107 -309
View File
@@ -2,357 +2,155 @@
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
* Base JavaScript utilities for all Sphinx HTML documentation.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
"use strict";
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
"TEXTAREA",
"INPUT",
"SELECT",
"BUTTON",
]);
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/
jQuery.urldecode = function(x) {
if (!x) {
return x
const _ready = (callback) => {
if (document.readyState !== "loading") {
callback();
} else {
document.addEventListener("DOMContentLoaded", callback);
}
return decodeURIComponent(x.replace(/\+/g, ' '));
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var bbox = node.parentElement.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
this.initOnKeyListeners();
const Documentation = {
init: () => {
Documentation.initDomainIndexTable();
Documentation.initOnKeyListeners();
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
LOCALE : 'unknown',
TRANSLATIONS: {},
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
LOCALE: "unknown",
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated === 'undefined')
return string;
return (typeof translated === 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated === 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
if (!body.length) {
body = $('body');
}
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('<p class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
.appendTo($('#searchbox'));
gettext: (string) => {
const translated = Documentation.TRANSLATIONS[string];
switch (typeof translated) {
case "undefined":
return string; // no translation
case "string":
return translated; // translation exists
default:
return translated[0]; // (singular, plural) translation tuple exists
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) === 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
ngettext: (singular, plural, n) => {
const translated = Documentation.TRANSLATIONS[singular];
if (typeof translated !== "undefined")
return translated[Documentation.PLURAL_EXPR(n)];
return n === 1 ? singular : plural;
},
addTranslations: (catalog) => {
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
Documentation.PLURAL_EXPR = new Function(
"n",
`return (${catalog.plural_expr})`
);
Documentation.LOCALE = catalog.locale;
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
var url = new URL(window.location);
url.searchParams.delete('highlight');
window.history.replaceState({}, '', url);
},
/**
* helper function to focus on search bar
*/
focusSearchBar : function() {
$('input[name=q]').first().focus();
focusSearchBar: () => {
document.querySelectorAll("input[name=q]")[0]?.focus();
},
/**
* make the url absolute
* Initialise the domain index toggle buttons
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
initDomainIndexTable: () => {
const toggler = (el) => {
const idNumber = el.id.substr(7);
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
if (el.src.substr(-9) === "minus.png") {
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
toggledRows.forEach((el) => (el.style.display = "none"));
} else {
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
toggledRows.forEach((el) => (el.style.display = ""));
}
};
const togglerElements = document.querySelectorAll("img.toggler");
togglerElements.forEach((el) =>
el.addEventListener("click", (event) => toggler(event.currentTarget))
);
togglerElements.forEach((el) => (el.style.display = ""));
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this === '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
},
initOnKeyListeners: function() {
initOnKeyListeners: () => {
// only install a listener if it is really needed
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS)
return;
if (
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
)
return;
$(document).keydown(function(event) {
var activeElementType = document.activeElement.tagName;
// don't navigate when in search box, textarea, dropdown or button
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
&& activeElementType !== 'BUTTON') {
if (event.altKey || event.ctrlKey || event.metaKey)
return;
document.addEventListener("keydown", (event) => {
// bail for input elements
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
// bail with special keys
if (event.altKey || event.ctrlKey || event.metaKey) return;
if (!event.shiftKey) {
switch (event.key) {
case 'ArrowLeft':
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS)
break;
var prevHref = $('link[rel="prev"]').prop('href');
if (prevHref) {
window.location.href = prevHref;
return false;
}
break;
case 'ArrowRight':
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS)
break;
var nextHref = $('link[rel="next"]').prop('href');
if (nextHref) {
window.location.href = nextHref;
return false;
}
break;
case 'Escape':
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS)
break;
Documentation.hideSearchWords();
return false;
}
}
// some keyboard layouts may need Shift to get /
if (!event.shiftKey) {
switch (event.key) {
case '/':
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS)
break;
Documentation.focusSearchBar();
return false;
case "ArrowLeft":
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
const prevLink = document.querySelector('link[rel="prev"]');
if (prevLink && prevLink.href) {
window.location.href = prevLink.href;
event.preventDefault();
}
break;
case "ArrowRight":
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
const nextLink = document.querySelector('link[rel="next"]');
if (nextLink && nextLink.href) {
window.location.href = nextLink.href;
event.preventDefault();
}
break;
}
}
// some keyboard layouts may need Shift to get /
switch (event.key) {
case "/":
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
Documentation.focusSearchBar();
event.preventDefault();
}
});
}
},
};
// quick alias for translations
_ = Documentation.gettext;
const _ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});
_ready(Documentation.init);
+5 -5
View File
@@ -1,8 +1,8 @@
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #eeffcc; }
.highlight .c { color: #408090; font-style: italic } /* Comment */
+423 -382
View File
@@ -4,22 +4,24 @@
*
* Sphinx JavaScript utilities for the full-text search.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
"use strict";
if (!Scorer) {
/**
* Simple result scoring code.
*/
/**
* Simple result scoring code.
*/
if (typeof Scorer === "undefined") {
var Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [filename, title, anchor, descr, score]
// The function takes a result array [docname, title, anchor, descr, score, filename]
// and returns the new score.
/*
score: function(result) {
return result[4];
score: result => {
const [docname, title, anchor, descr, score, filename] = result
return score
},
*/
@@ -28,9 +30,11 @@ if (!Scorer) {
// or matches in the last dotted part of the object name
objPartialMatch: 6,
// Additive scores depending on the priority of the object
objPrio: {0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5}, // used to be unimportantResults
objPrio: {
0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5, // used to be unimportantResults
},
// Used when the priority is not in the mapping.
objPrioDefault: 0,
@@ -39,452 +43,495 @@ if (!Scorer) {
partialTitle: 7,
// query found in terms
term: 5,
partialTerm: 2
partialTerm: 2,
};
}
if (!splitQuery) {
function splitQuery(query) {
return query.split(/\s+/);
const _removeChildren = (element) => {
while (element && element.lastChild) element.removeChild(element.lastChild);
};
/**
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
*/
const _escapeRegExp = (string) =>
string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
const _displayItem = (item, searchTerms) => {
const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT;
const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
const [docName, title, anchor, descr, score, _filename] = item;
let listItem = document.createElement("li");
let requestUrl;
let linkUrl;
if (docBuilder === "dirhtml") {
// dirhtml builder
let dirname = docName + "/";
if (dirname.match(/\/index\/$/))
dirname = dirname.substring(0, dirname.length - 6);
else if (dirname === "index/") dirname = "";
requestUrl = docUrlRoot + dirname;
linkUrl = requestUrl;
} else {
// normal html builders
requestUrl = docUrlRoot + docName + docFileSuffix;
linkUrl = docName + docLinkSuffix;
}
let linkEl = listItem.appendChild(document.createElement("a"));
linkEl.href = linkUrl + anchor;
linkEl.dataset.score = score;
linkEl.innerHTML = title;
if (descr)
listItem.appendChild(document.createElement("span")).innerHTML =
" (" + descr + ")";
else if (showSearchSummary)
fetch(requestUrl)
.then((responseData) => responseData.text())
.then((data) => {
if (data)
listItem.appendChild(
Search.makeSearchSummary(data, searchTerms)
);
});
Search.output.appendChild(listItem);
};
const _finishSearch = (resultCount) => {
Search.stopPulse();
Search.title.innerText = _("Search Results");
if (!resultCount)
Search.status.innerText = Documentation.gettext(
"Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
);
else
Search.status.innerText = _(
`Search finished, found ${resultCount} page(s) matching the search query.`
);
};
const _displayNextItem = (
results,
resultCount,
searchTerms
) => {
// results left, load the summary and display it
// this is intended to be dynamic (don't sub resultsCount)
if (results.length) {
_displayItem(results.pop(), searchTerms);
setTimeout(
() => _displayNextItem(results, resultCount, searchTerms),
5
);
}
// search finished, update title and status message
else _finishSearch(resultCount);
};
/**
* Default splitQuery function. Can be overridden in ``sphinx.search`` with a
* custom function per language.
*
* The regular expression works by splitting the string on consecutive characters
* that are not Unicode letters, numbers, underscores, or emoji characters.
* This is the same as ``\W+`` in Python, preserving the surrogate pair area.
*/
if (typeof splitQuery === "undefined") {
var splitQuery = (query) => query
.split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
.filter(term => term) // remove remaining empty strings
}
/**
* Search Module
*/
var Search = {
const Search = {
_index: null,
_queued_query: null,
_pulse_status: -1,
_index : null,
_queued_query : null,
_pulse_status : -1,
htmlToText : function(htmlString) {
var virtualDocument = document.implementation.createHTMLDocument('virtual');
var htmlElement = $(htmlString, virtualDocument);
htmlElement.find('.headerlink').remove();
docContent = htmlElement.find('[role=main]')[0];
if(docContent === undefined) {
console.warn("Content block not found. Sphinx search tries to obtain it " +
"via '[role=main]'. Could you check your theme or template.");
return "";
}
return docContent.textContent || docContent.innerText;
htmlToText: (htmlString) => {
const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html');
htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() });
const docContent = htmlElement.querySelector('[role="main"]');
if (docContent !== undefined) return docContent.textContent;
console.warn(
"Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template."
);
return "";
},
init : function() {
var params = $.getQueryParameters();
if (params.q) {
var query = params.q[0];
$('input[name="q"]')[0].value = query;
this.performSearch(query);
}
init: () => {
const query = new URLSearchParams(window.location.search).get("q");
document
.querySelectorAll('input[name="q"]')
.forEach((el) => (el.value = query));
if (query) Search.performSearch(query);
},
loadIndex : function(url) {
$.ajax({type: "GET", url: url, data: null,
dataType: "script", cache: true,
complete: function(jqxhr, textstatus) {
if (textstatus != "success") {
document.getElementById("searchindexloader").src = url;
}
}});
},
loadIndex: (url) =>
(document.body.appendChild(document.createElement("script")).src = url),
setIndex : function(index) {
var q;
this._index = index;
if ((q = this._queued_query) !== null) {
this._queued_query = null;
Search.query(q);
setIndex: (index) => {
Search._index = index;
if (Search._queued_query !== null) {
const query = Search._queued_query;
Search._queued_query = null;
Search.query(query);
}
},
hasIndex : function() {
return this._index !== null;
},
hasIndex: () => Search._index !== null,
deferQuery : function(query) {
this._queued_query = query;
},
deferQuery: (query) => (Search._queued_query = query),
stopPulse : function() {
this._pulse_status = 0;
},
stopPulse: () => (Search._pulse_status = -1),
startPulse : function() {
if (this._pulse_status >= 0)
return;
function pulse() {
var i;
startPulse: () => {
if (Search._pulse_status >= 0) return;
const pulse = () => {
Search._pulse_status = (Search._pulse_status + 1) % 4;
var dotString = '';
for (i = 0; i < Search._pulse_status; i++)
dotString += '.';
Search.dots.text(dotString);
if (Search._pulse_status > -1)
window.setTimeout(pulse, 500);
}
Search.dots.innerText = ".".repeat(Search._pulse_status);
if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
};
pulse();
},
/**
* perform a search for something (or wait until index is loaded)
*/
performSearch : function(query) {
performSearch: (query) => {
// create the required interface elements
this.out = $('#search-results');
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
this.dots = $('<span></span>').appendTo(this.title);
this.status = $('<p class="search-summary">&nbsp;</p>').appendTo(this.out);
this.output = $('<ul class="search"/>').appendTo(this.out);
const searchText = document.createElement("h2");
searchText.textContent = _("Searching");
const searchSummary = document.createElement("p");
searchSummary.classList.add("search-summary");
searchSummary.innerText = "";
const searchList = document.createElement("ul");
searchList.classList.add("search");
$('#search-progress').text(_('Preparing search...'));
this.startPulse();
const out = document.getElementById("search-results");
Search.title = out.appendChild(searchText);
Search.dots = Search.title.appendChild(document.createElement("span"));
Search.status = out.appendChild(searchSummary);
Search.output = out.appendChild(searchList);
const searchProgress = document.getElementById("search-progress");
// Some themes don't use the search progress node
if (searchProgress) {
searchProgress.innerText = _("Preparing search...");
}
Search.startPulse();
// index already loaded, the browser was quick!
if (this.hasIndex())
this.query(query);
else
this.deferQuery(query);
if (Search.hasIndex()) Search.query(query);
else Search.deferQuery(query);
},
/**
* execute search (requires search index to be loaded)
*/
query : function(query) {
var i;
query: (query) => {
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const titles = Search._index.titles;
const allTitles = Search._index.alltitles;
const indexEntries = Search._index.indexentries;
// stem the searchterms and add them to the correct list
var stemmer = new Stemmer();
var searchterms = [];
var excluded = [];
var hlterms = [];
var tmp = splitQuery(query);
var objectterms = [];
for (i = 0; i < tmp.length; i++) {
if (tmp[i] !== "") {
objectterms.push(tmp[i].toLowerCase());
}
// stem the search terms and add them to the correct list
const stemmer = new Stemmer();
const searchTerms = new Set();
const excludedTerms = new Set();
const highlightTerms = new Set();
const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
splitQuery(query.trim()).forEach((queryTerm) => {
const queryTermLower = queryTerm.toLowerCase();
// maybe skip this "word"
// stopwords array is from language_data.js
if (
stopwords.indexOf(queryTermLower) !== -1 ||
queryTerm.match(/^\d+$/)
)
return;
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i] === "") {
// skip this "word"
continue;
}
// stem the word
var word = stemmer.stemWord(tmp[i].toLowerCase());
var toAppend;
let word = stemmer.stemWord(queryTermLower);
// select the correct list
if (word[0] == '-') {
toAppend = excluded;
word = word.substr(1);
}
if (word[0] === "-") excludedTerms.add(word.substr(1));
else {
toAppend = searchterms;
hlterms.push(tmp[i].toLowerCase());
searchTerms.add(word);
highlightTerms.add(queryTermLower);
}
// only add if not already in the list
if (!$u.contains(toAppend, word))
toAppend.push(word);
});
if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js
localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" "))
}
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
// console.debug('SEARCH: searching for:');
// console.info('required: ', searchterms);
// console.info('excluded: ', excluded);
// console.debug("SEARCH: searching for:");
// console.info("required: ", [...searchTerms]);
// console.info("excluded: ", [...excludedTerms]);
// prepare search
var terms = this._index.terms;
var titleterms = this._index.titleterms;
// array of [docname, title, anchor, descr, score, filename]
let results = [];
_removeChildren(document.getElementById("search-progress"));
// array of [filename, title, anchor, descr, score]
var results = [];
$('#search-progress').empty();
const queryLower = query.toLowerCase();
for (const [title, foundTitles] of Object.entries(allTitles)) {
if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) {
for (const [file, id] of foundTitles) {
let score = Math.round(100 * queryLower.length / title.length)
results.push([
docNames[file],
titles[file] !== title ? `${titles[file]} > ${title}` : title,
id !== null ? "#" + id : "",
null,
score,
filenames[file],
]);
}
}
}
// search for explicit entries in index directives
for (const [entry, foundEntries] of Object.entries(indexEntries)) {
if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) {
for (const [file, id] of foundEntries) {
let score = Math.round(100 * queryLower.length / entry.length)
results.push([
docNames[file],
titles[file],
id ? "#" + id : "",
null,
score,
filenames[file],
]);
}
}
}
// lookup as object
for (i = 0; i < objectterms.length; i++) {
var others = [].concat(objectterms.slice(0, i),
objectterms.slice(i+1, objectterms.length));
results = results.concat(this.performObjectSearch(objectterms[i], others));
}
objectTerms.forEach((term) =>
results.push(...Search.performObjectSearch(term, objectTerms))
);
// lookup as search terms in fulltext
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
results.push(...Search.performTermsSearch(searchTerms, excludedTerms));
// let the scorer override scores with a custom scoring function
if (Scorer.score) {
for (i = 0; i < results.length; i++)
results[i][4] = Scorer.score(results[i]);
}
if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item)));
// now sort the results by score (in opposite order of appearance, since the
// display function below uses pop() to retrieve items) and then
// alphabetically
results.sort(function(a, b) {
var left = a[4];
var right = b[4];
if (left > right) {
return 1;
} else if (left < right) {
return -1;
} else {
results.sort((a, b) => {
const leftScore = a[4];
const rightScore = b[4];
if (leftScore === rightScore) {
// same score: sort alphabetically
left = a[1].toLowerCase();
right = b[1].toLowerCase();
return (left > right) ? -1 : ((left < right) ? 1 : 0);
const leftTitle = a[1].toLowerCase();
const rightTitle = b[1].toLowerCase();
if (leftTitle === rightTitle) return 0;
return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
}
return leftScore > rightScore ? 1 : -1;
});
// remove duplicate search results
// note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
let seen = new Set();
results = results.reverse().reduce((acc, result) => {
let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(',');
if (!seen.has(resultStr)) {
acc.push(result);
seen.add(resultStr);
}
return acc;
}, []);
results = results.reverse();
// for debugging
//Search.lastresults = results.slice(); // a copy
//console.info('search results:', Search.lastresults);
// console.info("search results:", Search.lastresults);
// print the results
var resultCount = results.length;
function displayNextItem() {
// results left, load the summary and display it
if (results.length) {
var item = results.pop();
var listItem = $('<li></li>');
var requestUrl = "";
var linkUrl = "";
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
// dirhtml builder
var dirname = item[0] + '/';
if (dirname.match(/\/index\/$/)) {
dirname = dirname.substring(0, dirname.length-6);
} else if (dirname == 'index/') {
dirname = '';
}
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
linkUrl = requestUrl;
} else {
// normal html builders
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
}
listItem.append($('<a/>').attr('href',
linkUrl +
highlightstring + item[2]).html(item[1]));
if (item[3]) {
listItem.append($('<span> (' + item[3] + ')</span>'));
Search.output.append(listItem);
setTimeout(function() {
displayNextItem();
}, 5);
} else if (DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY) {
$.ajax({url: requestUrl,
dataType: "text",
complete: function(jqxhr, textstatus) {
var data = jqxhr.responseText;
if (data !== '' && data !== undefined) {
var summary = Search.makeSearchSummary(data, searchterms, hlterms);
if (summary) {
listItem.append(summary);
}
}
Search.output.append(listItem);
setTimeout(function() {
displayNextItem();
}, 5);
}});
} else {
// just display title
Search.output.append(listItem);
setTimeout(function() {
displayNextItem();
}, 5);
}
}
// search finished, update title and status message
else {
Search.stopPulse();
Search.title.text(_('Search Results'));
if (!resultCount)
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
else
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
Search.status.fadeIn(500);
}
}
displayNextItem();
_displayNextItem(results, results.length, searchTerms);
},
/**
* search for object names
*/
performObjectSearch : function(object, otherterms) {
var filenames = this._index.filenames;
var docnames = this._index.docnames;
var objects = this._index.objects;
var objnames = this._index.objnames;
var titles = this._index.titles;
performObjectSearch: (object, objectTerms) => {
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const objects = Search._index.objects;
const objNames = Search._index.objnames;
const titles = Search._index.titles;
var i;
var results = [];
const results = [];
for (var prefix in objects) {
for (var iMatch = 0; iMatch != objects[prefix].length; ++iMatch) {
var match = objects[prefix][iMatch];
var name = match[4];
var fullname = (prefix ? prefix + '.' : '') + name;
var fullnameLower = fullname.toLowerCase()
if (fullnameLower.indexOf(object) > -1) {
var score = 0;
var parts = fullnameLower.split('.');
// check for different match types: exact matches of full name or
// "last name" (i.e. last dotted part)
if (fullnameLower == object || parts[parts.length - 1] == object) {
score += Scorer.objNameMatch;
// matches in last name
} else if (parts[parts.length - 1].indexOf(object) > -1) {
score += Scorer.objPartialMatch;
}
var objname = objnames[match[1]][2];
var title = titles[match[0]];
// If more than one term searched for, we require other words to be
// found in the name/title/description
if (otherterms.length > 0) {
var haystack = (prefix + ' ' + name + ' ' +
objname + ' ' + title).toLowerCase();
var allfound = true;
for (i = 0; i < otherterms.length; i++) {
if (haystack.indexOf(otherterms[i]) == -1) {
allfound = false;
break;
}
}
if (!allfound) {
continue;
}
}
var descr = objname + _(', in ') + title;
const objectSearchCallback = (prefix, match) => {
const name = match[4]
const fullname = (prefix ? prefix + "." : "") + name;
const fullnameLower = fullname.toLowerCase();
if (fullnameLower.indexOf(object) < 0) return;
var anchor = match[3];
if (anchor === '')
anchor = fullname;
else if (anchor == '-')
anchor = objnames[match[1]][1] + '-' + fullname;
// add custom score for some objects according to scorer
if (Scorer.objPrio.hasOwnProperty(match[2])) {
score += Scorer.objPrio[match[2]];
} else {
score += Scorer.objPrioDefault;
}
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
}
let score = 0;
const parts = fullnameLower.split(".");
// check for different match types: exact matches of full name or
// "last name" (i.e. last dotted part)
if (fullnameLower === object || parts.slice(-1)[0] === object)
score += Scorer.objNameMatch;
else if (parts.slice(-1)[0].indexOf(object) > -1)
score += Scorer.objPartialMatch; // matches in last name
const objName = objNames[match[1]][2];
const title = titles[match[0]];
// If more than one term searched for, we require other words to be
// found in the name/title/description
const otherTerms = new Set(objectTerms);
otherTerms.delete(object);
if (otherTerms.size > 0) {
const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
if (
[...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
)
return;
}
}
let anchor = match[3];
if (anchor === "") anchor = fullname;
else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
const descr = objName + _(", in ") + title;
// add custom score for some objects according to scorer
if (Scorer.objPrio.hasOwnProperty(match[2]))
score += Scorer.objPrio[match[2]];
else score += Scorer.objPrioDefault;
results.push([
docNames[match[0]],
fullname,
"#" + anchor,
descr,
score,
filenames[match[0]],
]);
};
Object.keys(objects).forEach((prefix) =>
objects[prefix].forEach((array) =>
objectSearchCallback(prefix, array)
)
);
return results;
},
/**
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
*/
escapeRegExp : function(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
},
/**
* search for full-text terms in the index
*/
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
var docnames = this._index.docnames;
var filenames = this._index.filenames;
var titles = this._index.titles;
performTermsSearch: (searchTerms, excludedTerms) => {
// prepare search
const terms = Search._index.terms;
const titleTerms = Search._index.titleterms;
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const titles = Search._index.titles;
var i, j, file;
var fileMap = {};
var scoreMap = {};
var results = [];
const scoreMap = new Map();
const fileMap = new Map();
// perform the search on the required terms
for (i = 0; i < searchterms.length; i++) {
var word = searchterms[i];
var files = [];
var _o = [
{files: terms[word], score: Scorer.term},
{files: titleterms[word], score: Scorer.title}
searchTerms.forEach((word) => {
const files = [];
const arr = [
{ files: terms[word], score: Scorer.term },
{ files: titleTerms[word], score: Scorer.title },
];
// add support for partial matches
if (word.length > 2) {
var word_regex = this.escapeRegExp(word);
for (var w in terms) {
if (w.match(word_regex) && !terms[word]) {
_o.push({files: terms[w], score: Scorer.partialTerm})
}
}
for (var w in titleterms) {
if (w.match(word_regex) && !titleterms[word]) {
_o.push({files: titleterms[w], score: Scorer.partialTitle})
}
}
const escapedWord = _escapeRegExp(word);
Object.keys(terms).forEach((term) => {
if (term.match(escapedWord) && !terms[word])
arr.push({ files: terms[term], score: Scorer.partialTerm });
});
Object.keys(titleTerms).forEach((term) => {
if (term.match(escapedWord) && !titleTerms[word])
arr.push({ files: titleTerms[word], score: Scorer.partialTitle });
});
}
// no match but word was a required one
if ($u.every(_o, function(o){return o.files === undefined;})) {
break;
}
if (arr.every((record) => record.files === undefined)) return;
// found search word in contents
$u.each(_o, function(o) {
var _files = o.files;
if (_files === undefined)
return
arr.forEach((record) => {
if (record.files === undefined) return;
if (_files.length === undefined)
_files = [_files];
files = files.concat(_files);
let recordFiles = record.files;
if (recordFiles.length === undefined) recordFiles = [recordFiles];
files.push(...recordFiles);
// set score for the word in each file to Scorer.term
for (j = 0; j < _files.length; j++) {
file = _files[j];
if (!(file in scoreMap))
scoreMap[file] = {};
scoreMap[file][word] = o.score;
}
// set score for the word in each file
recordFiles.forEach((file) => {
if (!scoreMap.has(file)) scoreMap.set(file, {});
scoreMap.get(file)[word] = record.score;
});
});
// create the mapping
for (j = 0; j < files.length; j++) {
file = files[j];
if (file in fileMap && fileMap[file].indexOf(word) === -1)
fileMap[file].push(word);
else
fileMap[file] = [word];
}
}
files.forEach((file) => {
if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1)
fileMap.get(file).push(word);
else fileMap.set(file, [word]);
});
});
// now check if the files don't contain excluded terms
for (file in fileMap) {
var valid = true;
const results = [];
for (const [file, wordList] of fileMap) {
// check if all requirements are matched
var filteredTermCount = // as search terms with length < 3 are discarded: ignore
searchterms.filter(function(term){return term.length > 2}).length
// as search terms with length < 3 are discarded
const filteredTermCount = [...searchTerms].filter(
(term) => term.length > 2
).length;
if (
fileMap[file].length != searchterms.length &&
fileMap[file].length != filteredTermCount
) continue;
wordList.length !== searchTerms.size &&
wordList.length !== filteredTermCount
)
continue;
// ensure that none of the excluded terms is in the search result
for (i = 0; i < excluded.length; i++) {
if (terms[excluded[i]] == file ||
titleterms[excluded[i]] == file ||
$u.contains(terms[excluded[i]] || [], file) ||
$u.contains(titleterms[excluded[i]] || [], file)) {
valid = false;
break;
}
}
if (
[...excludedTerms].some(
(term) =>
terms[term] === file ||
titleTerms[term] === file ||
(terms[term] || []).includes(file) ||
(titleTerms[term] || []).includes(file)
)
)
break;
// if we have still a valid result we can add it to the result list
if (valid) {
// select one (max) score for the file.
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
}
// select one (max) score for the file.
const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w]));
// add result to the result list
results.push([
docNames[file],
titles[file],
"",
null,
score,
filenames[file],
]);
}
return results;
},
@@ -492,34 +539,28 @@ var Search = {
/**
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words, hlwords is the list of normal, unstemmed
* words. the first one is used to find the occurrence, the
* latter for highlighting it.
* of stemmed words.
*/
makeSearchSummary : function(htmlText, keywords, hlwords) {
var text = Search.htmlToText(htmlText);
if (text == "") {
return null;
}
var textLower = text.toLowerCase();
var start = 0;
$.each(keywords, function() {
var i = textLower.indexOf(this.toLowerCase());
if (i > -1)
start = i;
});
start = Math.max(start - 120, 0);
var excerpt = ((start > 0) ? '...' : '') +
$.trim(text.substr(start, 240)) +
((start + 240 - text.length) ? '...' : '');
var rv = $('<p class="context"></p>').text(excerpt);
$.each(hlwords, function() {
rv = rv.highlightText(this, 'highlighted');
});
return rv;
}
makeSearchSummary: (htmlText, keywords) => {
const text = Search.htmlToText(htmlText);
if (text === "") return null;
const textLower = text.toLowerCase();
const actualStartPosition = [...keywords]
.map((k) => textLower.indexOf(k.toLowerCase()))
.filter((i) => i > -1)
.slice(-1)[0];
const startWithContext = Math.max(actualStartPosition - 120, 0);
const top = startWithContext === 0 ? "" : "...";
const tail = startWithContext + 240 < text.length ? "..." : "";
let summary = document.createElement("p");
summary.classList.add("context");
summary.textContent = top + text.substr(startWithContext, 240).trim() + tail;
return summary;
},
};
$(document).ready(function() {
Search.init();
});
_ready(Search.init);
+31 -6
View File
File diff suppressed because one or more lines are too long
+40 -7
View File
@@ -1,17 +1,16 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>Index &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<link rel="index" title="Index" href="#" />
<link rel="search" title="Search" href="search.html" />
@@ -36,8 +35,10 @@
<div class="genindex-jumpbox">
<a href="#A"><strong>A</strong></a>
| <a href="#C"><strong>C</strong></a>
| <a href="#D"><strong>D</strong></a>
| <a href="#G"><strong>G</strong></a>
| <a href="#H"><strong>H</strong></a>
| <a href="#I"><strong>I</strong></a>
| <a href="#M"><strong>M</strong></a>
| <a href="#P"><strong>P</strong></a>
| <a href="#R"><strong>R</strong></a>
@@ -75,6 +76,26 @@
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="libalsaaudio.html#alsaaudio.cards">cards() (in module alsaaudio)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.Mixer.close">close() (alsaaudio.Mixer method)</a>
<ul>
<li><a href="libalsaaudio.html#alsaaudio.PCM.close">(alsaaudio.PCM method)</a>
</li>
</ul></li>
</ul></td>
</tr></table>
<h2 id="D">D</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="libalsaaudio.html#alsaaudio.PCM.drain">drain() (alsaaudio.PCM method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="libalsaaudio.html#alsaaudio.PCM.drop">drop() (alsaaudio.PCM method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.PCM.dumpinfo">dumpinfo() (alsaaudio.PCM method)</a>
</li>
</ul></td>
</tr></table>
@@ -113,6 +134,14 @@
</ul></td>
</tr></table>
<h2 id="I">I</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="libalsaaudio.html#alsaaudio.PCM.info">info() (alsaaudio.PCM method)</a>, <a href="libalsaaudio.html#id0">[1]</a>
</li>
</ul></td>
</tr></table>
<h2 id="M">M</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
@@ -176,6 +205,8 @@
<li><a href="libalsaaudio.html#alsaaudio.PCM.set_tstamp_type">set_tstamp_type() (alsaaudio.PCM method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.PCM.setchannels">setchannels() (alsaaudio.PCM method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.Mixer.setenum">setenum() (alsaaudio.Mixer method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.PCM.setformat">setformat() (alsaaudio.PCM method)</a>
</li>
@@ -190,6 +221,8 @@
<li><a href="libalsaaudio.html#alsaaudio.Mixer.setrec">setrec() (alsaaudio.Mixer method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.Mixer.setvolume">setvolume() (alsaaudio.Mixer method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.PCM.state">state() (alsaaudio.PCM method)</a>
</li>
<li><a href="libalsaaudio.html#alsaaudio.Mixer.switchcap">switchcap() (alsaaudio.Mixer method)</a>
</li>
@@ -256,7 +289,7 @@
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<script>document.getElementById('searchbox').style.display = "block"</script>
@@ -273,8 +306,8 @@
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
</div>
+15 -12
View File
@@ -1,18 +1,17 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>alsaaudio documentation &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>alsaaudio documentation &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Introduction" href="pyalsaaudio.html" />
@@ -33,7 +32,7 @@
<div class="body" role="main">
<section id="alsaaudio-documentation">
<h1>alsaaudio documentation<a class="headerlink" href="#alsaaudio-documentation" title="Permalink to this headline"></a></h1>
<h1>alsaaudio documentation<a class="headerlink" href="#alsaaudio-documentation" title="Permalink to this heading"></a></h1>
<div class="toctree-wrapper compound">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul>
@@ -46,6 +45,10 @@
<li class="toctree-l1"><a class="reference internal" href="pyalsaaudio.html#testing">Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="terminology.html">PCM Terminology and Concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="libalsaaudio.html"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a><ul>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#alsaaudio.pcms"><code class="docutils literal notranslate"><span class="pre">pcms()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#alsaaudio.cards"><code class="docutils literal notranslate"><span class="pre">cards()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#alsaaudio.mixers"><code class="docutils literal notranslate"><span class="pre">mixers()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#alsaaudio.asoundlib_version"><code class="docutils literal notranslate"><span class="pre">asoundlib_version()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#pcm-objects">PCM Objects</a></li>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#mixer-objects">Mixer Objects</a></li>
<li class="toctree-l2"><a class="reference internal" href="libalsaaudio.html#examples">Examples</a></li>
@@ -55,20 +58,20 @@
</div>
</section>
<section id="download">
<h1>Download<a class="headerlink" href="#download" title="Permalink to this headline"></a></h1>
<h1>Download<a class="headerlink" href="#download" title="Permalink to this heading"></a></h1>
<ul class="simple">
<li><p><a class="reference external" href="https://pypi.python.org/pypi/pyalsaaudio">Download from pypi</a></p></li>
</ul>
</section>
<section id="github">
<h1>Github<a class="headerlink" href="#github" title="Permalink to this headline"></a></h1>
<h1>Github<a class="headerlink" href="#github" title="Permalink to this heading"></a></h1>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/larsimmisch/pyalsaaudio/">Repository</a></p></li>
<li><p><a class="reference external" href="https://github.com/larsimmisch/pyalsaaudio/issues">Bug tracker</a></p></li>
</ul>
</section>
<section id="indices-and-tables">
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline"></a></h1>
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this heading"></a></h1>
<ul class="simple">
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
@@ -120,7 +123,7 @@
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<script>document.getElementById('searchbox').style.display = "block"</script>
@@ -137,8 +140,8 @@
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
|
<a href="_sources/index.rst.txt"
+301 -76
View File
@@ -1,18 +1,18 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>alsaaudio &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>alsaaudio &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<script async="async" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="prev" title="PCM Terminology and Concepts" href="terminology.html" />
@@ -33,7 +33,7 @@
<div class="body" role="main">
<section id="module-alsaaudio">
<span id="alsaaudio"></span><h1><a class="reference internal" href="#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a><a class="headerlink" href="#module-alsaaudio" title="Permalink to this headline"></a></h1>
<span id="alsaaudio"></span><h1><a class="reference internal" href="#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a><a class="headerlink" href="#module-alsaaudio" title="Permalink to this heading"></a></h1>
<p>The <a class="reference internal" href="#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a> module defines functions and classes for using ALSA.</p>
<dl class="py function">
<dt class="sig sig-object py" id="alsaaudio.pcms">
@@ -69,13 +69,15 @@ instead.</p>
<dl class="py function">
<dt class="sig sig-object py" id="alsaaudio.mixers">
<span class="sig-prename descclassname"><span class="pre">alsaaudio.</span></span><span class="sig-name descname"><span class="pre">mixers</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cardindex</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">device</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'default'</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.mixers" title="Permalink to this definition"></a></dt>
<span class="sig-prename descclassname"><span class="pre">alsaaudio.</span></span><span class="sig-name descname"><span class="pre">mixers</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cardindex</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">device</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'default'</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.mixers" title="Permalink to this definition"></a></dt>
<dd><p>List the available mixers. The arguments are:</p>
<ul class="simple">
<ul>
<li><p><em>cardindex</em> - the card index. If this argument is given, the device name
is constructed as: hw:<em>cardindex</em> and
the <cite>device</cite> keyword argument is ignored. <code class="docutils literal notranslate"><span class="pre">0</span></code> is the first hardware sound
card.</p></li>
card.</p>
<p><strong>Note:</strong> This should not be used, as it bypasses most of ALSAs configuration.</p>
</li>
<li><p><em>device</em> - the name of the device on which the mixer resides. The default
is <code class="docutils literal notranslate"><span class="pre">'default'</span></code>.</p></li>
</ul>
@@ -110,13 +112,13 @@ device, not the mixers for the first card.</p></li>
</dd></dl>
<section id="pcm-objects">
<span id="id1"></span><h2>PCM Objects<a class="headerlink" href="#pcm-objects" title="Permalink to this headline"></a></h2>
<span id="id1"></span><h2>PCM Objects<a class="headerlink" href="#pcm-objects" title="Permalink to this heading"></a></h2>
<p>PCM objects in <a class="reference internal" href="#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a> can play or capture (record) PCM
sound through speakers or a microphone. The PCM constructor takes the
following arguments:</p>
<dl class="py class">
<dt class="sig sig-object py" id="alsaaudio.PCM">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">alsaaudio.</span></span><span class="sig-name descname"><span class="pre">PCM</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_NORMAL</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">rate</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">44100</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channels</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_FORMAT_S16_LE</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">periodsize</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">32</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">device</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'default'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cardindex</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM" title="Permalink to this definition"></a></dt>
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">alsaaudio.</span></span><span class="sig-name descname"><span class="pre">PCM</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">type</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_NORMAL</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">rate</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">44100</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channels</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">2</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_FORMAT_S16_LE</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">periodsize</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">32</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">periods</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">4</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">device</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'default'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cardindex</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-1</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM" title="Permalink to this definition"></a></dt>
<dd><p>This class is used to represent a PCM device (either for playback and
recording). The arguments are:</p>
<ul class="simple">
@@ -130,10 +132,6 @@ recording). The arguments are:</p>
The default value is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_FORMAT_S16_LE</span></code>.</p></li>
</ul>
<table class="docutils align-default">
<colgroup>
<col style="width: 24%" />
<col style="width: 76%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Format</p></th>
<th class="head"><p>Description</p></th>
@@ -144,7 +142,7 @@ The default value is <code class="xref py py-const docutils literal notranslate"
<td><p>Signed 8 bit samples for each channel</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">PCM_FORMAT_U8</span></code></p></td>
<td><p>Signed 8 bit samples for each channel</p></td>
<td><p>Unsigned 8 bit samples for each channel</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">PCM_FORMAT_S16_LE</span></code></p></td>
<td><p>Signed 16 bit samples for each channel Little Endian byte order)</p></td>
@@ -223,17 +221,27 @@ The default value is <code class="xref py py-const docutils literal notranslate"
</tr>
</tbody>
</table>
<ul class="simple">
<li><p><em>periodsize</em> - the period size in frames. Each write should consist of <em>periodsize</em> frames. The default value is 32.</p></li>
<ul>
<li><p><em>periodsize</em> - the period size in frames.
Make sure you understand <a class="reference internal" href="terminology.html#term-period"><span class="std std-ref">the meaning of periods</span></a>.
The default value is 32, which is below the actual minimum of most devices,
and will therefore likely be larger in practice.</p></li>
<li><p><em>periods</em> - the number of periods in the buffer. The default value is 4.</p></li>
<li><p><em>device</em> - the name of the PCM device that should be used (for example
a value from the output of <a class="reference internal" href="#alsaaudio.pcms" title="alsaaudio.pcms"><code class="xref py py-func docutils literal notranslate"><span class="pre">pcms()</span></code></a>). The default value is
<code class="docutils literal notranslate"><span class="pre">'default'</span></code>.</p></li>
<li><p><em>cardindex</em> - the card index. If this argument is given, the device name
is constructed as hw:<em>cardindex</em> and
the <cite>device</cite> keyword argument is ignored.
<code class="docutils literal notranslate"><span class="pre">0</span></code> is the first hardware sound card.</p></li>
<code class="docutils literal notranslate"><span class="pre">0</span></code> is the first hardware sound card.</p>
<p><strong>Note:</strong> This should not be used, as it bypasses most of ALSAs configuration.</p>
</li>
</ul>
<p>This will construct a PCM object with the given settings.</p>
<p><em>Changed in 0.10:</em></p>
<ul class="simple">
<li><p>Added the optional named parameter <cite>periods</cite>.</p></li>
</ul>
<p><em>Changed in 0.9:</em></p>
<ul class="simple">
<li><p>Added the optional named parameters <cite>rate</cite>, <cite>channels</cite>, <cite>format</cite> and <cite>periodsize</cite>.</p></li>
@@ -249,6 +257,159 @@ name of the card. This was always fragile and broke some legitimate usecases.</p
</dd></dl>
<p>PCM objects have the following methods:</p>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.info">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">info</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.info" title="Permalink to this definition"></a></dt>
<dd><p>The info function returns a dictionary containing the configuration of a PCM device. As ALSA takes into account limitations of the hardware and software devices the configuration achieved might not correspond to the values used during creation. There is therefore a need to check the realised configuration before processing the sound coming from the device or before sending sound to a device. A small subset of parameters can be set, but cannot be queried. These parameters are stored by alsaaudio and returned as they were given by the user, to distinguish them from parameters retrieved from ALSA these parameters have a name prefixed with <strong>“ (call value) “</strong>. Yet another set of properties derives directly from the hardware and can be obtained through ALSA.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Key</p></th>
<th class="head"><p>Description (Reference)</p></th>
<th class="head"><p>Type</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>name</p></td>
<td><p>PCM():device</p></td>
<td><p>string</p></td>
</tr>
<tr class="row-odd"><td><p>card_no</p></td>
<td><p><em>index of card</em></p></td>
<td><p>integer (negative indicates device not associable with a card)</p></td>
</tr>
<tr class="row-even"><td><p>device_no</p></td>
<td><p><em>index of PCM device</em></p></td>
<td><p>integer</p></td>
</tr>
<tr class="row-odd"><td><p>subdevice_no</p></td>
<td><p><em>index of PCM subdevice</em></p></td>
<td><p>integer</p></td>
</tr>
<tr class="row-even"><td><p>state</p></td>
<td><p><em>name of PCM state</em></p></td>
<td><p>string</p></td>
</tr>
<tr class="row-odd"><td><p>access_type</p></td>
<td><p><em>name of PCM access type</em></p></td>
<td><p>string</p></td>
</tr>
<tr class="row-even"><td><p>(call value) type</p></td>
<td><p>PCM():type</p></td>
<td><p>integer</p></td>
</tr>
<tr class="row-odd"><td><p>(call value) type_name</p></td>
<td><p>PCM():type</p></td>
<td><p>string</p></td>
</tr>
<tr class="row-even"><td><p>(call value) mode</p></td>
<td><p>PCM():mode</p></td>
<td><p>integer</p></td>
</tr>
<tr class="row-odd"><td><p>(call value) mode_name</p></td>
<td><p>PCM():mode</p></td>
<td><p>string</p></td>
</tr>
<tr class="row-even"><td><p>format</p></td>
<td><p>PCM():format</p></td>
<td><p>integer</p></td>
</tr>
<tr class="row-odd"><td><p>format_name</p></td>
<td><p>PCM():format</p></td>
<td><p>string</p></td>
</tr>
<tr class="row-even"><td><p>format_description</p></td>
<td><p>PCM():format</p></td>
<td><p>string</p></td>
</tr>
<tr class="row-odd"><td><p>subformat_name</p></td>
<td><p><em>name of PCM subformat</em></p></td>
<td><p>string</p></td>
</tr>
<tr class="row-even"><td><p>subformat_description</p></td>
<td><p><em>description of subformat</em></p></td>
<td><p>string</p></td>
</tr>
<tr class="row-odd"><td><p>channels</p></td>
<td><p>PCM():channels</p></td>
<td><p>integer</p></td>
</tr>
<tr class="row-even"><td><p>rate</p></td>
<td><p>PCM():rate</p></td>
<td><p>integer (Hz)</p></td>
</tr>
<tr class="row-odd"><td><p>period_time</p></td>
<td><p><em>period duration</em></p></td>
<td><p>integer (<span class="math notranslate nohighlight">\(\mu s\)</span>)</p></td>
</tr>
<tr class="row-even"><td><p>period_size</p></td>
<td><p>PCM():period_size</p></td>
<td><p>integer (frames)</p></td>
</tr>
<tr class="row-odd"><td><p>buffer_time</p></td>
<td><p><em>buffer time</em></p></td>
<td><p>integer (<span class="math notranslate nohighlight">\(\mu s\)</span>) (negative indicates error)</p></td>
</tr>
<tr class="row-even"><td><p>buffer_size</p></td>
<td><p><em>buffer size</em></p></td>
<td><p>integer (frames) (negative indicates error)</p></td>
</tr>
<tr class="row-odd"><td><p>get_periods</p></td>
<td><p><em>approx. periods in buffer</em></p></td>
<td><p>integer (negative indicates error)</p></td>
</tr>
<tr class="row-even"><td><p>rate_numden</p></td>
<td><p><em>numerator, denominator</em></p></td>
<td><p>tuple (integer (Hz), integer (Hz))</p></td>
</tr>
<tr class="row-odd"><td><p>significant_bits</p></td>
<td><p><em>significant bits in sample</em></p></td>
<td><p>integer (negative indicates error)</p></td>
</tr>
<tr class="row-even"><td><p>is_batch</p></td>
<td><p><em>hw: double buffering</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-odd"><td><p>is_block_transfer</p></td>
<td><p><em>hw: block transfer</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-even"><td><p>is_double</p></td>
<td><p><em>hw: double buffering</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-odd"><td><p>is_half_duplex</p></td>
<td><p><em>hw: half-duplex</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-even"><td><p>is_joint_duplex</p></td>
<td><p><em>hw: joint-duplex</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-odd"><td><p>can_overrange</p></td>
<td><p><em>hw: overrange detection</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-even"><td><p>can_mmap_sample_resolution</p></td>
<td><p><em>hw: sample-resol. mmap</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-odd"><td><p>can_pause</p></td>
<td><p><em>hw: pause</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-even"><td><p>can_resume</p></td>
<td><p><em>hw: resume</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
<tr class="row-odd"><td><p>can_sync_start</p></td>
<td><p><em>hw: synchronized start</em></p></td>
<td><p>boolean (True: hardware supported)</p></td>
</tr>
</tbody>
</table>
<p>The italicized descriptions give a summary of the “full” description as it can be found in the <a class="reference external" href="https://www.alsa-project.org/alsa-doc">ALSA documentation</a>. “hw:”: indicates that the property indicated relates to the hardware. Parameters passed to the PCM object during instantation are prefixed with “PCM():”, they are described there for the keyword argument indicated after “PCM():”.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.pcmtype">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">pcmtype</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.pcmtype" title="Permalink to this definition"></a></dt>
@@ -301,6 +462,38 @@ name of the card. This was always fragile and broke some legitimate usecases.</p
</div>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="id0">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">info</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#id0" title="Permalink to this definition"></a></dt>
<dd><p>Returns a dictionary with the PCM objects configured parameters.</p>
<p>Values are retrieved from the ALSA library if they are available;
otherwise they represent those stored by pyalsaaudio, and their keys
are prefixed with (call value) .</p>
<p><em>New in 0.9.1</em></p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.dumpinfo">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">dumpinfo</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.dumpinfo" title="Permalink to this definition"></a></dt>
<dd><p>Dumps the PCM objects configured parameters to stdout.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.state">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">state</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.state" title="Permalink to this definition"></a></dt>
<dd><p>Returs the current state of the stream, which can be one of
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_OPEN</span></code> (this should not actually happen),
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_SETUP</span></code> (after <a class="reference internal" href="#alsaaudio.PCM.drop" title="alsaaudio.PCM.drop"><code class="xref py py-func docutils literal notranslate"><span class="pre">drop()</span></code></a> or <a class="reference internal" href="#alsaaudio.PCM.drain" title="alsaaudio.PCM.drain"><code class="xref py py-func docutils literal notranslate"><span class="pre">drain()</span></code></a>),
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_PREPARED</span></code> (after construction),
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_RUNNING</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_XRUN</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_DRAINING</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_PAUSED</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_SUSPENDED</span></code>, and
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_STATE_DISCONNECTED</span></code>.</p>
<p><em>New in 0.10</em></p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.read">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">read</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.read" title="Permalink to this definition"></a></dt>
@@ -331,6 +524,9 @@ size of the data provided.</p>
<p>In <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_NONBLOCK</span></code> mode, the call will return immediately, with a
return value of zero, if the buffer is full. In this case, the data
should be written at a later time.</p>
<p>Note that this call completing means only that the samples were buffered
in the kernel, and playout will continue afterwards. Make sure that the
stream is drained before discarding the PCM handle.</p>
</dd></dl>
<dl class="py method">
@@ -340,12 +536,37 @@ should be written at a later time.</p>
Otherwise, playback/capture is resumed.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.drop">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">drop</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.drop" title="Permalink to this definition"></a></dt>
<dd><p>Stop the stream and drop residual buffered frames.</p>
<p><em>New in 0.9</em></p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.drain">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">drain</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.drain" title="Permalink to this definition"></a></dt>
<dd><p>For <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code> PCM objects, play residual buffered frames
and then stop the stream. In <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_NORMAL</span></code> mode,
this function blocks until all pending playback is drained.</p>
<p>For <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code> PCM objects, this function is not very useful.</p>
<p><em>New in 0.10</em></p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.close">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">close</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.close" title="Permalink to this definition"></a></dt>
<dd><p>Closes the PCM device.</p>
<p>For <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code> PCM objects in <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_NORMAL</span></code> mode,
this function blocks until all pending playback is drained.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.PCM.polldescriptors">
<span class="sig-prename descclassname"><span class="pre">PCM.</span></span><span class="sig-name descname"><span class="pre">polldescriptors</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.PCM.polldescriptors" title="Permalink to this definition"></a></dt>
<dd><p>Returns a tuple of <em>(file descriptor, eventmask)</em> that can be used to
wait for changes on the PCM with <em>select.poll</em>.</p>
<p>The <em>eventmask</em> value is compatible with <a class="reference external" href="http://docs.python.org/library/select.html#poll-objects">poll.register</a> in the Python
<dd><p>Returns a list of tuples of <em>(file descriptor, eventmask)</em> that can be
used to wait for changes on the PCM with <em>select.poll</em>.</p>
<p>The <em>eventmask</em> value is compatible with <a href="#id3"><span class="problematic" id="id4">`poll.register`__</span></a> in the Python
<code class="xref py py-const docutils literal notranslate"><span class="pre">select</span></code> module.</p>
</dd></dl>
@@ -385,10 +606,6 @@ return value can be either <code class="xref py py-const docutils literal notran
<dd><p>Return a Python tuple <em>(seconds, nanoseconds, frames_available_in_buffer)</em>.</p>
<p>The type of output is controlled by the tstamp_type, as described in the table below.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 43%" />
<col style="width: 57%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Timestamp Type</p></th>
<th class="head"><p>Description</p></th>
@@ -411,10 +628,6 @@ time using only the system clock.</p></td>
</table>
<p>The timestamp mode is controlled by the tstamp_mode, as described in the table below.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 43%" />
<col style="width: 57%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Timestamp Mode</p></th>
<th class="head"><p>Description</p></th>
@@ -455,11 +668,11 @@ accumulate to quite a lot after a few seconds. Hint: use time.time()
to check how much time has really passed, and add extra writes as nessecary.</p>
</section>
<section id="mixer-objects">
<span id="id3"></span><h2>Mixer Objects<a class="headerlink" href="#mixer-objects" title="Permalink to this headline"></a></h2>
<span id="id2"></span><h2>Mixer Objects<a class="headerlink" href="#mixer-objects" title="Permalink to this heading"></a></h2>
<p>Mixer objects provides access to the ALSA mixer API.</p>
<dl class="py class">
<dt class="sig sig-object py" id="alsaaudio.Mixer">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">alsaaudio.</span></span><span class="sig-name descname"><span class="pre">Mixer</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">control</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'Master'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cardindex</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">device</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'default'</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer" title="Permalink to this definition"></a></dt>
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">alsaaudio.</span></span><span class="sig-name descname"><span class="pre">Mixer</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">control</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'Master'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">cardindex</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">device</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'default'</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer" title="Permalink to this definition"></a></dt>
<dd><p>Arguments are:</p>
<ul class="simple">
<li><p><em>control</em> - specifies which control to manipulate using this mixer
@@ -508,10 +721,6 @@ devices.</p></li>
<dd><p>Returns a list of the switches which are defined by this specific mixer.
Possible values in this list are:</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 31%" />
<col style="width: 69%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Switch</p></th>
<th class="head"><p>Description</p></th>
@@ -551,10 +760,6 @@ Possible values in this list are:</p>
<dd><p>Returns a list of the volume control capabilities of this
mixer. Possible values in the list are:</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 28%" />
<col style="width: 72%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>Capability</p></th>
<th class="head"><p>Description</p></th>
@@ -610,47 +815,45 @@ control.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.getmute">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getmute</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getmute" title="Permalink to this definition"></a></dt>
<dd><p>Return a list indicating the current mute setting for each
channel. 0 means not muted, 1 means muted.</p>
<p>This method will fail if the mixer has no playback switch capabilities.</p>
<dt class="sig sig-object py" id="alsaaudio.Mixer.setenum">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">setenum</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">index</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.setenum" title="Permalink to this definition"></a></dt>
<dd><p>For enumerated controls, sets the currently selected item.
<em>index</em> is an index into the list of available enumerated items returned
by <a class="reference internal" href="#alsaaudio.Mixer.getenum" title="alsaaudio.Mixer.getenum"><code class="xref py py-func docutils literal notranslate"><span class="pre">getenum()</span></code></a>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.getrange">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getrange</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">pcmtype</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getrange" title="Permalink to this definition"></a></dt>
<dd><p>Return the volume range of the ALSA mixer controlled by this object.</p>
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getrange</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">pcmtype</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">units</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">VOLUME_UNITS_RAW</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getrange" title="Permalink to this definition"></a></dt>
<dd><p>Return the volume range of the ALSA mixer controlled by this object.
The value is a tuple of integers whose meaning is determined by the
<em>units</em> argument.</p>
<p>The optional <em>pcmtype</em> argument can be either <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code> or
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code>, which is relevant if the mixer can control both
playback and capture volume. The default value is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code>
if the mixer has playback channels, otherwise it is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.getrec">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getrec</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getrec" title="Permalink to this definition"></a></dt>
<dd><p>Return a list indicating the current record mute setting for each channel. 0
means not recording, 1 means recording.</p>
<p>This method will fail if the mixer has no capture switch capabilities.</p>
<p>The optional <em>units</em> argument can be one of <code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_PERCENTAGE</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_RAW</span></code>, or <code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_DB</span></code>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.getvolume">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getvolume</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">pcmtype</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getvolume" title="Permalink to this definition"></a></dt>
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getvolume</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">pcmtype</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">units</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">VOLUME_UNITS_PERCENTAGE</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getvolume" title="Permalink to this definition"></a></dt>
<dd><p>Returns a list with the current volume settings for each channel. The list
elements are integer percentages.</p>
elements are integers whose meaning is determined by the <em>units</em> argument.</p>
<p>The optional <em>pcmtype</em> argument can be either <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code> or
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code>, which is relevant if the mixer can control both
playback and capture volume. The default value is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code>
if the mixer has playback channels, otherwise it is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code>.</p>
<p>The optional <em>units</em> argument can be one of <code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_PERCENTAGE</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_RAW</span></code>, or <code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_DB</span></code>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.setvolume">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">setvolume</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">volume</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">pcmtype</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.setvolume" title="Permalink to this definition"></a></dt>
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">setvolume</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">volume</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">pcmtype</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">PCM_PLAYBACK</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">units</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">VOLUME_UNITS_PERCENTAGE</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.setvolume" title="Permalink to this definition"></a></dt>
<dd><p>Change the current volume settings for this mixer. The <em>volume</em> argument
controls the new volume setting as an integer percentage.</p>
is an integer whose meaning is determined by the <em>units</em> argument.</p>
<p>If the optional argument <em>channel</em> is present, the volume is set
only for this channel. This assumes that the mixer can control the
volume for the channels independently.</p>
@@ -658,6 +861,16 @@ volume for the channels independently.</p>
<code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code>, which is relevant if the mixer can control both
playback and capture volume. The default value is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_PLAYBACK</span></code>
if the mixer has playback channels, otherwise it is <code class="xref py py-const docutils literal notranslate"><span class="pre">PCM_CAPTURE</span></code>.</p>
<p>The optional <em>units</em> argument can be one of <code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_PERCENTAGE</span></code>,
<code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_RAW</span></code>, or <code class="xref py py-const docutils literal notranslate"><span class="pre">VOLUME_UNITS_DB</span></code>.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.getmute">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getmute</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getmute" title="Permalink to this definition"></a></dt>
<dd><p>Return a list indicating the current mute setting for each channel.
0 means not muted, 1 means muted.</p>
<p>This method will fail if the mixer has no playback switch capabilities.</p>
</dd></dl>
<dl class="py method">
@@ -670,6 +883,14 @@ muted. The default is to set the mute flag for all channels.</p>
<p>This method will fail if the mixer has no playback mute capabilities</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.getrec">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">getrec</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.getrec" title="Permalink to this definition"></a></dt>
<dd><p>Return a list indicating the current record mute setting for each channel.
0 means not recording, 1 means recording.</p>
<p>This method will fail if the mixer has no capture switch capabilities.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.setrec">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">setrec</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">capture</span></span></em><span class="optional">[</span>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span></em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.setrec" title="Permalink to this definition"></a></dt>
@@ -683,20 +904,26 @@ changed. The default is to set the capture flag for all channels.</p>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.polldescriptors">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">polldescriptors</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.polldescriptors" title="Permalink to this definition"></a></dt>
<dd><p>Returns a tuple of <em>(file descriptor, eventmask)</em> that can be used to
wait for changes on the mixer with <em>select.poll</em>.</p>
<p>The <em>eventmask</em> value is compatible with <a class="reference external" href="http://docs.python.org/library/select.html#poll-objects">poll.register</a> in the Python
<dd><p>Returns a list of tuples of <em>(file descriptor, eventmask)</em> that can be
used to wait for changes on the mixer with <em>select.poll</em>.</p>
<p>The <em>eventmask</em> value is compatible with <a href="#id3"><span class="problematic" id="id5">`poll.register`__</span></a> in the Python
<code class="xref py py-const docutils literal notranslate"><span class="pre">select</span></code> module.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.handleevents">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">handleevents</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.handleevents" title="Permalink to this definition"></a></dt>
<dd><p>Acknowledge events on the <em>polldescriptors</em> file descriptors
<dd><p>Acknowledge events on the <a class="reference internal" href="#alsaaudio.Mixer.polldescriptors" title="alsaaudio.Mixer.polldescriptors"><code class="xref py py-func docutils literal notranslate"><span class="pre">polldescriptors()</span></code></a> file descriptors
to prevent subsequent polls from returning the same events again.
Returns the number of events that were acknowledged.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="alsaaudio.Mixer.close">
<span class="sig-prename descclassname"><span class="pre">Mixer.</span></span><span class="sig-name descname"><span class="pre">close</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#alsaaudio.Mixer.close" title="Permalink to this definition"></a></dt>
<dd><p>Closes the Mixer device.</p>
</dd></dl>
<p><strong>A rant on the ALSA Mixer API</strong></p>
<p>The ALSA mixer API is extremely complicated - and hardly documented at all.
<a class="reference internal" href="#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a> implements a much simplified way to access this API. In
@@ -716,7 +943,7 @@ understand half of the API, and that which I do understand has come from a
painful trial and error process.</p>
</section>
<section id="examples">
<span id="pcm-example"></span><h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline"></a></h2>
<span id="pcm-example"></span><h2>Examples<a class="headerlink" href="#examples" title="Permalink to this heading"></a></h2>
<p>The following example are provided:</p>
<ul class="simple">
<li><p><cite>playwav.py</cite></p></li>
@@ -740,7 +967,7 @@ painful trial and error process.</p>
<p>mixertest.py accepts the commandline options <em>-d &lt;device&gt;</em> and
<em>-c &lt;cardindex&gt;</em>.</p>
<section id="playwav-py">
<h3>playwav.py<a class="headerlink" href="#playwav-py" title="Permalink to this headline"></a></h3>
<h3>playwav.py<a class="headerlink" href="#playwav-py" title="Permalink to this heading"></a></h3>
<p><strong>playwav.py</strong> plays a wav file.</p>
<p>To test PCM playback (on your default soundcard), run:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python playwav.py &lt;wav file&gt;
@@ -748,7 +975,7 @@ painful trial and error process.</p>
</div>
</section>
<section id="recordtest-py-and-playbacktest-py">
<h3>recordtest.py and playbacktest.py<a class="headerlink" href="#recordtest-py-and-playbacktest-py" title="Permalink to this headline"></a></h3>
<h3>recordtest.py and playbacktest.py<a class="headerlink" href="#recordtest-py-and-playbacktest-py" title="Permalink to this heading"></a></h3>
<p><strong>recordtest.py</strong> and <strong>playbacktest.py</strong> will record and play a raw
sound file in CD quality.</p>
<p>To test PCM recordings (on your default soundcard), run:</p>
@@ -763,7 +990,7 @@ with <code class="docutils literal notranslate"><span class="pre">Ctl-C</span></
</div>
</section>
<section id="mixertest-py">
<h3>mixertest.py<a class="headerlink" href="#mixertest-py" title="Permalink to this headline"></a></h3>
<h3>mixertest.py<a class="headerlink" href="#mixertest-py" title="Permalink to this heading"></a></h3>
<p>Without arguments, <strong>mixertest.py</strong> will list all available <em>controls</em> on the
default soundcard.</p>
<p>The output might look like this:</p>
@@ -814,12 +1041,6 @@ Channel 0 volume: 61%
Channel 1 volume: 61%
</pre></div>
</div>
<p class="rubric">Footnotes</p>
<dl class="footnote brackets">
<dt class="label" id="f1"><span class="brackets">1</span></dt>
<dd><p>ALSA also allows <code class="docutils literal notranslate"><span class="pre">PCM_ASYNC</span></code>, but this is not supported yet.</p>
</dd>
</dl>
</section>
</section>
</section>
@@ -849,6 +1070,10 @@ Channel 1 volume: 61%
<li class="toctree-l1"><a class="reference internal" href="pyalsaaudio.html#testing">Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="terminology.html">PCM Terminology and Concepts</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a><ul>
<li class="toctree-l2"><a class="reference internal" href="#alsaaudio.pcms"><code class="docutils literal notranslate"><span class="pre">pcms()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#alsaaudio.cards"><code class="docutils literal notranslate"><span class="pre">cards()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#alsaaudio.mixers"><code class="docutils literal notranslate"><span class="pre">mixers()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#alsaaudio.asoundlib_version"><code class="docutils literal notranslate"><span class="pre">asoundlib_version()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#pcm-objects">PCM Objects</a></li>
<li class="toctree-l2"><a class="reference internal" href="#mixer-objects">Mixer Objects</a></li>
<li class="toctree-l2"><a class="reference internal" href="#examples">Examples</a></li>
@@ -873,7 +1098,7 @@ Channel 1 volume: 61%
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<script>document.getElementById('searchbox').style.display = "block"</script>
@@ -890,8 +1115,8 @@ Channel 1 volume: 61%
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
|
<a href="_sources/libalsaaudio.rst.txt"
BIN
View File
Binary file not shown.
+6 -7
View File
@@ -1,17 +1,16 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Python Module Index &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>Python Module Index &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
@@ -98,7 +97,7 @@
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<script>document.getElementById('searchbox').style.display = "block"</script>
@@ -115,8 +114,8 @@
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
</div>
+20 -21
View File
@@ -1,18 +1,17 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Introduction &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>Introduction &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="PCM Terminology and Concepts" href="terminology.html" />
@@ -34,30 +33,30 @@
<div class="body" role="main">
<section id="introduction">
<h1>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h1>
<h1>Introduction<a class="headerlink" href="#introduction" title="Permalink to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author</dt>
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Casper Wilstrup &lt;<a class="reference external" href="mailto:cwi&#37;&#52;&#48;aves&#46;dk">cwi<span>&#64;</span>aves<span>&#46;</span>dk</a>&gt;</p>
</dd>
<dt class="field-even">Author</dt>
<dt class="field-even">Author<span class="colon">:</span></dt>
<dd class="field-even"><p>Lars Immisch &lt;<a class="reference external" href="mailto:lars&#37;&#52;&#48;ibp&#46;de">lars<span>&#64;</span>ibp<span>&#46;</span>de</a>&gt;</p>
</dd>
</dl>
<p id="front">This software is licensed under the PSF license - the same one used by the
majority of the python distribution. Basically you can use it for anything you
wish (even commercial purposes). There is no warranty whatsoever.</p>
<div class="topic">
<aside class="topic">
<p class="topic-title">Abstract</p>
<p>This package contains wrappers for accessing the ALSA API from Python. It is
currently fairly complete for PCM devices and Mixer access. MIDI sequencer
support is low on our priority list, but volunteers are welcome.</p>
<p>If you find bugs in the wrappers please use thegithub issue tracker.
<p>If you find bugs in the wrappers please use the github issue tracker.
Please dont send bug reports regarding ALSA specifically. There are several
bugs in this API, and those should be reported to the ALSA team - not me.</p>
</div>
</aside>
</section>
<section id="what-is-alsa">
<h1>What is ALSA<a class="headerlink" href="#what-is-alsa" title="Permalink to this headline"></a></h1>
<h1>What is ALSA<a class="headerlink" href="#what-is-alsa" title="Permalink to this heading"></a></h1>
<p>The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI
functionality to the Linux operating system.</p>
<p>Logically ALSA consists of these components:</p>
@@ -73,9 +72,9 @@ all ALSA capable applications.</p></li>
<p>More information about ALSA may be found on the project homepage
<a class="reference external" href="http://www.alsa-project.org">http://www.alsa-project.org</a></p>
<section id="alsa-and-python">
<h2>ALSA and Python<a class="headerlink" href="#alsa-and-python" title="Permalink to this headline"></a></h2>
<p>The older Linux sound API (OSS) which is now deprecated is well supported from
the standard Python library, through the ossaudiodev module. No native ALSA
<h2>ALSA and Python<a class="headerlink" href="#alsa-and-python" title="Permalink to this heading"></a></h2>
<p>The older Linux sound API (OSS) which is now deprecated is well supported
by the standard Python library, through the ossaudiodev module. No native ALSA
support exists in the standard library.</p>
<p>There are a few other “ALSA for Python” projects available, including at least
two different projects called pyAlsa. Neither of these seem to be under active
@@ -90,7 +89,7 @@ appreciated.</p>
</section>
</section>
<section id="installation">
<h1>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></a></h1>
<h1>Installation<a class="headerlink" href="#installation" title="Permalink to this heading"></a></h1>
<p>Note: the wrappers link with the alsasound library (from the alsa-lib package)
and need the ALSA headers for compilation. Verify that you have
/usr/lib/libasound.so and /usr/include/alsa (or similar paths) before building.</p>
@@ -109,7 +108,7 @@ ship with ALSA kernels.</p>
</div>
</section>
<section id="testing">
<h1>Testing<a class="headerlink" href="#testing" title="Permalink to this headline"></a></h1>
<h1>Testing<a class="headerlink" href="#testing" title="Permalink to this heading"></a></h1>
<p>Make sure that <code class="code docutils literal notranslate"><span class="pre">aplay</span></code> plays a file through the soundcard you want, then
try:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python playwav.py &lt;filename.wav&gt;
@@ -128,7 +127,7 @@ microphone works, then do:</p>
<p>Speak into the microphone, and interrupt the recording at any time
with <code class="docutils literal notranslate"><span class="pre">Ctl-C</span></code>.</p>
<p>Play back the recording with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python playbacktest.py-d &lt;device&gt; &lt;filename&gt;
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python playbacktest.py -d &lt;device&gt; &lt;filename&gt;
</pre></div>
</div>
<p>There is a minimal test suite in <code class="code docutils literal notranslate"><span class="pre">test.py</span></code>, but it is
@@ -185,7 +184,7 @@ a real problem.</p>
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<script>document.getElementById('searchbox').style.display = "block"</script>
@@ -202,8 +201,8 @@ a real problem.</p>
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
|
<a href="_sources/pyalsaaudio.rst.txt"
+5 -6
View File
@@ -1,18 +1,17 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>Search &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<script src="_static/searchtools.js"></script>
<script src="_static/language_data.js"></script>
<link rel="index" title="Index" href="genindex.html" />
@@ -116,8 +115,8 @@
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
</div>
+1 -1
View File
File diff suppressed because one or more lines are too long
+38 -33
View File
@@ -1,18 +1,17 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>PCM Terminology and Concepts &#8212; alsaaudio documentation 0.9.2 documentation</title>
<title>PCM Terminology and Concepts &#8212; alsaaudio documentation 0.10.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/sphinx_highlight.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="alsaaudio" href="libalsaaudio.html" />
@@ -34,7 +33,7 @@
<div class="body" role="main">
<section id="pcm-terminology-and-concepts">
<h1>PCM Terminology and Concepts<a class="headerlink" href="#pcm-terminology-and-concepts" title="Permalink to this headline"></a></h1>
<h1>PCM Terminology and Concepts<a class="headerlink" href="#pcm-terminology-and-concepts" title="Permalink to this heading"></a></h1>
<p>In order to use PCM devices it is useful to be familiar with some concepts and
terminology.</p>
<dl>
@@ -49,47 +48,53 @@ they can be big endian byte integers, little endian byte integers, or
floating point numbers.</p>
<p>Musically, the sample size determines the dynamic range. The
dynamic range is the difference between the quietest and the
loudest signal that can be resproduced.</p>
loudest signal that can be reproduced.</p>
</dd>
<dt>Frame</dt><dd><p>A frame consists of exactly one sample per channel. If there is only one
channel (Mono sound) a frame is simply a single sample. If the sound is
stereo, each frame consists of two samples, etc.</p>
</dd>
<dt>Frame size</dt><dd><dl class="simple">
<dt>This is the size in bytes of each frame. This can vary a lot: if each sample</dt><dd><dl class="simple">
<dt>is 8 bits, and were handling mono sound, the frame size is one byte.</dt><dd><p>Similarly in 6 channel audio with 64 bit floating point samples, the frame
size is 48 bytes</p>
</dd>
</dl>
</dd>
</dl>
<dt>Frame size</dt><dd><p>This is the size in bytes of each frame. This can vary a lot: if each sample
is 8 bits, and were handling mono sound, the frame size is one byte.
For six channel audio with 64 bit floating point samples, the frame size
is 48 bytes.</p>
</dd>
<dt>Rate</dt><dd><p>PCM sound consists of a flow of sound frames. The sound rate controls how
often the current frame is replaced. For example, a rate of 8000 Hz
means that a new frame is played or captured 8000 times per second.</p>
</dd>
<dt>Data rate</dt><dd><p>This is the number of bytes, which must be recorded or provided per
<dt>Data rate</dt><dd><p>This is the number of bytes which must be consumed or provided per
second at a certain frame size and rate.</p>
<p>8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of
8000 * 1 * 1 = 8 kb/s or 64kbit/s. This is typically used for telephony.</p>
<p>At the other end of the scale, 96000 Hz, 6 channel sound with 64
bit (8 bytes) samples has a data rate of 96000 * 6 * 8 = 4608
kb/s (almost 5 MB sound data per second)</p>
kb/s (almost 5 MB sound data per second).</p>
<p>If the data rate requirement is not met, an overrun (on capture) or
underrun (on playback) occurs; the term “xrun” is used to refer to
either event.</p>
</dd>
<dt>Period</dt><dd><p>When the hardware processes data this is done in chunks of frames. The time
interval between each processing (A/D or D/A conversion) is known
as the period.
The size of the period has direct implication on the latency of the
sound input or output. For low-latency the period size should be
very small, while low CPU resource usage would usually demand
larger period sizes. With ALSA, the CPU utilization is not impacted
much by the period size, since the kernel layer buffers multiple
periods internally, so each period generates an interrupt and a
memory copy, but userspace can be slower and read or write multiple
periods at the same time.</p>
</dl>
<dl id="term-period">
<dt>Period</dt><dd><p>The CPU processes sample data in chunks of frames, so-called periods
(also called fragments by some systems). The operating system kernels
sample buffer must hold at least two periods (at any given time, one
is processed by the sound hardware, and one by the CPU).</p>
<p>The completion of a <em>period</em> triggers a CPU interrupt, which causes
processing and context switching overhead. Therefore, a smaller period
size causes higher CPU resource usage at a given data rate.</p>
<p>A bigger size of the <em>buffer</em> improves the systems resilience to xruns.
The buffer being split into a bigger number of smaller periods also does
that, as it allows it to be drained / topped up sooner.</p>
<p>On the other hand, a bigger size of the <em>buffer</em> also increases the
playback latency, that is, the time it takes for a frame from being
sent out by the application to being actually audible.</p>
<p>Similarly, a bigger <em>period</em> size increases the capture latency.</p>
<p>The trade-off between latency, xrun resilience, and resource usage
must be made depending on the application.</p>
</dd>
<dt>Period size</dt><dd><p>This is the size of each period in Hz. <em>Not bytes, but Hz!.</em> In
<a class="reference internal" href="libalsaaudio.html#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a> the period size is set directly, and it is
<dt>Period size</dt><dd><p>This is the size of each period in frames. <em>Not bytes, but frames!</em>
In <a class="reference internal" href="libalsaaudio.html#module-alsaaudio" title="alsaaudio (Linux)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">alsaaudio</span></code></a> the period size is set directly, and it is
therefore important to understand the significance of this
number. If the period size is configured to for example 32,
each write should contain exactly 32 frames of sound data, and each
@@ -145,7 +150,7 @@ on.</p>
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<script>document.getElementById('searchbox').style.display = "block"</script>
@@ -162,8 +167,8 @@ on.</p>
&copy;2017, Lars Immisch & Casper Wilstrup.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.5.0</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
|
<a href="_sources/terminology.rst.txt"