€•zKŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ!/translations/zh_CN/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ!/translations/zh_TW/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ!/translations/it_IT/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ!/translations/ja_JP/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ!/translations/ko_KR/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ!/translations/pt_BR/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ!/translations/sp_SP/sound/utimers”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³Œ;/var/lib/git/docbuild/linux/Documentation/sound/utimers.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒUserspace-driven timers”h]”hŒUserspace-driven timers”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ field_list”“”)”}”(hhh]”hŒfield”“”)”}”(hhh]”(hŒ field_name”“”)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hhéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hçhhäh³hÇh´KubhŒ field_body”“”)”}”(hŒ&Ivan Orlov ”h]”hŒ paragraph”“”)”}”(hŒ%Ivan Orlov ”h]”(hŒ Ivan Orlov <”…””}”(hhÿh²hh³Nh´NubhŒ reference”“”)”}”(hŒivan.orlov0322@gmail.com”h]”hŒivan.orlov0322@gmail.com”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œmailto:ivan.orlov0322@gmail.com”uh1jhhÿubhŒ>”…””}”(hhÿh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khhùubah}”(h]”h ]”h"]”h$]”h&]”uh1h÷hhäubeh}”(h]”h ]”h"]”h$]”h&]”uh1hâh³hÇh´Khhßh²hubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒPreface”h]”hŒPreface”…””}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj5h²hh³hÇh´K ubhþ)”}”(hX0This document describes the userspace-driven timers: virtual ALSA timers which could be created and controlled by userspace applications using IOCTL calls. Such timers could be useful when synchronizing audio stream with timer sources which we don't have ALSA timers exported for (e.g. PTP clocks), and when synchronizing the audio stream going through two virtual sound devices using ``snd-aloop`` (for instance, when we have a network application sending frames to one snd-aloop device, and another sound application listening on the other end of snd-aloop).”h]”(hXƒThis document describes the userspace-driven timers: virtual ALSA timers which could be created and controlled by userspace applications using IOCTL calls. Such timers could be useful when synchronizing audio stream with timer sources which we don’t have ALSA timers exported for (e.g. PTP clocks), and when synchronizing the audio stream going through two virtual sound devices using ”…””}”(hjFh²hh³Nh´NubhŒliteral”“”)”}”(hŒ ``snd-aloop``”h]”hŒ snd-aloop”…””}”(hjPh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjFubhŒ¢ (for instance, when we have a network application sending frames to one snd-aloop device, and another sound application listening on the other end of snd-aloop).”…””}”(hjFh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K hj5h²hubeh}”(h]”Œpreface”ah ]”h"]”Œpreface”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K ubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Enabling userspace-driven timers”h]”hŒ Enabling userspace-driven timers”…””}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjph²hh³hÇh´Kubhþ)”}”(hŒ½The userspace-driven timers could be enabled in the kernel using the ``CONFIG_SND_UTIMER`` configuration option. It depends on the ``CONFIG_SND_TIMER`` option, so it also should be enabled.”h]”(hŒEThe userspace-driven timers could be enabled in the kernel using the ”…””}”(hjh²hh³Nh´NubjO)”}”(hŒ``CONFIG_SND_UTIMER``”h]”hŒCONFIG_SND_UTIMER”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjubhŒ) configuration option. It depends on the ”…””}”(hjh²hh³Nh´NubjO)”}”(hŒ``CONFIG_SND_TIMER``”h]”hŒCONFIG_SND_TIMER”…””}”(hj›h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjubhŒ& option, so it also should be enabled.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khjph²hubeh}”(h]”Œ enabling-userspace-driven-timers”ah ]”h"]”Œ enabling userspace-driven timers”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒUserspace-driven timers API”h]”hŒUserspace-driven timers API”…””}”(hj¾h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj»h²hh³hÇh´Kubhþ)”}”(hŒòUserspace application can create a userspace-driven ALSA timer by executing the ``SNDRV_TIMER_IOCTL_CREATE`` ioctl call on the ``/dev/snd/timer`` device file descriptor. The ``snd_timer_uinfo`` structure should be passed as an ioctl argument:”h]”(hŒPUserspace application can create a userspace-driven ALSA timer by executing the ”…””}”(hjÌh²hh³Nh´NubjO)”}”(hŒ``SNDRV_TIMER_IOCTL_CREATE``”h]”hŒSNDRV_TIMER_IOCTL_CREATE”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjÌubhŒ ioctl call on the ”…””}”(hjÌh²hh³Nh´NubjO)”}”(hŒ``/dev/snd/timer``”h]”hŒ/dev/snd/timer”…””}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjÌubhŒ device file descriptor. The ”…””}”(hjÌh²hh³Nh´NubjO)”}”(hŒ``snd_timer_uinfo``”h]”hŒsnd_timer_uinfo”…””}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjÌubhŒ1 structure should be passed as an ioctl argument:”…””}”(hjÌh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Khj»h²hubhŒ literal_block”“”)”}”(hŒqstruct snd_timer_uinfo { __u64 resolution; int fd; unsigned int id; unsigned char reserved[16]; }”h]”hŒqstruct snd_timer_uinfo { __u64 resolution; int fd; unsigned int id; unsigned char reserved[16]; }”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jh³hÇh´K&hj»h²hubhþ)”}”(hX/The ``resolution`` field sets the desired resolution in nanoseconds for the virtual timer. ``resolution`` field simply provides an information about the virtual timer, but does not affect the timing itself. ``id`` field gets overwritten by the ioctl, and the identifier you get in this field after the call can be used as a timer subdevice number when passing the timer to ``snd-aloop`` kernel module or other userspace applications. There could be up to 128 userspace-driven timers in the system at one moment of time, thus the id value ranges from 0 to 127.”h]”(hŒThe ”…””}”(hj h²hh³Nh´NubjO)”}”(hŒ``resolution``”h]”hŒ resolution”…””}”(hj(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj ubhŒI field sets the desired resolution in nanoseconds for the virtual timer. ”…””}”(hj h²hh³Nh´NubjO)”}”(hŒ``resolution``”h]”hŒ resolution”…””}”(hj:h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj ubhŒf field simply provides an information about the virtual timer, but does not affect the timing itself. ”…””}”(hj h²hh³Nh´NubjO)”}”(hŒ``id``”h]”hŒid”…””}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj ubhŒ  field gets overwritten by the ioctl, and the identifier you get in this field after the call can be used as a timer subdevice number when passing the timer to ”…””}”(hj h²hh³Nh´NubjO)”}”(hŒ ``snd-aloop``”h]”hŒ snd-aloop”…””}”(hj^h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj ubhŒ­ kernel module or other userspace applications. There could be up to 128 userspace-driven timers in the system at one moment of time, thus the id value ranges from 0 to 127.”…””}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K-hj»h²hubhþ)”}”(hX¨Besides from overwriting the ``snd_timer_uinfo`` struct, ioctl stores a timer file descriptor, which can be used to trigger the timer, in the ``fd`` field of the ``snd_timer_uinfo`` struct. Allocation of a file descriptor for the timer guarantees that the timer can only be triggered by the process which created it. The timer then can be triggered with ``SNDRV_TIMER_IOCTL_TRIGGER`` ioctl call on the timer file descriptor.”h]”(hŒBesides from overwriting the ”…””}”(hjvh²hh³Nh´NubjO)”}”(hŒ``snd_timer_uinfo``”h]”hŒsnd_timer_uinfo”…””}”(hj~h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjvubhŒ^ struct, ioctl stores a timer file descriptor, which can be used to trigger the timer, in the ”…””}”(hjvh²hh³Nh´NubjO)”}”(hŒ``fd``”h]”hŒfd”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjvubhŒ field of the ”…””}”(hjvh²hh³Nh´NubjO)”}”(hŒ``snd_timer_uinfo``”h]”hŒsnd_timer_uinfo”…””}”(hj¢h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjvubhŒ­ struct. Allocation of a file descriptor for the timer guarantees that the timer can only be triggered by the process which created it. The timer then can be triggered with ”…””}”(hjvh²hh³Nh´NubjO)”}”(hŒ``SNDRV_TIMER_IOCTL_TRIGGER``”h]”hŒSNDRV_TIMER_IOCTL_TRIGGER”…””}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjvubhŒ) ioctl call on the timer file descriptor.”…””}”(hjvh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K6hj»h²hubhþ)”}”(hŒDSo, the example code for creating and triggering the timer would be:”h]”hŒDSo, the example code for creating and triggering the timer would be:”…””}”(hjÌh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K=hj»h²hubj)”}”(hXistatic struct snd_timer_uinfo utimer_info = { /* Timer is going to tick (presumably) every 1000000 ns */ .resolution = 1000000ULL, .id = -1, }; int timer_device_fd = open("/dev/snd/timer", O_RDWR | O_CLOEXEC); if (ioctl(timer_device_fd, SNDRV_TIMER_IOCTL_CREATE, &utimer_info)) { perror("Failed to create the timer"); return -1; } ... /* * Now we want to trigger the timer. Callbacks of all of the * timer instances binded to this timer will be executed after * this call. */ ioctl(utimer_info.fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL); ... /* Now, destroy the timer */ close(timer_info.fd);”h]”hXistatic struct snd_timer_uinfo utimer_info = { /* Timer is going to tick (presumably) every 1000000 ns */ .resolution = 1000000ULL, .id = -1, }; int timer_device_fd = open("/dev/snd/timer", O_RDWR | O_CLOEXEC); if (ioctl(timer_device_fd, SNDRV_TIMER_IOCTL_CREATE, &utimer_info)) { perror("Failed to create the timer"); return -1; } ... /* * Now we want to trigger the timer. Callbacks of all of the * timer instances binded to this timer will be executed after * this call. */ ioctl(utimer_info.fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL); ... /* Now, destroy the timer */ close(timer_info.fd);”…””}”hjÚsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jh³hÇh´KAhj»h²hubhþ)”}”(hŒcMore detailed example of creating and ticking the timer could be found in the utimer ALSA selftest.”h]”hŒcMore detailed example of creating and ticking the timer could be found in the utimer ALSA selftest.”…””}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K]hj»h²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ%Userspace-driven timers and snd-aloop”h]”hŒ%Userspace-driven timers and snd-aloop”…””}”(hjùh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjöh²hh³hÇh´Kaubhþ)”}”(hXTUserspace-driven timers could be easily used with ``snd-aloop`` module when synchronizing two sound applications on both ends of the virtual sound loopback. For instance, if one of the applications receives sound frames from network and sends them to snd-aloop pcm device, and another application listens for frames on the other snd-aloop pcm device, it makes sense that the ALSA middle layer should initiate a data transaction when the new period of data is received through network, but not when the certain amount of jiffies elapses. Userspace-driven ALSA timers could be used to achieve this.”h]”(hŒ2Userspace-driven timers could be easily used with ”…””}”(hjh²hh³Nh´NubjO)”}”(hŒ ``snd-aloop``”h]”hŒ snd-aloop”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjubhX module when synchronizing two sound applications on both ends of the virtual sound loopback. For instance, if one of the applications receives sound frames from network and sends them to snd-aloop pcm device, and another application listens for frames on the other snd-aloop pcm device, it makes sense that the ALSA middle layer should initiate a data transaction when the new period of data is received through network, but not when the certain amount of jiffies elapses. Userspace-driven ALSA timers could be used to achieve this.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Kchjöh²hubhþ)”}”(hŒ‰To use userspace-driven ALSA timer as a timer source of snd-aloop, pass the following string as the snd-aloop ``timer_source`` parameter:”h]”(hŒnTo use userspace-driven ALSA timer as a timer source of snd-aloop, pass the following string as the snd-aloop ”…””}”(hj'h²hh³Nh´NubjO)”}”(hŒ``timer_source``”h]”hŒ timer_source”…””}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj'ubhŒ parameter:”…””}”(hj'h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Kmhjöh²hubj)”}”(hŒ4# modprobe snd-aloop timer_source="-1.4."”h]”hŒ4# modprobe snd-aloop timer_source="-1.4."”…””}”hjGsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jh³hÇh´Krhjöh²hubhþ)”}”(hŒµWhere ``utimer_id`` is the id of the timer you created with ``SNDRV_TIMER_IOCTL_CREATE``, and ``4`` is the number of userspace-driven timers device (``SNDRV_TIMER_GLOBAL_UDRIVEN``).”h]”(hŒWhere ”…””}”(hjUh²hh³Nh´NubjO)”}”(hŒ ``utimer_id``”h]”hŒ utimer_id”…””}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjUubhŒ) is the id of the timer you created with ”…””}”(hjUh²hh³Nh´NubjO)”}”(hŒ``SNDRV_TIMER_IOCTL_CREATE``”h]”hŒSNDRV_TIMER_IOCTL_CREATE”…””}”(hjoh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjUubhŒ, and ”…””}”(hjUh²hh³Nh´NubjO)”}”(hŒ``4``”h]”hŒ4”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjUubhŒ2 is the number of userspace-driven timers device (”…””}”(hjUh²hh³Nh´NubjO)”}”(hŒ``SNDRV_TIMER_GLOBAL_UDRIVEN``”h]”hŒSNDRV_TIMER_GLOBAL_UDRIVEN”…””}”(hj“h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjUubhŒ).”…””}”(hjUh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Kthjöh²hubhþ)”}”(hŒÕ``resolution`` for the userspace-driven ALSA timer used with snd-aloop should be calculated as ``1000000000ULL / frame_rate * period_size`` as the timer is going to tick every time a new period of frames is ready.”h]”(jO)”}”(hŒ``resolution``”h]”hŒ resolution”…””}”(hj¯h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj«ubhŒQ for the userspace-driven ALSA timer used with snd-aloop should be calculated as ”…””}”(hj«h²hh³Nh´NubjO)”}”(hŒ,``1000000000ULL / frame_rate * period_size``”h]”hŒ(1000000000ULL / frame_rate * period_size”…””}”(hjÁh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhj«ubhŒJ as the timer is going to tick every time a new period of frames is ready.”…””}”(hj«h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´Kxhjöh²hubhþ)”}”(hŒŸAfter that, each time you trigger the timer with ``SNDRV_TIMER_IOCTL_TRIGGER`` the new period of data will be transferred from one snd-aloop device to another.”h]”(hŒ1After that, each time you trigger the timer with ”…””}”(hjÙh²hh³Nh´NubjO)”}”(hŒ``SNDRV_TIMER_IOCTL_TRIGGER``”h]”hŒSNDRV_TIMER_IOCTL_TRIGGER”…””}”(hjáh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jNhjÙubhŒQ the new period of data will be transferred from one snd-aloop device to another.”…””}”(hjÙh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hýh³hÇh´K|hjöh²hubeh}”(h]”Œ%userspace-driven-timers-and-snd-aloop”ah ]”h"]”Œ%userspace-driven timers and snd-aloop”ah$]”h&]”uh1hÈhj»h²hh³hÇh´Kaubeh}”(h]”Œuserspace-driven-timers-api”ah ]”h"]”Œuserspace-driven timers api”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´Kubeh}”(h]”Œuserspace-driven-timers”ah ]”h"]”Œuserspace-driven timers”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j4Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jj jmjjj¸jµjjjþjûuŒ nametypes”}”(j‰jm‰j¸‰j‰jþ‰uh}”(j hÊjjj5jµjpjj»jûjöuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.