<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Txzone</title><link>https://txzone.net/</link><description>Solo developer and software architect adventures</description><language>en</language><lastBuildDate>Wed, 08 Mar 2023 17:07:42 +0000</lastBuildDate><atom:link href="https://txzone.net/index.xml" rel="self" type="application/rss+xml"/><item><title>Using AI for refactoring Vue 2 to Vue 3</title><link>https://txzone.net/2023/03/using-ai-for-refactoring-vue-2-to-vue-3/</link><pubDate>Wed, 08 Mar 2023 17:07:42 +0000</pubDate><guid>https://txzone.net/2023/03/using-ai-for-refactoring-vue-2-to-vue-3/</guid><description>&lt;p&gt;2022 has been an incredible year for AI-generated content. I see that as a tool, the same way you listen to music and create music afterwards. The same way my developer journey has been from reading open-source code, and contributing to the field.&lt;/p&gt;&#10;&lt;p&gt;I have a project made with &lt;a href="https://v2.vuejs.org/"&gt;Vue 2 using Typescript&lt;/a&gt;, &lt;a href="https://github.com/kaorun343/vue-property-decorator"&gt;Vue Property Decorator&lt;/a&gt; and &lt;a href="https://quasar.dev/"&gt;Quasar&lt;/a&gt;. My goal was to refactor to Vue 3 using &lt;a href="https://vuejs.org/guide/typescript/composition-api.html"&gt;Typescript with Composition API&lt;/a&gt;.&#10;My time is limited on the subject and not a big priority, and the amount of work seems too much for my bare hand that, 2 years ago, that i dropped it.&lt;/p&gt;&#10;&lt;p&gt;We are in 2023, could AI help me for a such task ?&lt;/p&gt;&#10;&lt;h2 id="tdlr"&gt;TDLR&lt;/h2&gt;&#10;&lt;p&gt;Gist: &lt;a href="https://gist.github.com/tito/230863f714ab43fc92ad55510de2ca4e"&gt;https://gist.github.com/tito/230863f714ab43fc92ad55510de2ca4e&lt;/a&gt;&lt;/p&gt;&#10;&lt;figure class="video"&gt;&lt;video controls preload="metadata" src="https://txzone.net/media/2023/03/Kooha-2023-03-08-17-47-30.mp4"&gt;&lt;/video&gt;&lt;/figure&gt;&#10;&#10;&lt;h2 id="the-test-case"&gt;The test case&lt;/h2&gt;&#10;&lt;p&gt;Here is my &amp;ldquo;test&amp;rdquo; source, where I&amp;rsquo;ll experiment the refactoring. The actual file is actually longer as it include template and style tag, but it doesn&amp;rsquo;t matter for our example.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Watch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;vue-property-decorator&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="kr"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;$route&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msgkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msgkey&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;LOGOUT_SUCCESS&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Vous êtes déconnecté&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;login&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Email ou mot de passe invalide&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="copilot"&gt;Copilot&lt;/h2&gt;&#10;&lt;p&gt;I use &lt;a href="http://copilot.github.com/"&gt;copilot&lt;/a&gt; day-to-day as my advanced auto completion. While i don&amp;rsquo;t use it for creating a new file from scratch, it is a very handy tool for auto completion for repetitive tasks, from variable declarations, object copying, filter/map&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;But that&amp;rsquo;s all it is. I cannot really take a whole file, and give instruction to copilot for converting from one syntax to another&amp;hellip;&lt;/p&gt;&#10;&lt;h2 id="chatgpt"&gt;ChatGPT&lt;/h2&gt;&#10;&lt;p&gt;Using OpenAI &lt;a href="https://platform.openai.com/docs/guides/chat"&gt;ChatGPT API&lt;/a&gt;, i got a prompt that fairly give me the output i wanted.&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code class="language-ansi" data-lang="ansi"&gt;You are an assistant design to help developper for migrating their code from Vue 2 to Vue 3 using Typescript with Composition API. Here is a set of rules you must absolutely follow:&#10;&#10;1. Rewrite the &amp;lt;script lang=&amp;#34;ts&amp;#34;&amp;gt; to &amp;lt;script setup lang=&amp;#34;ts&amp;#34;&amp;gt;&#10;2. The content of the script tag must be a valid Typescript code&#10;3. The component must be flattened into the script setup&#10;4. Remove any &amp;#34;export default&amp;#34;.&#10;5. Use the `onMounted` hook instead of the `created` lifecycle hook if necessary&#10;6. Use the `useRoute` approach instead of $route. Same for $router.&#10;7. Store is not using vuex but pinia.&#10;8. Auth related function is accessible in stores/auth.ts, using useAuthStore.&#10;9. Do not use Ref is the type can be infered from the value pass into ref()&#10;10. Do not put all the methods and properties into a global const object&#10;11. Prefer using global &amp;#34;const router = useRouter()&amp;#34; instead of live instanciation when needed&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My problem is, result are not consistent, and do follow my rules.&lt;/p&gt;&#10;&lt;h3 id="first-generation"&gt;First generation&lt;/h3&gt;&#10;&lt;p&gt;Not as perfect as wanted. It choose to not use &lt;code&gt;onMounted()&lt;/code&gt;, and flattened the code, which is allowed by the instruction. However, &lt;code&gt;this.$q&lt;/code&gt; is here, which end up failing.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;vue-router&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAuthStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;@/stores/auth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAuthStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;authStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Email ou mot de passe invalide&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msgkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msgkey&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;LOGOUT_SUCCESS&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Vous êtes déconnecté&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="second-generation"&gt;Second generation&lt;/h3&gt;&#10;&lt;p&gt;That&amp;rsquo;s what bother me. By giving the same input, i have a now a different output.&#10;It recognized Quasar, and put the code into the &lt;code&gt;onMounted()&lt;/code&gt;. Works for me.&#10;BUT, now the login function don&amp;rsquo;t have the same input as before, it decided to flatten the argument. OK.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRoute&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;vue-router&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;vue&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuasar&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;quasar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAuthStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;@/stores/auth&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuasar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRoute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAuthStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msgkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msgkey&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;LOGOUT_SUCCESS&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Vous êtes déconnecté&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;authStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Email ou mot de passe invalide&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="when-it-went-wrong"&gt;When it went wrong&lt;/h2&gt;&#10;&lt;p&gt;I tried to play with temperature, top_n, but from time to time, it generate something against the rules.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAuthStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-vue" data-lang="vue"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;GaugeChart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapZoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;&#10;&lt;p&gt;I can go again and give another set of rules to use for the migration, especially moving from a single store using Vuex to many stores using Pinia.&lt;/p&gt;&#10;&lt;p&gt;Out of 92 files needed to convert, totally over 22997 lines to convert, around 10 needed a refactoring by hand as i was not able to generate a correct approach.&#10;Nevertheless, it was much faster to go other it with the tool and review rather than manually pass through everything.&lt;/p&gt;&#10;&lt;p&gt;For today, i take that as a win.&lt;/p&gt;&#10;</description></item><item><title>Kivy Programming Contest 2014</title><link>https://txzone.net/2014/03/kivy-programming-contest-2014/</link><pubDate>Sun, 16 Mar 2014 19:16:41 +0000</pubDate><guid>https://txzone.net/2014/03/kivy-programming-contest-2014/</guid><description>&lt;p&gt;Kivy is organizing its second application development contest!. This is a great chance for users both new and experienced to show off their skills and compete for prizes. Entries will be judged on a range of criteria accessible to both new and experienced programmers, so don&amp;rsquo;t be afraid to dive in!&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="http://kivy.org/index.html#contest"&gt;&lt;img src="https://txzone.net/media/2014/03/poster_1.png" alt="poster_1"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;A big big thanks to the &lt;a href="https://www.python.org/psf/"&gt;Python Software Foundation&lt;/a&gt; for being our first and lovely sponsor :)&lt;/p&gt;&#10;</description></item><item><title>2048, in Python / Kivy</title><link>https://txzone.net/2014/03/2048-in-python-kivy/</link><pubDate>Sun, 16 Mar 2014 19:14:15 +0000</pubDate><guid>https://txzone.net/2014/03/2048-in-python-kivy/</guid><description>&lt;p&gt;If you don&amp;rsquo;t know the &lt;a href="https://play.google.com/store/apps/details?id=com.meltingrocks.kivy2048"&gt;2048 puzzle&lt;/a&gt; yet, you should. But be careful, it&amp;rsquo;s time consuming. I won&amp;rsquo;t go on the whole clone history of the game, but will just say that if you want to play it on the Web, play to the &lt;a href="http://gabrielecirulli.github.io/2048/"&gt;Gabriel Cirulli 2048&lt;/a&gt;. The author said &lt;a href="https://twitter.com/gabrielecirulli/status/444501275473100800"&gt;it wont make an official iOS/Android app&lt;/a&gt;, so&amp;hellip; let&amp;rsquo;s give &lt;a href="http://kivy.org"&gt;Kivy&lt;/a&gt; a try :)&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.meltingrocks.kivy2048"&gt;&lt;img src="https://txzone.net/media/2014/03/device-2014-03-15-114048.png" alt="device-2014-03-15-114048"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Only 2 hours of coding where needed for the first published version of the game. Then i learned on the &lt;a href="https://developers.google.com/games/services/android/quickstart"&gt;Google Play Game services APIs&lt;/a&gt; for integrating a leaderboard and achievements. And after a couple of hours during the night, what i can say is: Be patient! Even if you follow the documentation carefully, you need to wait few hours before your app_id works on their server, even in test mode. There never warn us about it.&lt;/p&gt;&#10;&lt;p&gt;When the setup is done and it start working, it is easy to login:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;PythonActivity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;org.renpy.android.PythonActivity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GameHelper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;com.google.example.games.basegameutils.GameHelper&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gh_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PythonActivity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GameHelper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLIENT_ALL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gh_instance_listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GameHelperListener&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gh_instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gh_instance_listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gh_instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PythonActivity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mActivity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unbind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;on_activity_result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_on_activity_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;on_activity_result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_on_activity_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s how you can unlock achievement:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# uid is the Google UID for the achievement you want&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;gh_instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Achievements&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gh_instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getApiClient&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And put the user score on the leaderboard:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# uid is the Google UID for the leaderboard you&amp;#39;ve created.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# You can have multiple leaderboard.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;gh_instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Games&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Leaderboards&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;submitScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gh_instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getApiClient&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is a little more code around that, but globally, using the new Play Games services APIs is now easy. I hope this little piece of code will help peoples to integrate it into their app. Somebody need to start a Python library for managing Google Play API and Game Center for iOS.&lt;/p&gt;&#10;&lt;p&gt;Have a look at the &lt;a href="http://github.com/tito/2048"&gt;source code&lt;/a&gt; for an example of the integration with the Play Games services APIs :)&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.meltingrocks.kivy2048"&gt;&lt;img src="https://txzone.net/media/remote/developer.android.com/en_generic_rgb_wo_45.png" alt="Get it on Google Play"&gt;&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Using Facebook SDK with Python-for-Android / Kivy</title><link>https://txzone.net/2013/08/using-facebook-sdk-with-python-for-android-kivy/</link><pubDate>Thu, 08 Aug 2013 09:50:26 +0000</pubDate><guid>https://txzone.net/2013/08/using-facebook-sdk-with-python-for-android-kivy/</guid><description>&lt;p&gt;For another museum project, &lt;a href="http://devocite.com/"&gt;Arnaud&lt;/a&gt; asked me to see if we could integrate Facebook in an app on Android. The &lt;a href="http://www.pythonforfacebook.com/"&gt;usual&lt;/a&gt; &lt;a href="https://github.com/sciyoshi/pyfacebook/"&gt;libraries&lt;/a&gt; are made for desktop, and manually open a webbrowser to handle the user authorization. But that&amp;rsquo;s not really nice for us, it would be nicer to have a native integration instead. Let&amp;rsquo;s see how we can use the official Facebook Android SDK.&lt;/p&gt;&#10;&lt;h2 id="prerequisites"&gt;Prerequisites&lt;/h2&gt;&#10;&lt;p&gt;You&amp;rsquo;ll need to have:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Kivy&amp;rsquo;s &lt;a href="http://python-for-android.readthedocs.org/en/latest/"&gt;python-for-android&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;A Facebook account (obviously)&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://developers.facebook.com/android/"&gt;Facebook SDK 3.0&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="get-the-example"&gt;Get the example&lt;/h2&gt;&#10;&lt;p&gt;Clone the &lt;a href="https://github.com/tito/p4a-facebook-example"&gt;Kivy/Facebook&lt;/a&gt; example:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code class="language-ansi" data-lang="ansi"&gt;$ git clone https://github.com/tito/p4a-facebook-example&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="register-a-facebook-application"&gt;Register a Facebook application&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Go to the &lt;a href="https://developers.facebook.com/apps"&gt;Facebook developers interface&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Click on &lt;img src="https://txzone.net/media/2013/08/S%C3%A9lection_107.png" alt="Sélection_107"&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Fill the information &amp;ldquo;App Name&amp;rdquo;. Don&amp;rsquo;t put &amp;ldquo;FB&amp;rdquo; or &amp;ldquo;Facebook&amp;rdquo; in the title, or your application name will be considered as Invalid :)&#10;&lt;img src="https://txzone.net/media/2013/08/S%C3%A9lection_108.png" alt="Sélection_108"&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Pass the captcha&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Write down your application id somewhere&lt;img src="https://txzone.net/media/2013/08/S%C3%A9lection_111.png" alt="Sélection_111"&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Now, you need to activate Native Android App. The package name is the same name as the one we will pass in &lt;code&gt;--package&lt;/code&gt; when building the APK. The Class Name is the &lt;code&gt;packagename/activity&lt;/code&gt;. Activity class is always the same for all the applications compiled with python-for-android.&#10;&lt;img src="https://txzone.net/media/2013/08/S%C3%A9lection_109.png" alt="Sélection_109"&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Right now, the Facebook Android SDK will not authorize our android application to be used, because Facebook want to know the signature hash that will be used by our generated APK. To generate the key hashes, you need to use the keytool. Here is an example for the android &amp;ldquo;debug&amp;rdquo; key:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ keytool -exportcert -alias androiddebugkey \&#10; -keystore ~/.android/debug.keystore | \&#10; openssl sha1 -binary | openssl base64&#10;Enter keystore password: android&#10;u+bzQmG87L298C4KGM8yODi3W/4=&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Copy the generated key hash, and paste it to the field:&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://txzone.net/media/2013/08/S%C3%A9lection_110.png" alt="Sélection_110"&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Setup the our application&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Go into &lt;code&gt;p4a-facebook-example&lt;/code&gt;, and edit the &lt;code&gt;main.py&lt;/code&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Search for &lt;code&gt;FACEBOOK_APP_ID&lt;/code&gt;, and replace with your own Application Id&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Go into python-for-android, and create a distribution:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ ./distribute.sh -m &amp;#39;kivy&amp;#39;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Go into the &lt;code&gt;dist/default&lt;/code&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Generate the APK one time (for generating all the file we need to customize). Replace &lt;code&gt;/path/to/p4a-facebook-example&lt;/code&gt;:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;./build.py --name &amp;#34;Facebook test&amp;#34; --package org.test.facebook \&#10; --version 1 --private /path/to/p4a-facebook-example/ \&#10; --window --permission INTERNET debug&#10;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Add a new reference to &lt;code&gt;project.properties&lt;/code&gt; to include the Facebook SDK. The path to the Facebook SDK &lt;strong&gt;MUST&lt;/strong&gt; be a relative path, otherwise you&amp;rsquo;ll get issues during the next build.&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;android.library.reference.1=../../facebook-android-sdk-3.0.2/facebook&#10;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Edit the &lt;code&gt;templates/AndroidManifest.tmpl.xml&lt;/code&gt; to include the Facebook login activity, just under the &lt;code&gt;&amp;lt;application&amp;gt;&lt;/code&gt;:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Rebuild your application&amp;hellip; and you&amp;rsquo;re ready to test :)&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Install the application on your device:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;adb install -r bin/Facebooktest-1-debug.apk&#10;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="test-your-application"&gt;Test your application&lt;/h2&gt;&#10;&lt;p&gt;The Facebook SDK 3.0 require to separate read and publish permissions. To the user, it means you&amp;rsquo;ll have 2 dialog to accept. Even if you just want to publish to the application stream, you need to have the basic permission (read) accepted by the user before publish permissions. This is already implemented in the example app.&lt;/p&gt;&#10;&lt;p&gt;When you start the application the first time, you&amp;rsquo;ll have:&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://txzone.net/media/2013/08/device-2013-08-08-110647.png"&gt;&lt;img src="https://txzone.net/media/2013/08/device-2013-08-08-110647.png" alt="device-2013-08-08-110647"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Depending if you have the Native Facebook application or not, you&amp;rsquo;ll have 2 kinds of authentification boxes.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://txzone.net/media/2013/08/device-2013-08-08-110834.png"&gt;&lt;img src="https://txzone.net/media/2013/08/device-2013-08-08-110834.png" alt="device-2013-08-08-110834"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Without Facebook installed on the device:&lt;/p&gt;&#10;&lt;p&gt;And with Facebook installed on the device:&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://txzone.net/media/2013/08/device-2013-08-08-111002.png"&gt;&lt;img src="https://txzone.net/media/2013/08/device-2013-08-08-111002.png" alt="device-2013-08-08-111002"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;After authentication, the user will need to accept our permissions:&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://txzone.net/media/2013/08/device-2013-08-08-111111.png"&gt;&lt;img src="https://txzone.net/media/2013/08/device-2013-08-08-111111.png" alt="device-2013-08-08-111111"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;It&amp;rsquo;s done!&lt;/p&gt;&#10;&lt;p&gt;The application have now the right to post :) The example post in the user stream as the application itself, not as the user. It&amp;rsquo;s called &amp;ldquo;publish_actions&amp;rdquo;.&lt;/p&gt;&#10;&lt;h2 id="getting-further"&gt;Getting further&lt;/h2&gt;&#10;&lt;p&gt;Obviously, when you use the Facebook SDK itself, you feel the pain of an API designed for Java. For every callback that Facebook want to call, you need to implement a Java class and define the callback method. Python is really simpler and fun to use.&lt;/p&gt;&#10;&lt;p&gt;See for yourself: we want to make a call of &amp;ldquo;[Request.newStatusUpdateRequest](&lt;a href="https://developers.facebook.com/docs/reference/android/current/Request#newStatusUpdateRequest(Session"&gt;https://developers.facebook.com/docs/reference/android/current/Request#newStatusUpdateRequest(Session&lt;/a&gt;, String, Callback))&amp;rdquo;. Se weed first to implement a &lt;code&gt;GraphUserCallback&lt;/code&gt; class, in Java. Thanks to Pyjnius, we can do it directly in Python:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_FacebookGraphUserCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PythonJavaClass&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;__javainterfaces__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;com.facebook.Request$GraphUserCallback&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;__javacontext__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;app&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_FacebookGraphUserCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@java_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(Lcom/facebook/model/GraphUser;Lcom/facebook/Response;)V&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;onCompleted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This Python/Java class will call our own python callback when the Java callback &lt;code&gt;onCompleted&lt;/code&gt; will be called. Then:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@run_on_ui_thread&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;newStatusUpdateRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_FacebookRequestCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executeAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All you have to do at the end, is to call the post method:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fb_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;message posted at &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I don&amp;rsquo;t provide a wrapper around all the possible Request method you can do with Facebook. I just have an example for &amp;ldquo;post&amp;rdquo; and &amp;ldquo;me&amp;rdquo;. Both wrap &amp;ldquo;[Request.newStatusUpdateRequest](&lt;a href="https://developers.facebook.com/docs/reference/android/current/Request#newStatusUpdateRequest(Session"&gt;https://developers.facebook.com/docs/reference/android/current/Request#newStatusUpdateRequest(Session&lt;/a&gt;, String, Callback))&amp;rdquo; and &amp;ldquo;[Request.newMeRequest](&lt;a href="https://developers.facebook.com/docs/reference/android/current/Request#newMeRequest(Session"&gt;https://developers.facebook.com/docs/reference/android/current/Request#newMeRequest(Session&lt;/a&gt;, GraphUserCallback))&amp;rdquo;. Please note that every request call must happen in the UI thread. Use the python-for-android/runnable module for that, with &lt;code&gt;@run_on_ui_thread&lt;/code&gt; decorator.&lt;/p&gt;&#10;&lt;h2 id="the-end"&gt;The end&lt;/h2&gt;&#10;&lt;p&gt;It was not easy to get it right, and it still complex to make all the pieces together. I&amp;rsquo;ve tried to use their own LoginButton (because they said that&amp;rsquo;s how they want it, everywhere), but i&amp;rsquo;ve not be able to use it in our app. Mostly because the LoginButton is a pure android widget, and because it doesn&amp;rsquo;t want to bring back the Activity after login. I was stuck too much time on it, and preferred to go in another way.&#10;Please note that you should not share an application with a fake Facebook button, the design / look-and-feel must be the same as the original one.&lt;/p&gt;&#10;&lt;p&gt;I hope that will help some of you to get started !&lt;/p&gt;&#10;</description></item><item><title>Kivy 1.7.0 is out</title><link>https://txzone.net/2013/05/kivy-1-7-0-is-out/</link><pubDate>Sun, 19 May 2013 07:48:23 +0000</pubDate><guid>https://txzone.net/2013/05/kivy-1-7-0-is-out/</guid><description>&lt;p&gt;If you missed it, &lt;a href="http://kivy.org/"&gt;Kivy 1.7.0&lt;/a&gt; is out last Monday. It&amp;rsquo;s quite a big release that include some big fixes we did during the :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="http://developer.android.com/tools/devices/emulator.html"&gt;Android Emulator&lt;/a&gt; is now supported&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="http://kivy.org/docs/api-kivy.uix.scrollview.html"&gt;ScrollView&lt;/a&gt; has been re-factored with new physics calculations. To be exact, the scrollview doesn&amp;rsquo;t calculate anything now, it just pass the touch position to an &lt;a href="http://kivy.org/docs/api-kivy.effects.scroll.html"&gt;Scroll effect&lt;/a&gt;. This class calculate the movement&amp;rsquo;s velocity, and the over-scroll&amp;rsquo;s distance (means how far you scrolled out of the bounds). Then, we implemented 2 visual effects that use the over-scroll to make the scrollview act as a [Damped spring, and/or to &lt;a href="http://kivy.org/docs/api-kivy.effects.opacityscroll.html"&gt;fade out&lt;/a&gt; the scrollview if you over-scroll too much.](&lt;a href="http://kivy.org/docs/api-kivy.effects.dampedscroll.html"&gt;http://kivy.org/docs/api-kivy.effects.dampedscroll.html&lt;/a&gt;)&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="http://kivy-garden.github.io/"&gt;Garden&lt;/a&gt;: a separated organization for centralize user&amp;rsquo;s widgets and addons. You can create garden packages very easily, and import it in the source code with just &amp;ldquo;kivy.garden.&lt;em&gt;packagename&lt;/em&gt;&amp;rdquo;. &lt;a href="https://github.com/kivy-garden/"&gt;Few garden packages&lt;/a&gt; are already available!&lt;/li&gt;&#10;&lt;li&gt;And more, &lt;a href="https://groups.google.com/forum/?fromgroups#!topic/kivy-users/TyOzyLtYKMw"&gt;Check the announcement&lt;/a&gt; :)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Crowdfunding Kivy on Raspberry Pi</title><link>https://txzone.net/2013/02/crowdfunding-kivy-on-raspberry-pi/</link><pubDate>Tue, 26 Feb 2013 17:06:37 +0000</pubDate><guid>https://txzone.net/2013/02/crowdfunding-kivy-on-raspberry-pi/</guid><description>&lt;p&gt;&lt;a href="http://kivy.org"&gt;Kivy&lt;/a&gt; doesn&amp;rsquo;t run yet on the &lt;a href="http://www.raspberrypi.com/"&gt;Raspberry Pi&lt;/a&gt;, and we need your help to crowdfund it!&#10;Even is Kivy is built to be compatible for GLES 2.0, we lack of a python EGL support.&lt;/p&gt;&#10;&lt;p&gt;The plan is to add a new EGL Window provider, in addition to the detection of non-multitouch devices such as keyboard and mouse.&lt;/p&gt;&#10;&lt;p&gt;All the informations are available at: &lt;a href="https://www.bountysource.com/#fundraisers/143-kivy-on-raspberry-pi"&gt;https://www.bountysource.com/#fundraisers/143-kivy-on-raspberry-pi&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Pyjnius: Accessing Java classes from Python</title><link>https://txzone.net/2012/08/pyjnius-accessing-java-classes-from-python/</link><pubDate>Mon, 20 Aug 2012 13:43:43 +0000</pubDate><guid>https://txzone.net/2012/08/pyjnius-accessing-java-classes-from-python/</guid><description>&lt;p&gt;We&amp;rsquo;re pleased to announce the &lt;a href="http://pyjnius.readthedocs.org"&gt;Pyjnius&lt;/a&gt; project. It&amp;rsquo;s a Python library to access Java classes from Python, on the desktop or on Android.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Source code: &lt;a href="http://github.com/kivy/pyjnius"&gt;github.com/kivy/pyjnius&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;Documentation: &lt;a href="http://pyjnius.readthedocs.org"&gt;pyjnius.readthedocs.org&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;We found others libraries such as &lt;a href="http://jpype.sourceforge.net/"&gt;JPype&lt;/a&gt; or &lt;a href="http://py4j.sourceforge.net/"&gt;Py4j&lt;/a&gt;, but we weren&amp;rsquo;t happy with the design and the usability. Using &lt;a href="http://www.jython.org/"&gt;Jython&lt;/a&gt; wasn&amp;rsquo;t an option either, because we wanted to use the library within our &lt;a href="http://github.com/kivy/python-for-android"&gt;python for android&lt;/a&gt; project.&lt;/p&gt;&#10;&lt;p&gt;Let me show you how simple it is to use Pyjnius:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;jnius&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;java.util.Stack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;world&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;world&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What we demonstrate here is the &lt;a href="http://pyjnius.readthedocs.org/en/latest/api.html#jnius.autoclass"&gt;autoclass&lt;/a&gt; function that create kind-of proxy that reflect all the methods and fields available from the Java class &lt;code&gt;java.util.Stack&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;Ok, maybe you want an Android-related example? Just have a look:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;jnius&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;MediaRecorder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;android.media.MediaRecorder&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AudioSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;android.media.MediaRecorder$AudioSource&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;OutputFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;android.media.MediaRecorder$OutputFormat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AudioEncoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;autoclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;android.media.MediaRecorder$AudioEncoder&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Record the Microphone with a 3GP recorder&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MediaRecorder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setAudioSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AudioSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setOutputFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OutputFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREE_GPP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setOutputFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/sdcard/testrecorder.3gp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setAudioEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AudioEncoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ARM_NB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Record 5 seconds&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mRecorder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;More examples are available in the documentation. We have a mapping between Java/Python type, native arrays, support for methods with multiple signatures, and a lot more. We are using &lt;a href="http://cython.org"&gt;Cython&lt;/a&gt; + &lt;a href="http://en.wikipedia.org/wiki/Java_Native_Interface"&gt;JNI&lt;/a&gt; internally. The performance cost is minimal.&lt;/p&gt;&#10;&lt;p&gt;The library is already available for &lt;a href="http://github.com/kivy/python-for-android"&gt;Python for android&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;The library have been done by &lt;a href="http://blog.tshirtman.fr/"&gt;Gabriel Pettier&lt;/a&gt; and myself, under the &lt;a href="http://kivy.org/"&gt;Kivy organization&lt;/a&gt;.&lt;/p&gt;&#10;</description></item><item><title>IOS Support for Kivy</title><link>https://txzone.net/2012/03/ios-support-for-kivy/</link><pubDate>Sun, 11 Mar 2012 22:45:42 +0000</pubDate><guid>https://txzone.net/2012/03/ios-support-for-kivy/</guid><description>&lt;p&gt;Kivy has now added &lt;a href="https://groups.google.com/d/topic/kivy-users/EoujXCpMSSk/discussion"&gt;official support for IOS platform&lt;/a&gt;. You can now package your Kivy application for the Ipad (and other iOS devices, testers needed).&lt;/p&gt;&#10;&lt;p&gt;The current instructions are available here: &lt;a href="http://kivy.org/docs/guide/packaging-ios.html"&gt;http://kivy.org/docs/guide/packaging-ios.html&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;For the full story on the multiple Apple limitations we are working with, i want to share the hardest part for Python integration: Apple&amp;rsquo;s prohibition on using dlopen() to load dynamic libraries.&#10;In a typical case, a compiled Python library&amp;rsquo;s extension is a &amp;ldquo;.so&amp;rdquo;, and the &amp;ldquo;.so&amp;rdquo; is dlopen() at import.&lt;/p&gt;&#10;&lt;p&gt;That being said, as we did for the &lt;a href="https://txzone.net/2012/01/introducing-python-for-android/"&gt;python-for-android&lt;/a&gt; project published in January, we are redirecting the compilation object to create static libraries. Theses libraries are included in the final application binary. But it&amp;rsquo;s not enough: we must also tell to Python to look for the library entry point in the application binary, instead of dlopen(). So in the python dynload loader:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;return (dl_funcptr) dlsym(RTLD_MAIN_ONLY, funcname)&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This way, Python will always look at the application binary, and never need to use dlopen().&lt;/p&gt;&#10;&lt;p&gt;If you are worried that Apple would reject a Python-based application, or even using Kivy altogether, we have tested it for you: the game that won the Kivy contest has been packaged for IOS, submitted to Apple&amp;hellip; and accepted. You can found &lt;a href="http://itunes.apple.com/us/app/deflectouch/id505729681"&gt;Deflectouch on iTunes&lt;/a&gt; (&lt;a href="https://github.com/stocyr/Deflectouch"&gt;source code&lt;/a&gt;).&lt;/p&gt;&#10;&lt;p&gt;Anyway, &lt;a href="http://kivy.org"&gt;Kivy&lt;/a&gt; is now officially supporting 5 platforms: Windows, Linux, MacOSX, Android and IOS!&lt;/p&gt;&#10;&lt;p&gt;Enjoy :)&lt;/p&gt;&#10;</description></item><item><title>Kivy programming contest #1 is over!</title><link>https://txzone.net/2012/02/kivy-programming-contest-1-is-over/</link><pubDate>Mon, 06 Feb 2012 10:34:54 +0000</pubDate><guid>https://txzone.net/2012/02/kivy-programming-contest-1-is-over/</guid><description>&lt;p&gt;During January, we hosted a contest for promoting the &lt;a href="http://kivy.org/"&gt;Kivy&lt;/a&gt; framework. The goal was simple: create a game using Kivy, without external non-pure python dependencies. All the entries have been submitted on our sponsor &lt;a href="http://github.com/"&gt;Github&lt;/a&gt; (and thanks to &lt;a href="http://notionink.com"&gt;NotionInk&lt;/a&gt;), under a compatible OSS licence. The contest registered 21 entries, and &lt;a href="http://kivy.org/#contest"&gt;11 submissions&lt;/a&gt; was valid.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="http://kivy.org/#contest"&gt;&lt;img src="https://txzone.net/media/remote/kivy.org/contest2012-end-featured.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Our winners are:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/stocyr/Deflectouch"&gt;Deflectouch&lt;/a&gt;, from Cyril Stoller&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/Zogg/FishLife"&gt;FishLife&lt;/a&gt;, from Zogg&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/niavlys/memoryKivy"&gt;memoryKivy&lt;/a&gt;, from Niavlys&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/dcower/centripetal"&gt;Centripetal&lt;/a&gt;, from Dilon Cower&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/wilsaj/flingy"&gt;Flingy&lt;/a&gt;, from Andy Wilson&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;In term of numbers, everything is growing:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;19919 unique visitors for the website (vs 9772 in December)&lt;/li&gt;&#10;&lt;li&gt;+56 subscribers on the mailing list (192 in total)&lt;/li&gt;&#10;&lt;li&gt;229 messages on kivy-users (vs 94 in December)&lt;/li&gt;&#10;&lt;li&gt;23 pull requests (vs 6 in December)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;That was a great event so far, with a perfect timing: Kivy have now 1 year old! (first release was 1st February 2011).&lt;/p&gt;&#10;</description></item><item><title>Introducing "Python for Android"</title><link>https://txzone.net/2012/01/introducing-python-for-android/</link><pubDate>Sun, 08 Jan 2012 16:20:06 +0000</pubDate><guid>https://txzone.net/2012/01/introducing-python-for-android/</guid><description>&lt;p&gt;I&amp;rsquo;m glad to share a new project called &lt;a href="https://github.com/kivy/python-for-android"&gt;Python for Android&lt;/a&gt;. The goal of this project is to &lt;strong&gt;package your python application into an APK&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://github.com/kivy/python-for-android"&gt;https://github.com/kivy/python-for-android&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;The project is under the umbrella of Kivy organization, but is not designed to be limited to Kivy only. Read the documentation to correctly install the NDK/SDK Android, and set the needed environment variables.&lt;/p&gt;&#10;&lt;p&gt;The packaging is done in 4 steps:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Ensure you have Android SDK/NDK downloaded and correctly installed&lt;/li&gt;&#10;&lt;li&gt;Ensure you have some environment set&lt;/li&gt;&#10;&lt;li&gt;Create a Python distribution containing the selected modules&lt;/li&gt;&#10;&lt;li&gt;Use that distribution to build an APK of your Python application&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Creating the python distribution is as simple as that:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;# create a simple distribution with python + PIL + Kivy&#10;./distribute.sh -m &amp;#34;pil kivy&amp;#34;&#10;&#10;# create a distribution with python + openssl + pil + kivy&#10;./distribute.sh -m &amp;#34;openssl pil kivy&amp;#34;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A directory &lt;code&gt;dist/default&lt;/code&gt; will be created, including the result of the whole arm compilation.&#10;Available libraries as for today: jpeg pil png sdl sqlite3 pygame kivy android libxml2 libxslt lxml ffmpeg openssl.&lt;/p&gt;&#10;&lt;p&gt;The second step is a little bit harder, since you need to provide more information for Android:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;cd dist/default&#10;./build.py --package org.test.touchtracer --name touchtracer \&#10;--version 1.0 --dir ~/code/kivy/examples/demo/touchtracer debug installd&#10;&#10;# --package: java name of your application&#10;# --name: title of your application&#10;# --version: version of your application&#10;# --dir: location of your application containing the main.py&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then you&amp;rsquo;ll get a nicely &lt;code&gt;bin/touchtracer-1.0-debug.apk&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;Pro:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;A blacklist.txt file that can be used to exclude files in the final APK&lt;/li&gt;&#10;&lt;li&gt;Reusable distribution for other applications&lt;/li&gt;&#10;&lt;li&gt;Modular recipes architecture&lt;/li&gt;&#10;&lt;li&gt;Be able to build independents python distributions&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Cons:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;You need a main.py file that will be used for starting your application&lt;/li&gt;&#10;&lt;li&gt;Only one java bootstrap available, using OpenGL ES 2.0.&lt;/li&gt;&#10;&lt;li&gt;Only Kivy toolkit is working. I&amp;rsquo;m sure that other people can enhance it to add other toolkit recipes. But for example, pygame is not gonna to work because the android project is OpenGL ES 2.0: pygame drawing will not work.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;I hope you&amp;rsquo;ll like it :)&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;We would like to thank Renpy / PGS4A for its initial pygame for android project&lt;/em&gt;&lt;/p&gt;&#10;</description></item><item><title>Kivy programming contest #1</title><link>https://txzone.net/2011/12/kivy-programming-contest-1/</link><pubDate>Mon, 26 Dec 2011 10:29:55 +0000</pubDate><guid>https://txzone.net/2011/12/kivy-programming-contest-1/</guid><description>&lt;p&gt;&lt;img src="https://txzone.net/media/2011/12/kivy-icon-128.png" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="http://kivy.org/"&gt;Kivy&lt;/a&gt;, an open source project for building cross platform applications and user interfaces, is announcing its 1st programming contest. The contest will start with the publication of official rules on January 1st. Registrations will be accepted through January 25th, and submissions will be accepted through January 31st. Prizes include Nvidia Tegra 2 android tablets from NotionInk, One-year “bronze” plans and t-shirts.&lt;/p&gt;&#10;&lt;p&gt;The goal of the contest is to encourage interested developers to learn more about Kivy, which is a cross platform Application and User Interface software library for the python programming language. Kivy applications run on Linux, Windows, OSX, Android (and iOS). The framework supports most inputs protocols and devices like WM_Touch, WM_Pen, Mac OS X Trackpad and Magic Mouse, single/multi touch screens, Mtdev, Linux Kernel HID, TUIO, and uses pure hardware accelerated rendering to enable developers to really take user interfaces to a new level.&lt;/p&gt;&#10;&lt;p&gt;The contest is sponsored by &lt;a href="http://www.notionink.com/"&gt;NotionInk&lt;/a&gt;, an indian company that designs tablets PCs, and &lt;a href="http://github.com/"&gt;Github&lt;/a&gt;, a web-based hosting service for software developments projects.&lt;/p&gt;&#10;&lt;p&gt;Join the contest at : &lt;a href="http://kivy.org/#contest"&gt;http://kivy.org/#contest&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Kivy 1.0.8 released ! What's next ?</title><link>https://txzone.net/2011/10/kivy-1-0-8-released-whats-next/</link><pubDate>Wed, 26 Oct 2011 23:09:07 +0000</pubDate><guid>https://txzone.net/2011/10/kivy-1-0-8-released-whats-next/</guid><description>&lt;p&gt;101 days after 1.0.7, &lt;a href="http://kivy.org/"&gt;Kivy 1.0.8&lt;/a&gt; have been released (&lt;a href="http://kivy.org/#changelog"&gt;changelog&lt;/a&gt;).&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://txzone.net/media/2011/10/kivy-1.0.81.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;This release include:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;New widgets: Virtual Keyboard, Accordion, ProgressBar&lt;/li&gt;&#10;&lt;li&gt;Video support on android - &lt;a href="http://github.com/tito/ffmpeg-android"&gt;Python bindings for ffmpeg&lt;/a&gt; have been done and are available on github. Theses are focused to be usable on android within Kivy project, but any help to clean and make the code more crossplatform is welcome !&lt;/li&gt;&#10;&lt;li&gt;Scroll wheel support in scrollview&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;1.6x more performance on Kivy langage&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Support for GIF image + set of images in Zip files&lt;/li&gt;&#10;&lt;li&gt;Bezier and stipple lines in graphics instructions&lt;/li&gt;&#10;&lt;li&gt;&amp;hellip; and lot of improvements and fixes !&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;A documentation translation project have been &lt;a href="https://groups.google.com/d/topic/kivy-dev/2s5sA8PHb4U/discussion"&gt;started&lt;/a&gt; (thanks for &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt; for generating gettext translations automatically from python autodoc). Help us at: &lt;a href="http://translation.kivy.org/"&gt;http://translation.kivy.org/&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;And now, where to go ?&lt;/p&gt;&#10;&lt;p&gt;The roadmap is not written, since what we do is mostly depending of our interests / jobs / contributions.&#10;But community is growing fast ! I see &lt;a href="https://github.com/tito/kivy/pull/281"&gt;$N multistroke recognizer&lt;/a&gt;, GSOC integration (better macosx integration), iOS port, better android packaging, unit test, better desktop integration, widget theming support, 3D graphics instructions&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;If you still hesitating about using Kivy&amp;hellip; just look at the frontpage for the current awesome projects made by the community. And they are lot of others projects going to be released during the next month ! We are also glad to see some big companies to use Kivy as the base for building their products.&#10;If you have also cool project going on, don&amp;rsquo;t hesitate to share :)&lt;/p&gt;&#10;&lt;p&gt;To finish, here is a video from Cyril that playing on &lt;a href="https://github.com/stocyr/IcarusTouch"&gt;Icarus Touch&lt;/a&gt;, an instrument that use Kivy for his UI. Awesome work !&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=u4NRu7mBXtA"&gt;▶ Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Fixing perl errors when using gitolite + ssh + custom locales</title><link>https://txzone.net/2011/10/fixing-perl-errors-when-using-gitolite-ssh-custom-locales/</link><pubDate>Tue, 18 Oct 2011 09:44:09 +0000</pubDate><guid>https://txzone.net/2011/10/fixing-perl-errors-when-using-gitolite-ssh-custom-locales/</guid><description>&lt;p&gt;If you have locale issues on a server, and your server is english only, this kind of issues can happen:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ git push origin master&#10;perl: warning: Setting locale failed.&#10;perl: warning: Please check that your locale settings:&#10;&#9;LANGUAGE = (unset),&#10;&#9;LC_ALL = (unset),&#10;&#9;LC_MESSAGES = &amp;#34;fr_FR.UTF-8&amp;#34;,&#10;&#9;LC_COLLATE = &amp;#34;fr_FR.UTF-8&amp;#34;,&#10;&#9;LC_CTYPE = &amp;#34;fr_FR.UTF-8&amp;#34;,&#10;&#9;LANG = &amp;#34;en_US.utf8&amp;#34;&#10; are supported and installed on your system.&#10;perl: warning: Falling back to the standard locale (&amp;#34;C&amp;#34;).&#10;Everything up-to-date&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You might want to check your &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; and look at the &lt;code&gt;AcceptEnv&lt;/code&gt; token.&#10;On this ssh server, it was:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;# Allow client to pass locale environment variables&#10;AcceptEnv LANG LC_*&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My locale environment was passed to the server, but the server doesn&amp;rsquo;t know about fr. Since i don&amp;rsquo;t want to install fr locales, just comment that line:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;# Allow client to pass locale environment variables&#10;# AcceptEnv LANG LC_*&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Done.&lt;/p&gt;&#10;</description></item><item><title>Texture compression, why does it matter ?</title><link>https://txzone.net/2011/09/texture-compression-why-does-it-matter/</link><pubDate>Sun, 04 Sep 2011 10:44:22 +0000</pubDate><guid>https://txzone.net/2011/09/texture-compression-why-does-it-matter/</guid><description>&lt;p&gt;&lt;a href="https://txzone.net/media/2011/09/museotouch2.png"&gt;&lt;img src="https://txzone.net/media/2011/09/museotouch2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;We all care about cash, time, life, love, and if you&amp;rsquo;re doing computer graphics, you might care about the memory consumption of your graphics card. Why ? For the same reason when you running out of cash :)&lt;/p&gt;&#10;&lt;p&gt;I&amp;rsquo;ll explain why does it matter to compress texture, and compare available possibilities. My personnal goal is to be able to load a lot of FULL HD pictures on tablet, for a museum project. The analysis is focused on DXT1 compression and size. I&amp;rsquo;m looking forward to ETC1 and will update that blog post with the result in the future.&lt;/p&gt;&#10;&lt;h2 id="what-are-we-dealing-with"&gt;What are we dealing with&lt;/h2&gt;&#10;&lt;p&gt;If you are doing an application that display lot of hd pictures, that&amp;rsquo;s matter. We&amp;rsquo;ll start from this simple math statement: a full HD picture is 1980x1020 with 4 channels (RGBA). Whatever if your pictures is in PNG, or JPEG, your graphics card is not able to understand it, and will store it in its memory decompressed. So this image will eat:&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;1920 x 1080 x 4 = 8294400 bytes = 7.91MB&lt;/code&gt;&#10;&lt;code&gt;1920 x 1080 x 4 + mipmaps = 10769252 bytes = 10.27MB&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;In theory. Because it might be more if your graphics card doesn&amp;rsquo;t support NPOT texture. If not, usually, the texture will be resized to the closest POT texture available, mean for us: 2048 x 2048. Then the size for POT will be:&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;2048 x 2048 x 4 = 16777216 bytes = 16MB&lt;/code&gt;&#10;&lt;code&gt;2048 x 2048 x 4 + mipmaps = 22369620 bytes = 21MB&lt;/code&gt;&lt;/p&gt;&#10;&lt;h2 id="compressions-types"&gt;Compressions types&lt;/h2&gt;&#10;&lt;p&gt;They are plenty types of compression availables. The most common are S3TC (including DXT1, DXT3, DXT5) from Savage3 originally, LATC from Nvidia, PVRTC from PowerVR, ETC1 from Ericsson&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;Not all of them are available everywhere, and it&amp;rsquo;s depending a lot from your hardware. Here is a list of tablet / vendor / texture compression available. (only tablet, not desktop computer.) Thanks to this &lt;a href="http://stackoverflow.com/questions/3881197/opengl-es-2-0-extensions-on-android-devices"&gt;stackoverflow thread about supported OpenGL ES 2.0 extensions on Android devices&lt;/a&gt;&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Tablette&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Vendor&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;a href="http://www.opengl.org/registry/specs/EXT/texture_compression_dxt1.txt"&gt;DXT1&lt;/a&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;a href="http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt"&gt;S3TC&lt;/a&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;a href="http://www.opengl.org/registry/specs/EXT/texture_compression_latc.txt"&gt;LATC&lt;/a&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;a href="http://www.khronos.org/registry/gles/extensions/IMG/IMG_texture_compression_pvrtc.txt"&gt;PVRTC&lt;/a&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;a href="http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt"&gt;ETC1&lt;/a&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;a href="http://en.wikipedia.org/wiki/3Dc"&gt;3DC&lt;/a&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;ATC&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;(desktop computer) GeForce GTX 560&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NVIDIA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Nexus One&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcom&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Toshiba Folio&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NVIDIA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;LGE Tablet&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NVIDIA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Galaxy Tab&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PowerVR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Acer Stream&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcomm&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Desire Z&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcomm&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Spica&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Samsumg&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HTC Desire&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcomm&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;VegaTab&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NVIDIA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Nexus S&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PowerVR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HTC Desire HD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcomm&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HTC Legend&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcomm&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Samsung Corby&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Qualcomm&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Droid 2&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PowerVR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Galaxy S&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PowerVR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Milestone&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PowerVR&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;X&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;We are seeing that ETC1 is standard compression for OpenGL ES 2, unfortunately, it will not work on desktop.&#10;PVRTC is specific to PowerVR device: it&amp;rsquo;s a standard on Ipad/Iphone.&lt;/p&gt;&#10;&lt;h2 id="using-dxt1"&gt;Using DXT1&lt;/h2&gt;&#10;&lt;p&gt;If you use DXT1, you need a POT image. DXT1 doesn&amp;rsquo;t work on NPOT.&lt;/p&gt;&#10;&lt;p&gt;To convert any image to DXT1 without any tool, you must know that your graphics card is capable of doing it, using specials opengl functions. But i wanted to precalculate them.&#10;&lt;a href="http://code.google.com/p/nvidia-texture-tools/"&gt;Nvidia texture tools&lt;/a&gt; contains tools for converting them, but you need an Nvidia card. For all others, you might want to look at &lt;a href="http://code.google.com/p/libsquish/"&gt;Libsquish&lt;/a&gt;. It&amp;rsquo;s designed to compress in software a raw image to DXTn.&#10;The result will be not a DXT1 &amp;ldquo;file&amp;rdquo;, because DXT1 is the compression format. The result will be stored in a DDS file, that we&amp;rsquo;ll see later about it.&lt;/p&gt;&#10;&lt;p&gt;If you want to be able to use libssquish in Python, you might want to apply my &lt;a href="http://code.google.com/p/libsquish/issues/attachmentText?id=17&amp;amp;aid=170001000&amp;amp;name=libsquish-python-binding.patch&amp;amp;token=c82cbbd3c5b614a8d798d832dedf126c"&gt;patch available on their issue tracker&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;For DXT1, the size of the file is not depending of the image content:&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;DXT1 2048x2048 RGBA = 2097152 bytes = 2MB&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;That&amp;rsquo;s already a big improvement. DXTn is able to store mipmaps of the texture too. For this size, the calculation is:&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;DXT1 2048x2048 RGBA + mipmap = 2795520 bytes = 2.73MB&lt;/code&gt;&lt;/p&gt;&#10;&lt;h2 id="comparaison-table"&gt;Comparaison table&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Type&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Resolution&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;File size&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;GPU size&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Images in a 256MB GPU&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Images in a 512MB GPU&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Raw RGBA image (POT)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2048 x 2048&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;-&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;16384KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;16&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;32&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PNG image (NPOT)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1920 x 1080&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;4373KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;8040KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;32&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;65&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PNG Image in reduced POT resolution&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1024 x 1024&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1268KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;4096KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;64&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;128&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DXT1 without mipmap&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2048 x 2048&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2048KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2048KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;128&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;256&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DXT1 without mipmap, reduced&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1024 x 1024&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;512KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;512KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;512&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1024&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DXT1 with mipmap&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2048 x 2048&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2730KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;2730KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;96&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;192&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DXT1 with mipmap, reduced&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;1024 x 1024&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;682KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;682KB&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;384&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;768&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;As soon as we use compression, what we see is:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;The file size is the same as GPU size&lt;/li&gt;&#10;&lt;li&gt;Even with POT texture compared to NPOT dxt1, we can still store 4x more images in GPU&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="and-with-kivy-"&gt;And with Kivy ?&lt;/h2&gt;&#10;&lt;p&gt;DXT1 itself is the compression format, but you cannot actually use it like that. You need to store the result is a formatted file. &lt;a href="http://msdn.microsoft.com/en-us/library/bb943991.aspx/"&gt;DDS&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="http://kivy.org/"&gt;Kivy&lt;/a&gt; is already able to read DDS files. But you must ensure that your graphics card is supporting DXT1 or S3TC. Look at &lt;a href="http://kivy.org/docs/api-kivy.graphics.opengl_utils.html?highlight=dxt#kivy.graphics.opengl_utils.gl_has_capability"&gt;gl_has_capability()&lt;/a&gt; function in Kivy then.&lt;/p&gt;&#10;</description></item><item><title>Kivy at EuroPython - Lightning explanation</title><link>https://txzone.net/2011/06/kivy-at-europython-lightning-explanation/</link><pubDate>Thu, 23 Jun 2011 13:46:27 +0000</pubDate><guid>https://txzone.net/2011/06/kivy-at-europython-lightning-explanation/</guid><description>&lt;p&gt;&lt;a href="http://kivy.org/"&gt;&lt;img src="https://txzone.net/media/2011/06/kivy-icon-64.png" alt=""&gt;&lt;/a&gt;&#10;For all the guys that was interested about Kivy lightning talk at &lt;a href="ep2011.europython.eu"&gt;EuroPython 2011&lt;/a&gt;, due to some incomprehension about what is Kivy, here is a lightning explanation to make it clear.&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="http://kivy.org/"&gt;Kivy&lt;/a&gt; is a Python framework designed for creating of Natural Users Interfaces. The framework containing abstraction for loading image, video, audio. It have a complete new approach about input events, and widgets. For example, you can use lot of widgets at the _same_ time, something not really possible in classical framework (qt, gtk&amp;hellip;): try to touch on a button while selecting something in a list. This is not only about multitouch for one user, but also for multi users. Kivy graphics engine is in OpenGL ES2, and all the widgets are using it.&lt;/p&gt;&#10;&lt;p&gt;If you write an application in top of Kivy, you can deploy it on Linux, MacOSX, Windows and Android. Without changing anything in your code. Because it&amp;rsquo;s in Python.&lt;/p&gt;&#10;&lt;p&gt;The presentation tool i&amp;rsquo;ve used is &lt;a href="http://github.com/tito/presemt"&gt;PreseMT&lt;/a&gt;. It have been made by &lt;a href="http://the-space-station.com"&gt;Christopher&lt;/a&gt; and &lt;a href="https://txzone.net/"&gt;Me&lt;/a&gt;. And it&amp;rsquo;s an application built using Kivy. A version of this tool is already published on &lt;a href="https://market.android.com/details?id=org.kivy.presemt"&gt;Android Market&lt;/a&gt;.&#10;PreseMT have been written in one week, and use lot of Kivy features. But it&amp;rsquo;s still not finished, and we are missing lot of features, like the ability to export the presentation in a &amp;ldquo;good&amp;rdquo; format. We have plan to make an export in HTML5, that will support animation too.&lt;/p&gt;&#10;&lt;p&gt;Feel free to follow me on &lt;a href="https://twitter.com/#!/mathieuvirbel"&gt;@mathieuvirbel&lt;/a&gt; !&lt;/p&gt;&#10;</description></item><item><title>Recording OpenGL output to H264 video</title><link>https://txzone.net/2011/06/recording-opengl-output-to-h264-video/</link><pubDate>Fri, 17 Jun 2011 10:48:48 +0000</pubDate><guid>https://txzone.net/2011/06/recording-opengl-output-to-h264-video/</guid><description>&lt;p&gt;&lt;a href="https://github.com/apitrace/apitrace"&gt;Apitrace&lt;/a&gt; is a tool for recording all the gl commands in a trace file. The trace file can be replay in later time, and they got a nice gui for checking all the gl call every frame, with introspection. They have a glretrace software that replay a trace file. We can use it to get the output of everyframe and push it in a gstreamer pipeline to make a video.&lt;/p&gt;&#10;&lt;p&gt;Why not using gtkRecordMyDesktop or other screen capture ? Sometime, the overhead of capturing and encoding video on live take too much CPU. And the application start to slow down. I didn&amp;rsquo;t see any slowdown using apitrace, and the trace file is very small compared to video output or raw video output.&lt;/p&gt;&#10;&lt;p&gt;So first, compile apitrace with stdout support:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ git clone git://github.com/tito/apitrace.git&#10;$ cd apitrace&#10;$ git checkout snapshot-stdout&#10;$ mkdir build&#10;$ cd build&#10;$ cmake ..&#10;$ make&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Take any opengl application, and make a trace file. The trace file will have the name of the binary. In my case, python is an alias to python2.7: the trace file will be python2.7.trace.&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ LD_PRELOAD=./glxtrace.so python ~/code/kivy/examples/demo/pictures/main.py&#10;# replay for fun now&#10;$ ./glretrace python2.7.trace&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To be able to make a video from the trace file, you need to know the size of the window, and the initial framerate. Here, my example is running at 800x600, 60fps:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ ./glretrace -sr python2.7-trace | \&#10; gst-launch fdsrc ! \&#10; videoparse width=800 height=600 format=rgbx framerate=60 ! \&#10; videoflip method=5 ! videorate ! ffmpegcolorspace ! \&#10; video/x-raw-yuv,width=800,height=600,framerate=\(fraction\)30/1 \&#10; x264enc pass=quant ! avimux ! filesink location=output.avi&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The final video will be saved in output.avi. You can check the video output here :&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=5vTHyxw91Ec"&gt;▶ Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Designing Configuration and Settings UI for Kivy</title><link>https://txzone.net/2011/06/designing-configuration-and-settings-ui-for-kivy/</link><pubDate>Thu, 09 Jun 2011 12:19:29 +0000</pubDate><guid>https://txzone.net/2011/06/designing-configuration-and-settings-ui-for-kivy/</guid><description>&lt;p&gt;From 3 weeks now, i&amp;rsquo;m working on packaging kivy application, to create a installer/bundle/deb of a Kivy application. The reason is simple: as soon as you are doing an application, the user should not care about installing Kivy itself. In the same time, i&amp;rsquo;ve work on other projects that require to have their own configuration. From a long time, we always wanted to have some in-app settings for configure Kivy. Even Android have a &amp;ldquo;settings&amp;rdquo; button, we wanted to use it. :)&lt;/p&gt;&#10;&lt;p&gt;This is now possible.&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://txzone.net/media/2011/06/app-settings.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;Yes, it look like the honeycomb settings panel. Kind of. Well.&lt;/p&gt;&#10;&lt;p&gt;The configuration is automatically handled by the App class, and you can put your own token on it. The settings UI (that you&amp;rsquo;re seeing on the screen) is created from a JSON definitions. You can press F1 or the settings key on android to bring the settings panel, hook the on_config_change to know when a configuration token is changed from the settings ui, etc.&lt;/p&gt;&#10;&lt;p&gt;This is available in master, and will be published on next 1.0.7 version. If you are interested, please read and give feedback about the &lt;a href="http://kivy.org/docs/api-kivy.app.html"&gt;App documentation&lt;/a&gt; and the &lt;a href="http://kivy.org/docs/api-kivy.uix.settings.html"&gt;Settings documentation&lt;/a&gt;.&lt;/p&gt;&#10;</description></item><item><title>NPOT textures support in OpenGL</title><link>https://txzone.net/2011/06/npot-textures-support-in-opengl/</link><pubDate>Sun, 05 Jun 2011 21:20:21 +0000</pubDate><guid>https://txzone.net/2011/06/npot-textures-support-in-opengl/</guid><description>&lt;p&gt;If you already done OpenGL development, you should be aware of POT (Power of two) texture. Because of very old conventions, the texture size must be a power of two size. Not necessarily the same for width and height though : 256x256 is valid as 128x512.&lt;/p&gt;&#10;&lt;p&gt;The usual thing to do when you want to load an NPOT texture (like 23x61) is to:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;take his closed POT size: 32x64&lt;/li&gt;&#10;&lt;li&gt;depending of the book you&amp;rsquo;re reading: blit/strech the 23x61 to the 32x64 texture&lt;/li&gt;&#10;&lt;li&gt;OR blit without stretch, and adjust texture coordinate (this is what kivy does right now.)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;The downside part of this approach is that you&amp;rsquo;re lost a part of memory. Bad.&lt;/p&gt;&#10;&lt;p&gt;While ago, i remember to found the &lt;a href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt"&gt;Rectangle texture&lt;/a&gt; support from NVidia. Aaah, finally, is it what we was waiting from a long time ? Erm, no. Their implementation have lot of downsides:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;The usage of a specific texture target: GL_TEXTURE_RECTANGLE_NV&lt;/li&gt;&#10;&lt;li&gt;No mipmap support&lt;/li&gt;&#10;&lt;li&gt;The texture coordinates are not normalized from 0-1&amp;hellip; but from 0-width/height of the image&lt;/li&gt;&#10;&lt;li&gt;Some wrap mode are not supported (GL_REPEAT for eg.)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;But today&amp;hellip; i discover that most graphics card are supporting rectangle texture. If the extension &lt;a href="http://www.nvidia.com/dev_content/nvopenglspecs/GL_ARB_texture_non_power_of_two.txt"&gt;GL_ARB_texture_non_power_of_two&lt;/a&gt; (&lt;a href="http://www.khronos.org/registry/gles/extensions/OES/OES_texture_npot.txt"&gt;OES_texture_npot&lt;/a&gt; for OpenGL ES platform), you can finally ensure that loading NPOT texture will&amp;hellip; just work as expected :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;You can still use GL_TEXTURE_2D&lt;/li&gt;&#10;&lt;li&gt;Mipmapping are supported&lt;/li&gt;&#10;&lt;li&gt;Texture coordinates are from 0-1&lt;/li&gt;&#10;&lt;li&gt;All wrap mode are supported&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;A little note here, in OpenGL ES 2, they have a native support for NPOT texture, but with somes limitations related to mipmapping.&lt;/p&gt;&#10;&lt;p&gt;If you want to just load NPOT texture safely without using rectangle texture, just check the availability of theses extensions :&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glGetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GL_EXTENSIONS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;npot_support&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;OES_texture_npot&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GL_ARB_texture_non_power_of_two&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Using microphone peak as input</title><link>https://txzone.net/2011/05/using-microphone-peak-as-input/</link><pubDate>Tue, 24 May 2011 12:01:21 +0000</pubDate><guid>https://txzone.net/2011/05/using-microphone-peak-as-input/</guid><description>&lt;p&gt;I&amp;rsquo;m currently on a project that involve disabled peoples, audio and kinect. Theses boys and girls are doing lot of loud sounds, so the idea is to use their sound as a trigger. We can use gstreamer to make that work quite easily, cause it have everything we need: a &lt;a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-pulsesrc.html"&gt;audio source&lt;/a&gt;, and &lt;a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-level.html"&gt;level calculator&lt;/a&gt;.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pygst&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pygst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.10&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;gobject&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threads_init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;pulsesrc ! audioconvert ! &amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;audio/x-raw-int,channels=2,rate=44100,endianness=1234,&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;width=32,depth=32,signed=(bool)True !&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;level name=level interval=10000000 !&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;fakesink&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;level&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_bus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_signal_watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_peak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# filter only on level messages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;structure&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;peak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# read peak&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;peak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;peak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# connect the callback&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;show_peak&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# start the pipeline&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATE_PLAYING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_context_default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output could be something like this :&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;peak -35.2370719856&#10;peak -35.0252114393&#10;peak -10.8591229158&#10;peak -4.6007387433&#10;peak -4.85102463679&#10;peak -6.45292575653&#10;peak -6.83102903668&#10;peak -7.39486319074&#10;peak -13.9852340247&#10;peak -17.423901433&#10;peak -35.0852178272&#10;peak -35.8725208237&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next, we can use that information to record their sound, and use it on some scenario. So, instead of use the fakesink, we can use &lt;a href="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gst-plugins-base-libs-appsink.html"&gt;appsink&lt;/a&gt;. This module allow you to read the buffer pushed by the previous module. So we can put theses buffers into a list, and use them when needed :)&lt;/p&gt;&#10;&lt;p&gt;The state machine will handle the 3 phases :&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Wait for a peak &amp;gt; -30db&lt;/li&gt;&#10;&lt;li&gt;Recording the sound, stop when the peak is &amp;lt; -32db&lt;/li&gt;&#10;&lt;li&gt;Replay the last sound&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Note: The -30 / -32 are taken from my tests. If you have more noise, you need to adjust theses triggers.&lt;/p&gt;&#10;&lt;p&gt;And here is the final example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pygst&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pygst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0.10&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;gobject&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threads_init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pipeline_play&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;pulsesrc ! audioconvert ! &amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;audio/x-raw-int,channels=2,rate=44100,endianness=1234,&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;width=32,depth=32,signed=(bool)True !&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;level name=level interval=10000000 !&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;appsink name=app emit-signals=True&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wait&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;buffers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;level&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;app&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_bus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_signal_watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_peak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;peak&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# filter only on level messages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;structure&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;peak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# read peak&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;peak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enqueue_audio_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;buffers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pull-buffer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;play_sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;pipeline_play&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;audio.dat&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pipeline_play&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pipeline_play&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_launch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;filesrc location=audio.dat !&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;audio/x-raw-int,channels=2,rate=44100,endianness=1234,&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;width=32,depth=32,signed=(bool)True !&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;audioamplify amplification=2 ! autoaudiosink&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pipeline_play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATE_NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pipeline_play&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATE_PLAYING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# connect the callback&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;show_peak&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;new-buffer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enqueue_audio_buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# start the pipeline&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATE_PLAYING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# main loop&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gobject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main_context_default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peak&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# wait for somebody to make a sound&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wait&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;record&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# discard any buffer&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;buffers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# record the current audio, until the peak is going down&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;record&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;peak&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;replay&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# replay last sound&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;replay&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;play_sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wait&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Usage: Just make a sound&amp;hellip; and it will replay just after.&lt;/p&gt;&#10;</description></item><item><title>Kivy on Android, part 2</title><link>https://txzone.net/2011/04/kivy-on-android-part-2/</link><pubDate>Tue, 12 Apr 2011 20:56:09 +0000</pubDate><guid>https://txzone.net/2011/04/kivy-on-android-part-2/</guid><description>&lt;p&gt;Hi guys,&lt;/p&gt;&#10;&lt;p&gt;Look like people are following my blog and waiting for android version of Kivy.&#10;We have a launcher that you can already use. Check the :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="http://kivy.org/docs/installation/installation-android.html"&gt;How do install Kivy on android&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="http://kivy.org/docs/guide/android.html"&gt;Kivy on Android guide&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Maybe during the next release, or a little bit after, i&amp;rsquo;ll release a software to create an Android package of a Kivy application. The code is already on launchpad, but it&amp;rsquo;s still a work in progress. As soon as i have finished, i&amp;rsquo;ll publish it on &lt;a href="https://groups.google.com/group/kivy-dev"&gt;kivy-dev mailing list&lt;/a&gt;. If you didn&amp;rsquo;t subscribe yet, do it now ! :)&lt;/p&gt;&#10;&lt;p&gt;More to come by the end of that week&amp;hellip; !&lt;/p&gt;&#10;</description></item></channel></rss>