#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2020, Google Inc.
#
# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
#
# Generate formats definitions from YAML

import argparse
import re
import string
import sys
import yaml


class DRMFourCC(object):
    format_regex = re.compile(r"#define (DRM_FORMAT_[A-Z0-9_]+)[ \t]+fourcc_code\(('.', '.', '.', '.')\)")
    mod_vendor_regex = re.compile(r"#define DRM_FORMAT_MOD_VENDOR_([A-Z0-9_]+)[ \t]+([0-9a-fA-Fx]+)")
    mod_regex = re.compile(r"#define ([A-Za-z0-9_]+)[ \t]+fourcc_mod_code\(([A-Z0-9_]+), ([0-9a-fA-Fx]+)\)")

    def __init__(self, filename):
        self.formats = {}
        self.vendors = {}
        self.mods = {}

        for line in open(filename, 'rb').readlines():
            line = line.decode('utf-8')

            match = DRMFourCC.format_regex.match(line)
            if match:
                format, fourcc = match.groups()
                self.formats[format] = fourcc
                continue

            match = DRMFourCC.mod_vendor_regex.match(line)
            if match:
                vendor, value = match.groups()
                self.vendors[vendor] = int(value, 0)
                continue

            match = DRMFourCC.mod_regex.match(line)
            if match:
                mod, vendor, value = match.groups()
                self.mods[mod] = (vendor, int(value, 0))
                continue

    def fourcc(self, name):
        return self.formats[name]

    def mod(self, name):
        vendor, value = self.mods[name]
        return self.vendors[vendor], value


def generate_h(formats, drm_fourcc):
    template = string.Template('constexpr PixelFormat ${name}{ __fourcc(${fourcc}), __mod(${mod}) };')

    fmts = []

    for format in formats:
        name, format = format.popitem()
        fourcc = drm_fourcc.fourcc(format['fourcc'])
        if format.get('big-endian'):
            fourcc += '| DRM_FORMAT_BIG_ENDIAN'

        data = {
            'name': name,
            'fourcc': fourcc,
            'mod': '0, 0',
        }

        mod = format.get('mod')
        if mod:
            data['mod'] = '%u, %u' % drm_fourcc.mod(mod)

        fmts.append(template.substitute(data))

    return {'formats': '\n'.join(fmts)}


def fill_template(template, data):

    template = open(template, 'rb').read()
    template = template.decode('utf-8')
    template = string.Template(template)
    return template.substitute(data)


def main(argv):

    # Parse command line arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-o', dest='output', metavar='file', type=str,
                        help='Output file name. Defaults to standard output if not specified.')
    parser.add_argument('input', type=str,
                        help='Input file name.')
    parser.add_argument('template', type=str,
                        help='Template file name.')
    parser.add_argument('drm_fourcc', type=str,
                        help='Path to drm_fourcc.h.')
    args = parser.parse_args(argv[1:])

    data = open(args.input, 'rb').read()
    formats = yaml.safe_load(data)['formats']
    drm_fourcc = DRMFourCC(args.drm_fourcc)

    data = generate_h(formats, drm_fourcc)
    data = fill_template(args.template, data)

    if args.output:
        output = open(args.output, 'wb')
        output.write(data.encode('utf-8'))
        output.close()
    else:
        sys.stdout.write(data)

    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv))
<a id='n21' href='#n21'>21</a>
<a id='n22' href='#n22'>22</a>
<a id='n23' href='#n23'>23</a>
<a id='n24' href='#n24'>24</a>
<a id='n25' href='#n25'>25</a>
<a id='n26' href='#n26'>26</a>
<a id='n27' href='#n27'>27</a>
<a id='n28' href='#n28'>28</a>
<a id='n29' href='#n29'>29</a>
<a id='n30' href='#n30'>30</a>
<a id='n31' href='#n31'>31</a>
<a id='n32' href='#n32'>32</a>
<a id='n33' href='#n33'>33</a>
<a id='n34' href='#n34'>34</a>
<a id='n35' href='#n35'>35</a>
<a id='n36' href='#n36'>36</a>
<a id='n37' href='#n37'>37</a>
<a id='n38' href='#n38'>38</a>
<a id='n39' href='#n39'>39</a>
<a id='n40' href='#n40'>40</a>
<a id='n41' href='#n41'>41</a>
<a id='n42' href='#n42'>42</a>
<a id='n43' href='#n43'>43</a>
<a id='n44' href='#n44'>44</a>
<a id='n45' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
<a id='n88' href='#n88'>88</a>
<a id='n89' href='#n89'>89</a>
<a id='n90' href='#n90'>90</a>
<a id='n91' href='#n91'>91</a>
<a id='n92' href='#n92'>92</a>
<a id='n93' href='#n93'>93</a>
<a id='n94' href='#n94'>94</a>
<a id='n95' href='#n95'>95</a>
<a id='n96' href='#n96'>96</a>
<a id='n97' href='#n97'>97</a>
<a id='n98' href='#n98'>98</a>
<a id='n99' href='#n99'>99</a>
<a id='n100' href='#n100'>100</a>
<a id='n101' href='#n101'>101</a>
<a id='n102' href='#n102'>102</a>
<a id='n103' href='#n103'>103</a>
<a id='n104' href='#n104'>104</a>
<a id='n105' href='#n105'>105</a>
<a id='n106' href='#n106'>106</a>
<a id='n107' href='#n107'>107</a>
<a id='n108' href='#n108'>108</a>
<a id='n109' href='#n109'>109</a>
<a id='n110' href='#n110'>110</a>
<a id='n111' href='#n111'>111</a>
<a id='n112' href='#n112'>112</a>
<a id='n113' href='#n113'>113</a>
<a id='n114' href='#n114'>114</a>
<a id='n115' href='#n115'>115</a>
<a id='n116' href='#n116'>116</a>
<a id='n117' href='#n117'>117</a>
<a id='n118' href='#n118'>118</a>
<a id='n119' href='#n119'>119</a>
<a id='n120' href='#n120'>120</a>
<a id='n121' href='#n121'>121</a>
<a id='n122' href='#n122'>122</a>
<a id='n123' href='#n123'>123</a>
<a id='n124' href='#n124'>124</a>
<a id='n125' href='#n125'>125</a>
<a id='n126' href='#n126'>126</a>
<a id='n127' href='#n127'>127</a>
<a id='n128' href='#n128'>128</a>
<a id='n129' href='#n129'>129</a>
<a id='n130' href='#n130'>130</a>
<a id='n131' href='#n131'>131</a>
<a id='n132' href='#n132'>132</a>
<a id='n133' href='#n133'>133</a>
<a id='n134' href='#n134'>134</a>
<a id='n135' href='#n135'>135</a>
<a id='n136' href='#n136'>136</a>
<a id='n137' href='#n137'>137</a>
<a id='n138' href='#n138'>138</a>
<a id='n139' href='#n139'>139</a>
<a id='n140' href='#n140'>140</a>
<a id='n141' href='#n141'>141</a>
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
<a id='n170' href='#n170'>170</a>
<a id='n171' href='#n171'>171</a>
<a id='n172' href='#n172'>172</a>
<a id='n173' href='#n173'>173</a>
<a id='n174' href='#n174'>174</a>
<a id='n175' href='#n175'>175</a>
<a id='n176' href='#n176'>176</a>
</pre></td>
<td class='lines'><pre><code><span class="hl com">/* SPDX-License-Identifier: GPL-2.0-or-later */</span>
<span class="hl com">/*</span>
<span class="hl com"> * Copyright (C) 2019, Google Inc.</span>
<span class="hl com"> *</span>
<span class="hl com"> * threads.cpp - Threads test</span>
<span class="hl com"> */</span>

<span class="hl ppc">#include &lt;chrono&gt;</span>
<span class="hl ppc">#include &lt;iostream&gt;</span>
<span class="hl ppc">#include &lt;memory&gt;</span>
<span class="hl ppc">#include &lt;pthread.h&gt;</span>
<span class="hl ppc">#include &lt;thread&gt;</span>
<span class="hl ppc">#include &lt;time.h&gt;</span>

<span class="hl ppc">#include &lt;libcamera/base/thread.h&gt;</span>

<span class="hl ppc">#include</span> <span class="hl pps">&quot;test.h&quot;</span><span class="hl ppc"></span>

<span class="hl kwa">using namespace</span> std<span class="hl opt">;</span>
<span class="hl kwa">using namespace</span> libcamera<span class="hl opt">;</span>

<span class="hl kwc">class</span> DelayThread <span class="hl opt">:</span> <span class="hl kwc">public</span> Thread
<span class="hl opt">{</span>
<span class="hl kwc">public</span><span class="hl opt">:</span>
	<span class="hl kwd">DelayThread</span><span class="hl opt">(</span><span class="hl kwc">chrono</span><span class="hl opt">::</span><span class="hl kwc">steady_clock</span><span class="hl opt">::</span>duration duration<span class="hl opt">)</span>
		<span class="hl opt">:</span> <span class="hl kwd">duration_</span><span class="hl opt">(</span>duration<span class="hl opt">)</span>
	<span class="hl opt">{</span>
	<span class="hl opt">}</span>

<span class="hl kwc">protected</span><span class="hl opt">:</span>
	<span class="hl kwb">void</span> <span class="hl kwd">run</span><span class="hl opt">()</span>
	<span class="hl opt">{</span>
		<span class="hl kwc">this_thread</span><span class="hl opt">::</span><span class="hl kwd">sleep_for</span><span class="hl opt">(</span>duration_<span class="hl opt">);</span>
	<span class="hl opt">}</span>

<span class="hl kwc">private</span><span class="hl opt">:</span>
	<span class="hl kwc">chrono</span><span class="hl opt">::</span><span class="hl kwc">steady_clock</span><span class="hl opt">::</span>duration duration_<span class="hl opt">;</span>
<span class="hl opt">};</span>

<span class="hl kwc">class</span> CancelThread <span class="hl opt">:</span> <span class="hl kwc">public</span> Thread
<span class="hl opt">{</span>
<span class="hl kwc">public</span><span class="hl opt">:</span>
	<span class="hl kwd">CancelThread</span><span class="hl opt">(</span><span class="hl kwb">bool</span> <span class="hl opt">&amp;</span>cancelled<span class="hl opt">)</span>
		<span class="hl opt">:</span> <span class="hl kwd">cancelled_</span><span class="hl opt">(</span>cancelled<span class="hl opt">)</span>
	<span class="hl opt">{