diff --git a/go.mod b/go.mod index 0c66d56..a949c5c 100644 --- a/go.mod +++ b/go.mod @@ -3,19 +3,19 @@ module github.com/go-musicfox/spotifox go 1.21 require ( - github.com/anhoder/foxful-cli v0.1.4 + github.com/anhoder/foxful-cli v0.3.3 github.com/arcspace/go-arc-sdk v0.0.0-20230811172934-db6c05cc94b2 github.com/arcspace/go-librespot v0.0.0-20230811173922-2e901b172fbe github.com/buger/jsonparser v1.1.1 github.com/charmbracelet/bubbles v0.16.1 - github.com/charmbracelet/bubbletea v0.24.2 + github.com/charmbracelet/bubbletea v0.25.0 github.com/charmbracelet/lipgloss v0.8.0 - github.com/ebitengine/purego v0.4.0 - github.com/faiface/beep v1.1.0 - github.com/go-musicfox/notificator v0.1.0 + github.com/ebitengine/purego v0.7.0 + github.com/go-musicfox/notificator v0.1.2 github.com/godbus/dbus/v5 v5.1.0 github.com/gookit/gcli/v2 v2.3.4 github.com/gookit/ini/v2 v2.2.2 + github.com/gopxl/beep v1.4.0 github.com/mattn/go-runewidth v0.0.15 github.com/muesli/termenv v0.15.2 github.com/nicksnyder/go-i18n/v2 v2.2.1 @@ -25,33 +25,25 @@ require ( github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/zmb3/spotify/v2 v2.3.1 go.etcd.io/bbolt v1.3.7 + golang.org/x/mod v0.8.0 golang.org/x/oauth2 v0.7.0 + golang.org/x/text v0.13.0 ) require ( capnproto.org/go/capnp/v3 v3.0.0-alpha-29 // indirect - github.com/brynbellomy/klog v0.0.0-20200414031930-87fbf2e555ae // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/rs/cors v1.9.0 // indirect - golang.org/x/net v0.17.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.57.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect - zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae // indirect -) - -require ( github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect + github.com/brynbellomy/klog v0.0.0-20200414031930-87fbf2e555ae // indirect + github.com/ebitengine/oto/v3 v3.1.0 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 // indirect - github.com/gookit/color v1.5.3 // indirect - github.com/gookit/goutil v0.6.10 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gookit/color v1.5.2 // indirect + github.com/gookit/goutil v0.6.7 // indirect github.com/hajimehoshi/go-mp3 v0.3.4 // indirect - github.com/hajimehoshi/oto v1.0.1 // indirect github.com/jfreymuth/oggvorbis v1.0.5 // indirect github.com/jfreymuth/vorbis v1.0.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect @@ -61,29 +53,31 @@ require ( github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.6 // indirect + github.com/robotn/gohook v0.41.0 // indirect + github.com/rs/cors v1.9.0 // indirect github.com/sahilm/fuzzy v0.1.0 // indirect + github.com/vcaesar/keycode v0.10.1 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/exp/shiny v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/image v0.10.0 // indirect - golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda // indirect - golang.org/x/mod v0.12.0 - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 + golang.org/x/crypto v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/term v0.17.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect + google.golang.org/grpc v1.57.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect + zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae // indirect ) replace ( + capnproto.org/go/capnp/v3 v3.0.0-alpha-29 => capnproto.org/go/capnp/v3 v3.0.0-alpha.29 github.com/arcspace/go-librespot v0.0.0-20230811173922-2e901b172fbe => github.com/go-musicfox/go-librespot v0.1.0 - github.com/charmbracelet/bubbletea v0.24.2 => github.com/go-musicfox/bubbletea v0.24.1 - github.com/cnsilvan/UnblockNeteaseMusic v0.0.0-20230310083816-92b59c95a366 => github.com/go-musicfox/UnblockNeteaseMusic v0.1.2 - github.com/faiface/beep v1.1.0 => github.com/go-musicfox/beep v1.2.4 - github.com/frolovo22/tag v0.0.2 => github.com/go-musicfox/tag v1.0.2 + github.com/charmbracelet/bubbletea v0.25.0 => github.com/go-musicfox/bubbletea v0.25.0-foxful github.com/gookit/gcli/v2 v2.3.4 => github.com/anhoder/gcli/v2 v2.3.5 + github.com/gopxl/beep v1.4.0 => github.com/go-musicfox/beep v1.4.1 github.com/hajimehoshi/go-mp3 v0.3.4 => github.com/go-musicfox/go-mp3 v0.3.3 - github.com/hajimehoshi/oto v1.0.1 => github.com/go-musicfox/oto v1.0.3 github.com/shkh/lastfm-go => github.com/go-musicfox/lastfm-go v0.0.2 + zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae => github.com/zenhack/go-util v0.0.0-20230607025951-8b02fee814ae ) diff --git a/go.sum b/go.sum index 92ad36e..d85575a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -capnproto.org/go/capnp/v3 v3.0.0-alpha-29 h1:ICLhiy4Jmp0d7hLQO+HzFAVIft/oxpPAUPV8tqx+eUE= -capnproto.org/go/capnp/v3 v3.0.0-alpha-29/go.mod h1:+ysMHvOh1EWNOyorxJWs1omhRFiDoKxKkWQACp54jKM= +capnproto.org/go/capnp/v3 v3.0.0-alpha.29 h1:Kp8kq5GVl1ANe0mxv+cl1ISEPAv45phpdMIPpB8cgN8= +capnproto.org/go/capnp/v3 v3.0.0-alpha.29/go.mod h1:+ysMHvOh1EWNOyorxJWs1omhRFiDoKxKkWQACp54jKM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -37,9 +37,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/anhoder/foxful-cli v0.1.4 h1:W6l0VKv6GIDGHwIoodn7Q7p8o8olwVjmaO38lFFwyww= -github.com/anhoder/foxful-cli v0.1.4/go.mod h1:TyHexyRKpyb5iM9mMC1UVxe2RRkgr3StNwxxVBi5LDo= +github.com/anhoder/foxful-cli v0.3.3 h1:46yWhlEujS+NquwHVXi9I/84V1/2/Lmn4hgFPToMAxY= +github.com/anhoder/foxful-cli v0.3.3/go.mod h1:M6018fGlfMbZIGGWgYC82Thk8u57VJguePEg3BbyPWA= github.com/anhoder/gcli/v2 v2.3.5 h1:tiFK7xnZxNHIevEaRtfT4Cfhz4OYFcJaeB1S55dxxBU= github.com/anhoder/gcli/v2 v2.3.5/go.mod h1:AOxm27rFzNDLpBrwbW1pAh3ofebpXOQk/9x009qC9y8= github.com/arcspace/go-arc-sdk v0.0.0-20230811172934-db6c05cc94b2 h1:2witwGPGGe92Y1wkBUB3RsTMU79yVMOMPqyfWP8vfBQ= @@ -62,45 +61,37 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cocoonlife/goflac v0.0.0-20170210142907-50ea06ed5a9d/go.mod h1:swNVb00X8NOH/qeHuqnqiyfecAnWlThLX+NbH8r6yHw= -github.com/cocoonlife/testify v0.0.0-20160218172820-792cc1faeb64/go.mod h1:LoCAz53rbPcqs8Da2BjB/yDy4gxMtiSQmqnYI/DGH+U= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.4.0 h1:RQVuMIxQPQ5iCGEJvjQ17YOK+1tMKjVau2FUMvXH4HE= -github.com/ebitengine/purego v0.4.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= +github.com/ebitengine/oto/v3 v3.1.0 h1:9tChG6rizyeR2w3vsygTTTVVJ9QMMyu00m2yBOCch6U= +github.com/ebitengine/oto/v3 v3.1.0/go.mod h1:IK1QTnlfZK2GIB6ziyECm433hAdTaPpOsGMLhEyEGTg= +github.com/ebitengine/purego v0.7.0 h1:HPZpl61edMGCEW6XK2nsR6+7AnJ3unUxpTZBkkIXnMc= +github.com/ebitengine/purego v0.7.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 h1:VRIbnDWRmAh5yBdz+J6yFMF5vso1It6vn+WmM/5l7MA= github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776/go.mod h1:9wvnDu3YOfxzWM9Cst40msBF1C2UdQgDv962oTxSuMs= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= -github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs= -github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498= -github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-musicfox/beep v1.2.4 h1:ajavZLIBQTisWMj6eBUQXSFjHy8nYKwegKXbCRP2JHI= -github.com/go-musicfox/beep v1.2.4/go.mod h1:QB92mt1VbsDuBu14lEbOQCrHT6oYM09bRzzESO5/dGE= -github.com/go-musicfox/bubbletea v0.24.1 h1:ElKRFpwu18vjWmxb0DTfyY1rEgIz6UfRkIOlasU1QRQ= -github.com/go-musicfox/bubbletea v0.24.1/go.mod h1:CH++FOcBybavOwuOrKgYOl5Xr+Hac0Gk5afQIpk5WMQ= +github.com/go-musicfox/beep v1.4.1 h1:1U7nnypAez/OgEBy+Kf9pnxL4ZYBk4OFASGKIi5nhuU= +github.com/go-musicfox/beep v1.4.1/go.mod h1:FLIgNbvzfm53Fe9yu6PEeEGbdFiA6ubejExj5dp2ctI= +github.com/go-musicfox/bubbletea v0.25.0-foxful h1:HRvsptwgdgK7ltKFfddIcgRQezMA9Gagi0QD8hlMkFo= +github.com/go-musicfox/bubbletea v0.25.0-foxful/go.mod h1:0d493G5q9s3TvUgvzfo1h8S4aGTyfyqQwyCSB088uwU= github.com/go-musicfox/go-librespot v0.1.0 h1:7BCcmyBrTkRXjHkMB9DRE3td9LmWmlg483t5IJIv1Pw= github.com/go-musicfox/go-librespot v0.1.0/go.mod h1:XQ3of3y1Pq5c6iRT+SqrWjD42FlGuBvMDWx5iePKwhc= github.com/go-musicfox/go-mp3 v0.3.3 h1:xBfUaYhbG6LipvPLDSlawLSO1A5z3InSJz8vB3+3bHc= github.com/go-musicfox/go-mp3 v0.3.3/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo= github.com/go-musicfox/lastfm-go v0.0.2 h1:S/jXVK/bSi9JGZGm7ynQWY3nQ8gvMzbpHf2yKZ9ge+g= github.com/go-musicfox/lastfm-go v0.0.2/go.mod h1:QAs3ciul8v40zzwgDPDVq12CSACAIZUHXSSeBJLCdQE= -github.com/go-musicfox/notificator v0.1.0 h1:bWkLOIDYZKpmZMfNwsbPETqKJvWVrxyRvxqFPsd+5Vw= -github.com/go-musicfox/notificator v0.1.0/go.mod h1:1FtZ3LEbv/I+EnrHOagRI2e3CwltRFhda6xLR3kOViI= -github.com/go-musicfox/oto v1.0.3 h1:O6LIcfSRPgVcsgE2/yCmh4e7nOoX80yPCFgWSMLVXCc= -github.com/go-musicfox/oto v1.0.3/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos= +github.com/go-musicfox/notificator v0.1.2 h1:rJbJr2bbdqYX+wkPJuAszWxO4lXXE7EvwXgUZErOVhY= +github.com/go-musicfox/notificator v0.1.2/go.mod h1:1FtZ3LEbv/I+EnrHOagRI2e3CwltRFhda6xLR3kOViI= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -156,31 +147,23 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= -github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= -github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= github.com/gookit/goutil v0.6.6/go.mod h1:D++7kbQd/6vECyYTxB5tq6AKDIG9ZYwZNhubWJvN9dw= -github.com/gookit/goutil v0.6.10 h1:iq7CXOf+fYLvrVAh3+ZoLgufGfK65TwbzE8NpnPGtyk= -github.com/gookit/goutil v0.6.10/go.mod h1:qqrPoX+Pm6YmxqqccgkNLPirTFX7UYMES1SK+fokqQU= +github.com/gookit/goutil v0.6.7 h1:Sz0y5eslPZ8M2lUhRaSMnwEeX5nb9z7SoCsw0ZbMwe4= +github.com/gookit/goutil v0.6.7/go.mod h1:ti+JpLBGSN83ga6SSZa6uozhntToWSzOPm2z1hvpQSc= github.com/gookit/ini/v2 v2.2.2 h1:3B8abZJrVH1vi/7TU4STuTBxdhiAq1ORSt6NJZCahaI= github.com/gookit/ini/v2 v2.2.2/go.mod h1:wGEfnBxv+7nVXytWM44tiqczv5hLKJ+m9MaA2uJg3iM= -github.com/hajimehoshi/go-mp3 v0.3.1/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= -github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= -github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos= github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A= -github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= -github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk= github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ= github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= -github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0= github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE= github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -192,19 +175,15 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU= -github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -219,7 +198,6 @@ github.com/nicksnyder/go-i18n/v2 v2.2.1 h1:aOzRCdwsJuoExfZhoiXHy4bjruwCMdt5otbYo github.com/nicksnyder/go-i18n/v2 v2.2.1/go.mod h1:fF2++lPHlo+/kPaj3nB0uxtPwzlPm+BlgwGX7MkeGj0= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -229,8 +207,10 @@ github.com/raitonoberu/lyricsapi v0.0.0-20230113141433-eded40b42d7c h1:+haxwIg5L github.com/raitonoberu/lyricsapi v0.0.0-20230113141433-eded40b42d7c/go.mod h1:OZuR43VBUauOq6BfM6M8Frcw7JPOSa2wKHP6lIqomhg= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg= +github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robotn/gohook v0.41.0 h1:h1vK3w/UQpq0YkIiGnxm9Awv85W54esL0/NUYGueggo= +github.com/robotn/gohook v0.41.0/go.mod h1:FedpuAkVqzM5t67L5fcf3hSSCUDO9cM5YkWCw1U+nuc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= @@ -248,7 +228,10 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tinylib/msgp v1.1.5 h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= -github.com/tosone/minimp3 v1.0.2/go.mod h1:N6vjknGR7PboMTyJVhe/7RHNQiIc0jWZxFKlSWdfzwc= +github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw= +github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= +github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= +github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= @@ -257,6 +240,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zenhack/go-util v0.0.0-20230607025951-8b02fee814ae h1:21C0ORMJ468Syvrfcl+qQt7FSIx5F2wDXm+1WwurT0Y= +github.com/zenhack/go-util v0.0.0-20230607025951-8b02fee814ae/go.mod h1:1LtNdPAs8WH+BTcQiZAOo2MIKD/5jyK/u7sZ9ZPe5SE= github.com/zmb3/spotify/v2 v2.3.1 h1:aEyIPotROM3JJjHMCImFROgnPIUpzVo8wymYSaPSd9w= github.com/zmb3/spotify/v2 v2.3.1/go.mod h1:+LVh9CafHu7SedyqYmEf12Rd01dIVlEL845yNhksW0E= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= @@ -273,8 +258,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -286,15 +271,10 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/exp/shiny v0.0.0-20230522175609-2e198f4a06a1 h1:NxHSRPlbeyFGDc6rU7YsvxV/4bXS9XhuvUt5pP63XUs= -golang.org/x/exp/shiny v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:UH99kUObWAZkDnWqppdQe5ZhPYESUw8I0zVV1uWBR+0= -golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.10.0 h1:gXjUUtwtx5yOE0VKWq1CH4IJAClq4UGgUA3i+rpON9M= -golang.org/x/image v0.10.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -306,10 +286,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda h1:O+EUvnBNPwI4eLthn8W5K+cS8zQZfgTABPLNm6Bna34= -golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -317,9 +294,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -352,8 +328,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -373,18 +349,16 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -408,20 +382,21 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -432,7 +407,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -539,8 +513,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -553,8 +527,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.57.1 h1:upNTNqv0ES+2ZOOqACwVtS3Il8M12/+Hz41RCPzAjQg= -google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -589,5 +563,3 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae h1:MjNLCVT0QYNmXStslQk+ugtOvFCVpC7H6mWtkEI2PxI= -zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae/go.mod h1:1LtNdPAs8WH+BTcQiZAOo2MIKD/5jyK/u7sZ9ZPe5SE= diff --git a/internal/macdriver/avcore/avcore.go b/internal/macdriver/avcore/avcore.go index aa68fdd..8b5c73f 100644 --- a/internal/macdriver/avcore/avcore.go +++ b/internal/macdriver/avcore/avcore.go @@ -12,7 +12,7 @@ var importOnce sync.Once func importFramework() { importOnce.Do(func() { - _, err := purego.Dlopen("AVFoundation.framework/AVFoundation", purego.RTLD_GLOBAL) + _, err := purego.Dlopen("/System/Library/Frameworks/AVFoundation.framework/AVFoundation", purego.RTLD_GLOBAL) if err != nil { panic(err) } diff --git a/internal/macdriver/avcore/avplayer_test.go b/internal/macdriver/avcore/avplayer_test.go index 62cee0e..5ba51c8 100644 --- a/internal/macdriver/avcore/avplayer_test.go +++ b/internal/macdriver/avcore/avplayer_test.go @@ -4,6 +4,8 @@ package avcore import ( "fmt" + "path/filepath" + "runtime" "testing" "time" @@ -37,7 +39,9 @@ func TestAVPlayer(t *testing.T) { } defer player.Release() - file := core.String("./testdata/a.mp3") + _, path, _, _ := runtime.Caller(0) + uri := "/" + filepath.Join(filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(path)))), "testdata", "a.map3") + file := core.String(uri) defer file.Release() url := core.NSURL_fileURLWithPath(file) defer url.Release() diff --git a/internal/macdriver/avcore/testdata/a.mp3 b/internal/macdriver/avcore/testdata/a.mp3 deleted file mode 100644 index 15533c5..0000000 Binary files a/internal/macdriver/avcore/testdata/a.mp3 and /dev/null differ diff --git a/internal/macdriver/cocoa/cocoa.go b/internal/macdriver/cocoa/cocoa.go index fa1cdb6..74b428b 100644 --- a/internal/macdriver/cocoa/cocoa.go +++ b/internal/macdriver/cocoa/cocoa.go @@ -12,7 +12,7 @@ var importOnce sync.Once func importFramework() { importOnce.Do(func() { - _, err := purego.Dlopen("AppKit.framework/AppKit", purego.RTLD_GLOBAL) + _, err := purego.Dlopen("/System/Library/Frameworks/AppKit.framework/AppKit", purego.RTLD_GLOBAL) if err != nil { panic(err) } @@ -34,6 +34,8 @@ type CGRect struct { Size CGSize } -type NSPoint = CGPoint -type NSRect = CGRect -type NSSize = CGSize +type ( + NSPoint = CGPoint + NSRect = CGRect + NSSize = CGSize +) diff --git a/internal/macdriver/cocoa/nsapplication_delegate.go b/internal/macdriver/cocoa/nsapplication_delegate.go index 587afba..46794a9 100644 --- a/internal/macdriver/cocoa/nsapplication_delegate.go +++ b/internal/macdriver/cocoa/nsapplication_delegate.go @@ -4,59 +4,54 @@ package cocoa import ( "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" "github.com/go-musicfox/spotifox/internal/macdriver/core" ) -func init() { - importFramework() - - var err error - class_DefaultAppDelegate, err = objc.RegisterClass(&defaultAppDelegateBinding{}) - if err != nil { - panic(err) - } -} - -var ( - class_DefaultAppDelegate objc.Class -) - var ( + class_DefaultAppDelegate objc.Class sel_applicationDidFinishLaunching = objc.RegisterName("applicationDidFinishLaunching:") sel_applicationShouldTerminateAfterLastWindowClosed = objc.RegisterName("applicationShouldTerminateAfterLastWindowClosed:") -) -var ( defaultDelegate *defaultAppDelegate ) -type defaultAppDelegateBinding struct { - //nolint:golint,unused - isa objc.Class `objc:"NSDefaultAppDelegate : NSObject "` +func init() { + importFramework() + + var err error + class_DefaultAppDelegate, err = objc.RegisterClass( + "NSDefaultAppDelegate", + objc.GetClass("NSObject"), + []*objc.Protocol{objc.GetProtocol("NSApplicationDelegate")}, + []objc.FieldDef{}, + []objc.MethodDef{ + { + Cmd: sel_applicationDidFinishLaunching, + Fn: applicationDidFinishLaunching, + }, + { + Cmd: sel_applicationShouldTerminateAfterLastWindowClosed, + Fn: applicationShouldTerminateAfterLastWindowClosed, + }, + }, + ) + if err != nil { + panic(err) + } } -func (defaultAppDelegateBinding) ApplicationDidFinishLaunching(_ objc.SEL, notification objc.ID) { +func applicationDidFinishLaunching(id objc.ID, cmd objc.SEL, notification objc.ID) { if defaultDelegate != nil && defaultDelegate.didFinishLaunchingCallback != nil { defaultDelegate.didFinishLaunchingCallback(notification) } } -func (defaultAppDelegateBinding) ApplicationShouldTerminateAfterLastWindowClosed(_ objc.SEL, _ objc.ID) bool { +func applicationShouldTerminateAfterLastWindowClosed(id objc.ID, cmd objc.SEL, notification objc.ID) bool { return true } -func (defaultAppDelegateBinding) Selector(metName string) objc.SEL { - switch metName { - case "ApplicationDidFinishLaunching": - return sel_applicationDidFinishLaunching - case "ApplicationShouldTerminateAfterLastWindowClosed": - return sel_applicationShouldTerminateAfterLastWindowClosed - default: - return 0 - } -} - type defaultAppDelegate struct { core.NSObject didFinishLaunchingCallback func(notification objc.ID) diff --git a/internal/macdriver/cocoa/nsimage.go b/internal/macdriver/cocoa/nsimage.go index 2395cbf..1e4f5d4 100644 --- a/internal/macdriver/cocoa/nsimage.go +++ b/internal/macdriver/cocoa/nsimage.go @@ -4,6 +4,7 @@ package cocoa import ( "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" "github.com/go-musicfox/spotifox/internal/macdriver/core" ) diff --git a/internal/macdriver/cocoa/nsnotificationcenter.go b/internal/macdriver/cocoa/nsnotificationcenter.go index b14290c..c2ab17f 100644 --- a/internal/macdriver/cocoa/nsnotificationcenter.go +++ b/internal/macdriver/cocoa/nsnotificationcenter.go @@ -4,6 +4,7 @@ package cocoa import ( "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" "github.com/go-musicfox/spotifox/internal/macdriver/core" ) diff --git a/internal/macdriver/cocoa/nsworkspace.go b/internal/macdriver/cocoa/nsworkspace.go index 2fcee63..85618ec 100644 --- a/internal/macdriver/cocoa/nsworkspace.go +++ b/internal/macdriver/cocoa/nsworkspace.go @@ -4,6 +4,7 @@ package cocoa import ( "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver/core" ) diff --git a/internal/macdriver/core/core.go b/internal/macdriver/core/core.go index b9aea8d..f03fd53 100644 --- a/internal/macdriver/core/core.go +++ b/internal/macdriver/core/core.go @@ -9,6 +9,7 @@ import ( "github.com/ebitengine/purego" "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" ) @@ -23,7 +24,7 @@ var ( func importFramework() { importOnce.Do(func() { var err error - if _, err = purego.Dlopen("Foundation.framework/Foundation", purego.RTLD_GLOBAL); err != nil { + if _, err = purego.Dlopen("/System/Library/Frameworks/Foundation.framework/Foundation", purego.RTLD_GLOBAL); err != nil { panic(err) } if objcLib, err = purego.Dlopen("/usr/lib/libobjc.A.dylib", purego.RTLD_GLOBAL); err != nil { @@ -38,8 +39,10 @@ func init() { purego.RegisterLibFunc(&objc_autoreleasePoolPop, objcLib, "objc_autoreleasePoolPop") } -type NSUInteger = uint32 -type NSInteger = int32 +type ( + NSUInteger = uint32 + NSInteger = int32 +) type NSObject struct { objc.ID diff --git a/internal/macdriver/core/nsautoreleasepool.go b/internal/macdriver/core/nsautoreleasepool.go index 7fcfb82..73ceb2b 100644 --- a/internal/macdriver/core/nsautoreleasepool.go +++ b/internal/macdriver/core/nsautoreleasepool.go @@ -1,7 +1,10 @@ +//go:build darwin + package core import ( "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" ) diff --git a/internal/macdriver/core/nsstring.go b/internal/macdriver/core/nsstring.go index d03bdb3..f92d587 100644 --- a/internal/macdriver/core/nsstring.go +++ b/internal/macdriver/core/nsstring.go @@ -41,7 +41,7 @@ func (s NSString) InitWithUTF8String(utf8 string) NSString { } func (s NSString) String() string { - return string(unsafe.Slice((*byte)(unsafe.Pointer(s.Send(sel_UTF8String))), s.Send(macdriver.SEL_length))) + return string(unsafe.Slice((*byte)(unsafe.Pointer(s.Send(sel_UTF8String))), s.Send(macdriver.SEL_length))) //nolint:govet } func String(str string) NSString { diff --git a/internal/macdriver/mediaplayer/mediaplayer.go b/internal/macdriver/mediaplayer/mediaplayer.go index cc79765..b4698f0 100644 --- a/internal/macdriver/mediaplayer/mediaplayer.go +++ b/internal/macdriver/mediaplayer/mediaplayer.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/ebitengine/purego" + "github.com/go-musicfox/spotifox/internal/macdriver/core" ) @@ -13,7 +14,7 @@ var importOnce sync.Once func importFramework() { importOnce.Do(func() { - _, err := purego.Dlopen("MediaPlayer.framework/MediaPlayer", purego.RTLD_GLOBAL) + _, err := purego.Dlopen("/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer", purego.RTLD_GLOBAL) if err != nil { panic(err) } diff --git a/internal/player/beep_decoder.go b/internal/player/beep_decoder.go index 97c6b93..af30312 100644 --- a/internal/player/beep_decoder.go +++ b/internal/player/beep_decoder.go @@ -3,9 +3,9 @@ package player import ( "io" - "github.com/faiface/beep" - "github.com/faiface/beep/mp3" - "github.com/faiface/beep/vorbis" + "github.com/gopxl/beep" + "github.com/gopxl/beep/mp3" + "github.com/gopxl/beep/vorbis" "github.com/pkg/errors" ) diff --git a/internal/player/beep_player.go b/internal/player/beep_player.go index 21ca681..71f358b 100644 --- a/internal/player/beep_player.go +++ b/internal/player/beep_player.go @@ -5,16 +5,20 @@ import ( "io" "net/http" "os" - "path" + "path/filepath" "sync" "time" "github.com/go-musicfox/spotifox/utils" + "github.com/gopxl/beep" + "github.com/gopxl/beep/effects" + "github.com/gopxl/beep/speaker" "github.com/zmb3/spotify/v2" +) - "github.com/faiface/beep" - "github.com/faiface/beep/effects" - "github.com/faiface/beep/speaker" +const ( + sampleRate = beep.SampleRate(44100) + resampleQuiality = 4 ) type beepPlayer struct { @@ -41,7 +45,7 @@ type beepPlayer struct { close chan struct{} } -func NewBeepPlayer() Player { +func NewBeepPlayer() *beepPlayer { p := &beepPlayer{ state: Stopped, @@ -64,9 +68,11 @@ func NewBeepPlayer() Player { return p } +// listen 开始监听 func (p *beepPlayer) listen() { var ( done = make(chan struct{}) + resp *http.Response reader io.ReadCloser err error ctx context.Context @@ -80,7 +86,11 @@ func (p *beepPlayer) listen() { } ) - cacheFile := path.Join(utils.GetLocalDataDir(), "music_cache") + if err = speaker.Init(sampleRate, sampleRate.N(time.Millisecond*200)); err != nil { + panic(err) + } + + cacheFile := filepath.Join(utils.GetLocalDataDir(), "music_cache") for { select { case <-p.close: @@ -96,7 +106,7 @@ func (p *beepPlayer) listen() { if p.timer != nil { p.timer.SetPassed(0) } - // clean pre + // 清理上一轮 if cancel != nil { cancel() } @@ -115,9 +125,12 @@ func (p *beepPlayer) listen() { if reader, err = p.curMusic.NewAssetReader(); err != nil { utils.Logger().Printf("new asset reader err: %+v", err) p.stopNoLock() - continue + goto nextLoop + } else { + reader = resp.Body } + // 边下载边播放 go func(ctx context.Context, cacheWFile *os.File, read io.ReadCloser) { defer func() { if utils.Recover(true) { @@ -138,7 +151,7 @@ func (p *beepPlayer) listen() { cacheReader, _ := os.OpenFile(cacheFile, os.O_RDONLY, 0666) // 使用新的文件后需手动Seek到上次播放处 lastStreamer := p.curStreamer - defer lastStreamer.Close() + defer func() { _ = lastStreamer.Close() }() pos := lastStreamer.Position() if p.curStreamer, p.curFormat, err = DecodeSong(p.curMusic.SongType(), cacheReader); err != nil { p.stopNoLock() @@ -151,7 +164,7 @@ func (p *beepPlayer) listen() { pos = 1 } _ = p.curStreamer.Seek(pos) - p.ctrl.Streamer = beep.Seq(beep.StreamerFunc(p.streamer), beep.Callback(doneHandle)) + p.ctrl.Streamer = beep.Seq(p.resampleStreamer(p.curFormat.SampleRate), beep.Callback(doneHandle)) } }(ctx, p.cacheWriter, reader) @@ -159,7 +172,7 @@ func (p *beepPlayer) listen() { if err = utils.WaitForNBytes(p.cacheReader, N, time.Millisecond*100, 50); err != nil { utils.Logger().Printf("WaitForNBytes err: %+v", err) p.stopNoLock() - continue + goto nextLoop } } else { // 单曲循环以及歌单只有一首歌时不再请求网络 @@ -170,14 +183,12 @@ func (p *beepPlayer) listen() { if p.curStreamer, p.curFormat, err = DecodeSong(p.curMusic.SongType(), p.cacheReader); err != nil { p.stopNoLock() - break + goto nextLoop } - if err = speaker.Init(p.curFormat.SampleRate, p.curFormat.SampleRate.N(time.Millisecond*200)); err != nil { - panic(err) - } + utils.Logger().Printf("current song sample rate: %d", p.curFormat.SampleRate) - p.ctrl.Streamer = beep.Seq(beep.StreamerFunc(p.streamer), beep.Callback(doneHandle)) + p.ctrl.Streamer = beep.Seq(p.resampleStreamer(p.curFormat.SampleRate), beep.Callback(doneHandle)) p.volume.Streamer = p.ctrl speaker.Play(p.volume) @@ -197,6 +208,8 @@ func (p *beepPlayer) listen() { }) p.resumeNoLock() prevSongId = p.curMusic.SongInfo.ID + + nextLoop: p.l.Unlock() } } @@ -204,9 +217,11 @@ func (p *beepPlayer) listen() { // Play 播放音乐 func (p *beepPlayer) Play(music MediaAsset) { + timer := time.NewTimer(time.Second) + defer timer.Stop() select { case p.musicChan <- music: - default: + case <-timer.C: } } @@ -256,7 +271,7 @@ func (p *beepPlayer) Seek(duration time.Duration) { } if p.state == Playing || p.state == Paused { speaker.Lock() - newPos := p.curFormat.SampleRate.N(duration) + newPos := sampleRate.N(duration) if newPos < 0 { newPos = 0 @@ -277,6 +292,7 @@ func (p *beepPlayer) Seek(duration time.Duration) { } } +// UpVolume 调大音量 func (p *beepPlayer) UpVolume() { if p.volume.Volume >= 0 { return @@ -288,6 +304,7 @@ func (p *beepPlayer) UpVolume() { p.volume.Volume += 0.25 } +// DownVolume 调小音量 func (p *beepPlayer) DownVolume() { if p.volume.Volume <= -5 { return @@ -303,7 +320,7 @@ func (p *beepPlayer) DownVolume() { } func (p *beepPlayer) Volume() int { - return int((p.volume.Volume + 5) * 100 / 5) // to 0~100 + return int((p.volume.Volume + 5) * 100 / 5) // 转为0~100存储 } func (p *beepPlayer) SetVolume(volume int) { @@ -328,6 +345,7 @@ func (p *beepPlayer) pausedNoLock() { p.setState(Paused) } +// Paused 暂停播放 func (p *beepPlayer) Paused() { p.l.Lock() defer p.l.Unlock() @@ -343,6 +361,7 @@ func (p *beepPlayer) resumeNoLock() { p.setState(Playing) } +// Resume 继续播放 func (p *beepPlayer) Resume() { p.l.Lock() defer p.l.Unlock() @@ -358,21 +377,26 @@ func (p *beepPlayer) stopNoLock() { p.setState(Stopped) } +// Stop 停止 func (p *beepPlayer) Stop() { p.l.Lock() defer p.l.Unlock() p.stopNoLock() } +// Toggle 切换状态 func (p *beepPlayer) Toggle() { switch p.State() { case Paused, Stopped: p.Resume() case Playing: p.Paused() + default: + p.Resume() } } +// Close 关闭 func (p *beepPlayer) Close() { p.l.Lock() defer p.l.Unlock() @@ -382,12 +406,11 @@ func (p *beepPlayer) Close() { } close(p.close) speaker.Clear() + speaker.Close() } func (p *beepPlayer) reset() { - speaker.Clear() - speaker.Close() - // close pre timer + // 关闭旧计时器 if p.timer != nil { p.timer.Stop() } @@ -402,9 +425,16 @@ func (p *beepPlayer) reset() { p.curStreamer = nil } p.cacheDownloaded = false + speaker.Clear() } func (p *beepPlayer) streamer(samples [][2]float64) (n int, ok bool) { + defer func() { + if err := recover(); err != nil { + utils.Logger().Printf("streamer panic: %+v", err) + p.Stop() + } + }() n, ok = p.curStreamer.Stream(samples) err := p.curStreamer.Err() if err == nil && (ok || p.cacheDownloaded) { @@ -427,3 +457,10 @@ func (p *beepPlayer) streamer(samples [][2]float64) (n int, ok bool) { p.resumeNoLock() return } + +func (p *beepPlayer) resampleStreamer(old beep.SampleRate) beep.Streamer { + if old == sampleRate { + return beep.StreamerFunc(p.streamer) + } + return beep.Resample(resampleQuiality, old, sampleRate, beep.StreamerFunc(p.streamer)) +} diff --git a/internal/player/osx_player_darwin.go b/internal/player/osx_player_darwin.go index c3aad35..1e1bf0e 100644 --- a/internal/player/osx_player_darwin.go +++ b/internal/player/osx_player_darwin.go @@ -30,7 +30,7 @@ type osxPlayer struct { close chan struct{} } -func NewOsxPlayer() Player { +func NewOsxPlayer() *osxPlayer { p := &osxPlayer{ state: Stopped, timeChan: make(chan time.Duration), diff --git a/internal/player/osx_player_handler_darwin.go b/internal/player/osx_player_handler_darwin.go index c613ded..7be02ce 100644 --- a/internal/player/osx_player_handler_darwin.go +++ b/internal/player/osx_player_handler_darwin.go @@ -4,34 +4,38 @@ package player import ( "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" "github.com/go-musicfox/spotifox/internal/macdriver/avcore" "github.com/go-musicfox/spotifox/internal/macdriver/core" ) -func init() { - var err error - class_AVPlayerHandler, err = objc.RegisterClass(&playerHandlerBinding{}) - if err != nil { - panic(err) - } -} - var ( class_AVPlayerHandler objc.Class + sel_handleFinish = objc.RegisterName("handleFinish:") _player *osxPlayer ) -var ( - sel_handleFinish = objc.RegisterName("handleFinish:") -) - -type playerHandlerBinding struct { - //nolint:golint,unused - isa objc.Class `objc:"AVPlayerHandler : NSObject"` +func init() { + var err error + class_AVPlayerHandler, err = objc.RegisterClass( + "AVPlayerHandler", + objc.GetClass("NSObject"), + []*objc.Protocol{}, + []objc.FieldDef{}, + []objc.MethodDef{ + { + Cmd: sel_handleFinish, + Fn: handleFinish, + }, + }, + ) + if err != nil { + panic(err) + } } -func (playerHandlerBinding) HandleFinish(_ objc.SEL, event objc.ID) { +func handleFinish(id objc.ID, cmd objc.SEL, event objc.ID) { // 这里会出现两次通知 core.Autorelease(func() { var item avcore.AVPlayerItem @@ -45,15 +49,6 @@ func (playerHandlerBinding) HandleFinish(_ objc.SEL, event objc.ID) { }) } -func (playerHandlerBinding) Selector(metName string) objc.SEL { - switch metName { - case "HandleFinish": - return sel_handleFinish - default: - return 0 - } -} - type playerHandler struct { core.NSObject } diff --git a/internal/state_handler/remote_command_handler_darwin.go b/internal/state_handler/remote_command_handler_darwin.go index 5b52460..5f8e823 100644 --- a/internal/state_handler/remote_command_handler_darwin.go +++ b/internal/state_handler/remote_command_handler_darwin.go @@ -6,24 +6,12 @@ import ( "time" "github.com/ebitengine/purego/objc" + "github.com/go-musicfox/spotifox/internal/macdriver" "github.com/go-musicfox/spotifox/internal/macdriver/core" "github.com/go-musicfox/spotifox/internal/macdriver/mediaplayer" ) -func init() { - var err error - class_RemoteCommandHandler, err = objc.RegisterClass(&remoteCommandHandlerBinding{}) - if err != nil { - panic(err) - } -} - -var ( - class_RemoteCommandHandler objc.Class - _playerController Controller -) - var ( sel_handlePlayCommand = objc.RegisterName("handlePlayCommand:") sel_handlePauseCommand = objc.RegisterName("handlePauseCommand:") @@ -46,38 +34,113 @@ var ( sel_handleDisableLanguageOptionCommand = objc.RegisterName("handleDisableLanguageOptionCommand:") sel_handleWillSleepOrPowerOff = objc.RegisterName("handleWillSleepOrPowerOff:") sel_handleDidWake = objc.RegisterName("handleDidWake:") - - sels = map[string]objc.SEL{ - "HandlePlayCommand": sel_handlePlayCommand, - "HandlePauseCommand": sel_handlePauseCommand, - "HandleStopCommand": sel_handleStopCommand, - "HandleTogglePlayPauseCommand": sel_handleTogglePlayPauseCommand, - "HandleNextTrackCommand": sel_handleNextTrackCommand, - "HandlePreviousTrackCommand": sel_handlePreviousTrackCommand, - "HandleChangeRepeatModeCommand": sel_handleChangeRepeatModeCommand, - "HandleChangeShuffleModeCommand": sel_handleChangeShuffleModeCommand, - "HandleChangePlaybackRateCommand": sel_handleChangePlaybackRateCommand, - "HandleSeekBackwardCommand": sel_handleSeekBackwardCommand, - "HandleSeekForwardCommand": sel_handleSeekForwardCommand, - "HandleSkipForwardCommand": sel_handleSkipForwardCommand, - "HandleSkipBackwardCommand": sel_handleSkipBackwardCommand, - "HandleChangePlaybackPositionCommand": sel_handleChangePlaybackPositionCommand, - "HandleLikeCommand": sel_handleLikeCommand, - "HandleDislikeCommand": sel_handleDislikeCommand, - "HandleBookmarkCommand": sel_handleBookmarkCommand, - "HandleEnableLanguageOptionCommand": sel_handleEnableLanguageOptionCommand, - "HandleDisableLanguageOptionCommand": sel_handleDisableLanguageOptionCommand, - "HandleWillSleepOrPowerOff": sel_handleWillSleepOrPowerOff, - "HandleDidWake": sel_handleDidWake, - } ) -type remoteCommandHandlerBinding struct { - //nolint:golint,unused - isa objc.Class `objc:"RemoteCommandHandler : NSObject"` +func init() { + var err error + class_RemoteCommandHandler, err = objc.RegisterClass( + "RemoteCommandHandler", + objc.GetClass("NSObject"), + []*objc.Protocol{}, + []objc.FieldDef{}, + []objc.MethodDef{ + { + Cmd: sel_handlePlayCommand, + Fn: handlePlayCommand, + }, + { + Cmd: sel_handlePauseCommand, + Fn: handlePauseCommand, + }, + { + Cmd: sel_handleStopCommand, + Fn: handleStopCommand, + }, + { + Cmd: sel_handleTogglePlayPauseCommand, + Fn: handleTogglePlayPauseCommand, + }, + { + Cmd: sel_handleNextTrackCommand, + Fn: handleNextTrackCommand, + }, + { + Cmd: sel_handlePreviousTrackCommand, + Fn: handlePreviousTrackCommand, + }, + { + Cmd: sel_handleChangeRepeatModeCommand, + Fn: handleChangeRepeatModeCommand, + }, + { + Cmd: sel_handleChangeShuffleModeCommand, + Fn: handleChangeShuffleModeCommand, + }, + { + Cmd: sel_handleChangePlaybackRateCommand, + Fn: handleChangePlaybackRateCommand, + }, + { + Cmd: sel_handleSeekBackwardCommand, + Fn: handleSeekBackwardCommand, + }, + { + Cmd: sel_handleSeekForwardCommand, + Fn: handleSeekForwardCommand, + }, + { + Cmd: sel_handleSkipForwardCommand, + Fn: handleSkipForwardCommand, + }, + { + Cmd: sel_handleSkipBackwardCommand, + Fn: handleSkipBackwardCommand, + }, + { + Cmd: sel_handleChangePlaybackPositionCommand, + Fn: handleChangePlaybackPositionCommand, + }, + { + Cmd: sel_handleLikeCommand, + Fn: handleLikeCommand, + }, + { + Cmd: sel_handleDislikeCommand, + Fn: handleDislikeCommand, + }, + { + Cmd: sel_handleBookmarkCommand, + Fn: handleBookmarkCommand, + }, + { + Cmd: sel_handleEnableLanguageOptionCommand, + Fn: handleEnableLanguageOptionCommand, + }, + { + Cmd: sel_handleDisableLanguageOptionCommand, + Fn: handleDisableLanguageOptionCommand, + }, + { + Cmd: sel_handleWillSleepOrPowerOff, + Fn: handleWillSleepOrPowerOff, + }, + { + Cmd: sel_handleDidWake, + Fn: handleDidWake, + }, + }, + ) + if err != nil { + panic(err) + } } -func (remoteCommandHandlerBinding) HandlePlayCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +var ( + class_RemoteCommandHandler objc.Class + _playerController Controller +) + +func handlePlayCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -85,7 +148,7 @@ func (remoteCommandHandlerBinding) HandlePlayCommand(_ objc.SEL, event objc.ID) return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandlePauseCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handlePauseCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -93,7 +156,7 @@ func (remoteCommandHandlerBinding) HandlePauseCommand(_ objc.SEL, event objc.ID) return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleStopCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleStopCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -101,7 +164,7 @@ func (remoteCommandHandlerBinding) HandleStopCommand(_ objc.SEL, event objc.ID) return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleTogglePlayPauseCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleTogglePlayPauseCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -109,7 +172,7 @@ func (remoteCommandHandlerBinding) HandleTogglePlayPauseCommand(_ objc.SEL, even return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleNextTrackCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleNextTrackCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -117,7 +180,7 @@ func (remoteCommandHandlerBinding) HandleNextTrackCommand(_ objc.SEL, event objc return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandlePreviousTrackCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handlePreviousTrackCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -125,35 +188,35 @@ func (remoteCommandHandlerBinding) HandlePreviousTrackCommand(_ objc.SEL, event return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleChangeRepeatModeCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleChangeRepeatModeCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleChangeShuffleModeCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleChangeShuffleModeCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleChangePlaybackRateCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleChangePlaybackRateCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleSeekBackwardCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleSeekBackwardCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleSeekForwardCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleSeekForwardCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleSkipForwardCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleSkipForwardCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleSkipBackwardCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleSkipBackwardCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleChangePlaybackPositionCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleChangePlaybackPositionCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { if _playerController == nil { return mediaplayer.MPRemoteCommandHandlerStatusCommandFailed } @@ -167,41 +230,34 @@ func (remoteCommandHandlerBinding) HandleChangePlaybackPositionCommand(_ objc.SE return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleLikeCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleLikeCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleDislikeCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleDislikeCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleBookmarkCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleBookmarkCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleEnableLanguageOptionCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleEnableLanguageOptionCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleDisableLanguageOptionCommand(_ objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { +func handleDisableLanguageOptionCommand(id objc.ID, cmd objc.SEL, event objc.ID) mediaplayer.MPRemoteCommandHandlerStatus { return mediaplayer.MPRemoteCommandHandlerStatusSuccess } -func (remoteCommandHandlerBinding) HandleWillSleepOrPowerOff(_ objc.SEL, notification objc.ID) { +func handleWillSleepOrPowerOff(id objc.ID, cmd objc.SEL, notification objc.ID) { if _playerController == nil { return } _playerController.CtrlPaused() } -func (remoteCommandHandlerBinding) HandleDidWake(_ objc.SEL, notification objc.ID) { -} - -func (remoteCommandHandlerBinding) Selector(metName string) objc.SEL { - if sel, ok := sels[metName]; ok { - return sel - } - return 0 +func handleDidWake(id objc.ID, cmd objc.SEL, notification objc.ID) { } type remoteCommandHandler struct { diff --git a/internal/state_handler/state_handler_darwin.go b/internal/state_handler/state_handler_darwin.go index d15f822..319983b 100644 --- a/internal/state_handler/state_handler_darwin.go +++ b/internal/state_handler/state_handler_darwin.go @@ -4,6 +4,7 @@ package state_handler import ( "sync" + "time" "github.com/go-musicfox/spotifox/internal/macdriver/cocoa" "github.com/go-musicfox/spotifox/internal/macdriver/core" @@ -19,7 +20,7 @@ var stateMap = map[player.State]mediaplayer.MPNowPlayingPlaybackState{ player.Interrupted: mediaplayer.MPNowPlayingPlaybackStateInterrupted, } -type Handler struct { +type RemoteControl struct { nowPlayingCenter *mediaplayer.MPNowPlayingInfoCenter remoteCommandCenter *mediaplayer.MPRemoteCommandCenter commandHandler *remoteCommandHandler @@ -34,22 +35,22 @@ const ( MediaTypeVedio ) -func NewHandler(p Controller, _ PlayingInfo) *Handler { +func NewRemoteControl(p Controller, _ PlayingInfo) *RemoteControl { playingCenter := mediaplayer.MPNowPlayingInfoCenter_defaultCenter() commandCenter := mediaplayer.MPRemoteCommandCenter_sharedCommandCenter() commandHandler := remoteCommandHandler_new(p) - handler := &Handler{ + ctrl := &RemoteControl{ nowPlayingCenter: &playingCenter, remoteCommandCenter: &commandCenter, commandHandler: &commandHandler, } - handler.registerCommands() - handler.nowPlayingCenter.SetPlaybackState(mediaplayer.MPNowPlayingPlaybackStateStopped) - return handler + ctrl.registerCommands() + ctrl.nowPlayingCenter.SetPlaybackState(mediaplayer.MPNowPlayingPlaybackStateStopped) + return ctrl } -func (s *Handler) registerCommands() { +func (s *RemoteControl) registerCommands() { number := core.NSNumber_numberWithDouble(15.0) defer number.Release() intervals := core.NSArray_arrayWithObject(number.NSObject) @@ -84,7 +85,7 @@ func (s *Handler) registerCommands() { workspaceNC.AddObserverSelectorNameObject(s.commandHandler.ID, sel_handleDidWake, core.String("NSWorkspaceDidWakeNotification"), core.NSObject{}) } -func (s *Handler) SetPlayingInfo(info PlayingInfo) { +func (s *RemoteControl) SetPlayingInfo(info PlayingInfo) { total := info.TotalDuration.Seconds() ur := info.PassedDuration.Seconds() @@ -135,7 +136,10 @@ func (s *Handler) SetPlayingInfo(info PlayingInfo) { s.nowPlayingCenter.SetNowPlayingInfo(dic.NSDictionary) } -func (s *Handler) Release() { +func (s *RemoteControl) SetPosition(time.Duration) { +} + +func (s *RemoteControl) Release() { s.nowPlayingCenter.Release() s.remoteCommandCenter.Release() } diff --git a/vendor/github.com/anhoder/foxful-cli/model/app.go b/vendor/github.com/anhoder/foxful-cli/model/app.go index 1cdc3c0..5664da9 100644 --- a/vendor/github.com/anhoder/foxful-cli/model/app.go +++ b/vendor/github.com/anhoder/foxful-cli/model/app.go @@ -38,8 +38,6 @@ func NewApp(options *Options) (a *App) { return } -type WithOption func(options *Options) - func (a *App) With(w ...WithOption) *App { for _, item := range w { if item != nil { @@ -49,20 +47,6 @@ func (a *App) With(w ...WithOption) *App { return a } -func WithHook(init, close func(a *App)) WithOption { - return func(opts *Options) { - opts.InitHook = init - opts.CloseHook = close - } -} - -func WithMainMenu(mainMenu Menu, mainMenuTitle *MenuItem) WithOption { - return func(opts *Options) { - opts.MainMenu = mainMenu - opts.MainMenuTitle = mainMenuTitle - } -} - func (a *App) Init() tea.Cmd { if a.options.InitHook != nil { a.options.InitHook(a) @@ -153,6 +137,11 @@ func (a *App) Run() error { } a.page = a.options.InitPage } + + if len(a.options.GlobalKeyHandlers) > 0 { + ListenGlobalKeys(a, a.options.GlobalKeyHandlers) + } + a.program = tea.ReplaceWithFoxfulRenderer(tea.NewProgram(a, a.options.TeaOptions...)) _, err := a.program.Run() return err diff --git a/vendor/github.com/anhoder/foxful-cli/model/global_hotkey_disabled.go b/vendor/github.com/anhoder/foxful-cli/model/global_hotkey_disabled.go new file mode 100644 index 0000000..6cc560a --- /dev/null +++ b/vendor/github.com/anhoder/foxful-cli/model/global_hotkey_disabled.go @@ -0,0 +1,8 @@ +//go:build !enable_global_hotkey + +package model + +type GlobalKeyHandler interface{} + +func ListenGlobalKeys(_ *App, _ map[string]GlobalKeyHandler) { +} diff --git a/vendor/github.com/anhoder/foxful-cli/model/global_hotkey_enabled.go b/vendor/github.com/anhoder/foxful-cli/model/global_hotkey_enabled.go new file mode 100644 index 0000000..ba71aa0 --- /dev/null +++ b/vendor/github.com/anhoder/foxful-cli/model/global_hotkey_enabled.go @@ -0,0 +1,27 @@ +//go:build enable_global_hotkey + +package model + +import ( + "strings" + + hook "github.com/robotn/gohook" +) + +type GlobalKeyHandler func(hook.Event) Page + +func ListenGlobalKeys(app *App, handlers map[string]GlobalKeyHandler) { + for global, handler := range handlers { + h := handler + keys := strings.Split(global, "+") + hook.Register(hook.KeyDown, keys, func(e hook.Event) { + page := h(e) + if page == nil { + page = app.page + } + app.program.Send(page.Msg()) + }) + } + s := hook.Start() + hook.Process(s) +} diff --git a/vendor/github.com/anhoder/foxful-cli/model/main.go b/vendor/github.com/anhoder/foxful-cli/model/main.go index 9caf141..98f09f5 100644 --- a/vendor/github.com/anhoder/foxful-cli/model/main.go +++ b/vendor/github.com/anhoder/foxful-cli/model/main.go @@ -159,7 +159,7 @@ func (m *Main) Update(msg tea.Msg, a *App) (Page, tea.Cmd) { } func (m *Main) View(a *App) string { - var windowHeight, windowWidth = a.WindowHeight(), a.WindowWidth() + windowHeight, windowWidth := a.WindowHeight(), a.WindowWidth() if windowHeight <= 0 || windowWidth <= 0 { return "" } @@ -199,7 +199,7 @@ func (m *Main) View(a *App) string { if component == nil { continue } - var view, lines = component.View(a, m) + view, lines := component.View(a, m) builder.WriteString(view) top += lines } @@ -299,7 +299,7 @@ func (m *Main) MenuTitleView(a *App, top *int, menuTitle *MenuItem) string { realString := menuTitle.OriginString() formatString := menuTitle.String() if runewidth.StringWidth(realString) > maxLen { - var menuTmp = *menuTitle + menuTmp := *menuTitle titleLen := runewidth.StringWidth(menuTmp.Title) subTitleLen := runewidth.StringWidth(menuTmp.Subtitle) if titleLen >= maxLen-1 { @@ -359,7 +359,7 @@ func (m *Main) menuListView(a *App, top *int) string { // fill blanks if maxLines > lines { - var windowWidth = a.WindowWidth() + windowWidth := a.WindowWidth() if windowWidth-m.menuStartColumn > 0 { menuListBuilder.WriteString(strings.Repeat(" ", windowWidth-m.menuStartColumn)) } @@ -455,13 +455,13 @@ func (m *Main) menuItemView(a *App, index int) (string, int) { menuName = util.SetNormalStyle(tmp) } } else if menuTitleLen+menuSubtitleLen > itemMaxLen { - var r = []rune(m.menuList[index].Subtitle) + r := []rune(m.menuList[index].Subtitle) r = append(r, []rune(" ")...) var i int if m.options.Ticker != nil { i = int(m.options.Ticker.PassedTime().Milliseconds()/500) % len(r) } - var s = make([]rune, 0, itemMaxLen-menuTitleLen) + s := make([]rune, 0, itemMaxLen-menuTitleLen) for j := i; j < i+itemMaxLen-menuTitleLen; j++ { s = append(s, r[j%len(r)]) } @@ -590,8 +590,14 @@ func (m *Main) keyMsgHandle(msg tea.KeyMsg, a *App) (Page, tea.Cmd) { case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9": num, _ := strconv.Atoi(key) start := (m.menuCurPage - 1) * m.menuPageSize - if start+num < len(m.menuList) { - m.selectedIndex = start + num + if start+num >= len(m.menuList) { + break + } + target := start + num + if m.selectedIndex == target { + newPage = m.EnterMenu(nil, nil) + } else { + m.selectedIndex = target } case "g": newPage = m.MoveTop() @@ -603,7 +609,7 @@ func (m *Main) keyMsgHandle(msg tea.KeyMsg, a *App) (Page, tea.Cmd) { newPage = m.BackMenu() case "r", "R": return m, a.RerenderCmd(true) - case "/", "/": + case "/", "/", "、": if m.menu.IsSearchable() { m.inSearching = true m.searchInput.Focus() @@ -640,7 +646,7 @@ func (m *Main) mouseMsgHandle(msg tea.MouseMsg, a *App) (Page, tea.Cmd) { func (m *Main) searchMenuHandle() { m.inSearching = false - var searchMenu = m.options.LocalSearchMenu + searchMenu := m.options.LocalSearchMenu if m.options.LocalSearchMenu == nil { searchMenu = DefaultSearchMenu() } diff --git a/vendor/github.com/anhoder/foxful-cli/model/options.go b/vendor/github.com/anhoder/foxful-cli/model/options.go index 4d63fc5..ed1433c 100644 --- a/vendor/github.com/anhoder/foxful-cli/model/options.go +++ b/vendor/github.com/anhoder/foxful-cli/model/options.go @@ -27,8 +27,9 @@ type Options struct { LocalSearchMenu LocalSearchMenu // Local search result menu Components []Component // Custom Extra components - KBControllers []KeyboardController - MouseControllers []MouseController + GlobalKeyHandlers map[string]GlobalKeyHandler + KBControllers []KeyboardController + MouseControllers []MouseController InitHook func(a *App) CloseHook func(a *App) @@ -52,12 +53,14 @@ func DefaultOptions() *Options { Welcome: util.PkgName, }, ProgressOptions: ProgressOptions{ - FirstEmptyChar: '.', - EmptyChar: '.', - LastEmptyChar: '.', - FirstFullChar: '#', - FullChar: '#', - LastFullChar: '#', + EmptyCharWhenFirst: '.', + EmptyChar: '.', + EmptyCharWhenLast: '.', + FirstEmptyChar: '.', + FullCharWhenFirst: '#', + FullChar: '#', + FullCharWhenLast: '#', + LastFullChar: '#', }, WhetherDisplayTitle: true, DualColumn: true, @@ -67,3 +70,26 @@ func DefaultOptions() *Options { MainMenu: &DefaultMenu{}, } } + +type WithOption func(options *Options) + +func WithHook(init, close func(a *App)) WithOption { + return func(opts *Options) { + opts.InitHook = init + opts.CloseHook = close + } +} + +func WithMainMenu(mainMenu Menu, mainMenuTitle *MenuItem) WithOption { + return func(opts *Options) { + opts.MainMenu = mainMenu + opts.MainMenuTitle = mainMenuTitle + } +} + +func WithGlobalKeyHandlers(m map[string]GlobalKeyHandler) WithOption { + return func(options *Options) { + options.GlobalKeyHandlers = m + } +} + diff --git a/vendor/github.com/anhoder/foxful-cli/model/progress.go b/vendor/github.com/anhoder/foxful-cli/model/progress.go index 3448d2d..b5e1baf 100644 --- a/vendor/github.com/anhoder/foxful-cli/model/progress.go +++ b/vendor/github.com/anhoder/foxful-cli/model/progress.go @@ -8,20 +8,24 @@ import ( ) type ProgressOptions struct { - FirstEmptyChar rune - EmptyChar rune - LastEmptyChar rune - FirstFullChar rune - FullChar rune - LastFullChar rune + EmptyCharWhenFirst rune + EmptyChar rune + EmptyCharWhenLast rune + FirstEmptyChar rune + FullCharWhenFirst rune + FullChar rune + FullCharWhenLast rune + LastFullChar rune } func Progress(options *ProgressOptions, width, fullSize int, progressRamp []string) string { var fullCells strings.Builder for i := 0; i < fullSize && i < len(progressRamp); i++ { if i == 0 { - fullCells.WriteString(termenv.String(string(options.FirstFullChar)).Foreground(util.TermProfile.Color(progressRamp[i])).String()) + fullCells.WriteString(termenv.String(string(options.FullCharWhenFirst)).Foreground(util.TermProfile.Color(progressRamp[i])).String()) } else if i >= width-1 { + fullCells.WriteString(termenv.String(string(options.FullCharWhenLast)).Foreground(util.TermProfile.Color(progressRamp[i])).String()) + } else if i == fullSize-1 { fullCells.WriteString(termenv.String(string(options.LastFullChar)).Foreground(util.TermProfile.Color(progressRamp[i])).String()) } else { fullCells.WriteString(termenv.String(string(options.FullChar)).Foreground(util.TermProfile.Color(progressRamp[i])).String()) @@ -34,15 +38,18 @@ func Progress(options *ProgressOptions, width, fullSize int, progressRamp []stri ) if emptySize > 0 { if fullSize == 0 { - emptyCells.WriteRune(options.FirstEmptyChar) + emptyCells.WriteRune(options.EmptyCharWhenFirst) emptySize-- } emptySize-- if emptySize > 0 { - emptyCells.WriteString(strings.Repeat(string(options.EmptyChar), emptySize)) + emptyCells.WriteString(string(options.FirstEmptyChar)) + if emptySize > 1 { + emptyCells.WriteString(strings.Repeat(string(options.EmptyChar), emptySize-1)) + } } if fullSize < width { - emptyCells.WriteRune(options.LastEmptyChar) + emptyCells.WriteRune(options.EmptyCharWhenLast) } } return fullCells.String() + util.SetFgStyle(emptyCells.String(), termenv.ANSIBrightBlack) diff --git a/vendor/github.com/charmbracelet/bubbletea/README.md b/vendor/github.com/charmbracelet/bubbletea/README.md index 395b65c..b61b94d 100644 --- a/vendor/github.com/charmbracelet/bubbletea/README.md +++ b/vendor/github.com/charmbracelet/bubbletea/README.md @@ -1,10 +1,11 @@ # Bubble Tea

- Bubble Tea Title Treatment
+ Bubble Tea Title Treatment
Latest Release GoDoc Build Status + phorm.ai

The fun, functional and stateful way to build terminal apps. A Go framework @@ -266,15 +267,21 @@ delve in headless mode and then connect to it: ```bash # Start the debugger -$ dlv debug --headless . -API server listening at: 127.0.0.1:34241 +$ dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 . +API server listening at: 127.0.0.1:43000 # Connect to it from another terminal -$ dlv connect 127.0.0.1:34241 +$ dlv connect 127.0.0.1:43000 ``` -Note that the default port used will vary on your system and per run, so -actually watch out what address the first `dlv` run tells you to connect to. +If you do not explicitly supply the `--listen` flag, the port used will vary +per run, so passing this in makes the debugger easier to use from a script +or your IDE of choice. + +Additionally, we pass in `--api-version=2` because delve defaults to version 1 +for backwards compatibility reasons. However, delve recommends using version 2 +for all new development and some clients may no longer work with version 1. +For more information, see the [Delve documentation](https://github.com/go-delve/delve/tree/master/Documentation/api). ### Logging Stuff @@ -316,60 +323,91 @@ your program in another window. For some Bubble Tea programs in production, see: +* [ASCII Movie](https://github.com/gabe565/ascii-movie): a Star Wars ASCII art movie player * [AT CLI](https://github.com/daskycodes/at_cli): execute AT Commands via serial port connections * [Aztify](https://github.com/Azure/aztfy): bring Microsoft Azure resources under Terraform * [brows](https://github.com/rubysolo/brows): a GitHub release browser * [Canard](https://github.com/mrusme/canard): an RSS client * [charm](https://github.com/charmbracelet/charm): the official Charm user account manager +* [chatgpt-cli](https://github.com/j178/chatgpt): a CLI for ChatGPT +* [chatgpt-tui](https://github.com/tearingItUp786/chatgpt-tui): a TUI for ChatGPT with SQLite sessions +* [ChatGPTUI](https://github.com/dwisiswant0/chatgptui): a TUI for ChatGPT * [chezmoi](https://github.com/twpayne/chezmoi): securely manage your dotfiles across multiple machines -* [chtop](https://github.com/chhetripradeep/chtop): monitor your ClickHouse node without leaving terminal +* [chip-8](https://github.com/braheezy/chip-8): a CHIP-8 interpreter +* [chtop](https://github.com/chhetripradeep/chtop): monitor your ClickHouse node without leaving the terminal * [circumflex](https://github.com/bensadeh/circumflex): read Hacker News in the terminal * [clidle](https://github.com/ajeetdsouza/clidle): a Wordle clone * [cLive](https://github.com/koki-develop/clive): automate terminal operations and view them live in a browser * [container-canary](https://github.com/NVIDIA/container-canary): a container validator * [countdown](https://github.com/aldernero/countdown): a multi-event countdown timer -* [dns53](https://github.com/purpleclay/dns53): dynamic DNS with Amazon Route53. Expose your EC2 quickly, securely and privately -* [eks-node-viewer](https://github.com/awslabs/eks-node-viewer): a tool for visualizing dynamic node usage within an eks cluster -* [enola](https://github.com/sherlock-project/enola): hunt down social media accounts by username across social networks +* [CRT](https://github.com/BigJk/crt): a simple terminal emulator for running Bubble Tea in a dedicated window, with optional shaders +* [cueitup](https://github.com/dhth/cueitup): inspect messages in an AWS SQS queue in a simple and deliberate manner +* [Daytona](https://github.com/daytonaio/daytona): an development environment manager +* [dns53](https://github.com/purpleclay/dns53): dynamic DNS with Amazon Route53; expose your EC2 quickly, securely and privately +* [eks-node-viewer](https://github.com/awslabs/eks-node-viewer): a tool for visualizing dynamic node usage within an EKS cluster +* [End Of Eden](https://github.com/BigJk/end_of_eden): a "Slay the Spire"-like, roguelike deck-builder game +* [enola](https://github.com/sherlock-project/enola): find social media accounts by username across social networks * [flapioca](https://github.com/kbrgl/flapioca): Flappy Bird on the CLI! * [fm](https://github.com/knipferrc/fm): a terminal-based file manager * [fork-cleaner](https://github.com/caarlos0/fork-cleaner): clean up old and inactive forks in your GitHub account +* [fractals-cli](https://github.com/MicheleFiladelfia/fractals-cli): a multiplatform terminal fractal explorer * [fztea](https://github.com/jon4hz/fztea): a Flipper Zero TUI +* [gama](https://github.com/termkit/gama): manage GitHub Actions from the terminal * [gambit](https://github.com/maaslalani/gambit): chess in the terminal * [gembro](https://git.sr.ht/~rafael/gembro): a mouse-driven Gemini browser * [gh-b](https://github.com/joaom00/gh-b): a GitHub CLI extension for managing branches * [gh-dash](https://www.github.com/dlvhdr/gh-dash): a GitHub CLI extension for PRs and issues * [gitflow-toolkit](https://github.com/mritd/gitflow-toolkit): a GitFlow submission tool * [Glow](https://github.com/charmbracelet/glow): a markdown reader, browser, and online markdown stash +* [go-sweep](https://github.com/maxpaulus43/go-sweep): Minesweeper in the terminal * [gocovsh](https://github.com/orlangure/gocovsh): explore Go coverage reports from the CLI -* [got](https://github.com/fedeztk/got): a simple translator and text-to-speech app build on top of simplytranslate's APIs +* [got](https://github.com/fedeztk/got): a simple translator and text-to-speech app built on simplytranslate's APIs +* [gum](https://github.com/charmbracelet/gum): interactivity and styling for shells and shell scripts +* [hiSHtory](https://github.com/ddworken/hishtory): your shell history in context: synced, and queryable * [httpit](https://github.com/gonetx/httpit): a rapid http(s) benchmark tool +* [Huh?](https://github.com/charmbracelet/huh): an interactive prompt and form toolkit * [IDNT](https://github.com/r-darwish/idnt): a batch software uninstaller +* [json-log-viewer](https://github.com/hedhyw/json-log-viewer): an interactive JSON log viewer * [kboard](https://github.com/CamiloGarciaLaRotta/kboard): a typing game -* [mandelbrot-cli](https://github.com/MicheleFiladelfia/mandelbrot-cli): a multiplatform terminal mandelbrot set explorer +* [kplay](https://github.com/dhth/kplay): inspect messages in a Kafka topic +* [laboon](https://github.com/arisnacg/laboon): a Docker-desktop-style container manager * [mc](https://github.com/minio/mc): the official [MinIO](https://min.io) client * [mergestat](https://github.com/mergestat/mergestat): run SQL queries on git repositories +* [meteor](https://github.com/stefanlogue/meteor): a highly customizable conventional commit message tool +* [mods](https://github.com/charmbracelet/mods): AI on the CLI, built for pipelines +* [nachrichten](https://github.com/zMoooooritz/nachrichten): access up-to-date news in German provided by the [Tagesschau](https://www.tagesschau.de/) * [Neon Modem Overdrive](https://github.com/mrusme/neonmodem): a BBS-style TUI client for Discourse, Lemmy, Lobste.rs and Hacker News +* [nom](https://github.com/guyfedwards/nom): an RSS reader and manager * [Noted](https://github.com/torbratsberg/noted): a note viewer and manager -* [pathos](https://github.com/chip/pathos): a PATH env variable editor +* [outtasync](https://github.com/dhth/outtasync): identify CloudFormation stacks that are out of sync with their template files +* [pathos](https://github.com/chip/pathos): a PATH environment variable editor * [portal](https://github.com/ZinoKader/portal): secure transfers between computers -* [redis-viewer](https://github.com/SaltFishPr/redis-viewer): a Redis databases browser +* [puffin](https://github.com/siddhantac/puffin): a TUI for hledger to manage your finances +* [punchout](https://github.com/dhth/punchout): takes the suck out of logging time on JIRA +* [redis-viewer](https://github.com/SaltFishPr/redis-viewer): a Redis database browser +* [redis_tui](https://github.com/mat2cc/redis_tui): a Redis database browser +* [schemas](https://github.com/dhth/schemas): lets you inspect postgres schemas in the terminal +* [scrabbler](https://github.com/wI2L/scrabbler): an automatic draw tool for your duplicate Scrabble games * [sku](https://github.com/fedeztk/sku): Sudoku on the CLI * [Slides](https://github.com/maaslalani/slides): a markdown-based presentation tool * [SlurmCommander](https://github.com/CLIP-HPC/SlurmCommander): a Slurm workload manager TUI * [Soft Serve](https://github.com/charmbracelet/soft-serve): a command-line-first Git server that runs a TUI over SSH * [solitaire-tui](https://github.com/brianstrauch/solitaire-tui): Klondike Solitaire for the terminal * [StormForge Optimize Controller](https://github.com/thestormforge/optimize-controller): a tool for experimenting with application configurations in Kubernetes +* [Storydb](https://github.com/grrlopes/storydb): an improved bash/zsh-style ctrl+r command history finder * [STTG](https://github.com/wille1101/sttg): a teletext client for SVT, Sweden’s national public television station * [sttr](https://github.com/abhimanyu003/sttr): a general-purpose text transformer * [tasktimer](https://github.com/caarlos0/tasktimer): a dead-simple task timer * [termdbms](https://github.com/mathaou/termdbms): a keyboard and mouse driven database browser * [ticker](https://github.com/achannarasappa/ticker): a terminal stock viewer and stock position tracker +* [trainer](https://github.com/rusinikita/trainer): a Go concurrency coding interview simulator with learning materials * [tran](https://github.com/abdfnx/tran): securely transfer stuff between computers (based on [portal](https://github.com/ZinoKader/portal)) +* [Trufflehog](https://github.com/trufflesecurity/trufflehog): find leaked credentials * [Typer](https://github.com/maaslalani/typer): a typing test -* [typioca](https://github.com/bloznelis/typioca): Cozy typing speed tester in terminal -* [tz](https://github.com/oz/tz): an aid for scheduling across multiple time zones +* [typioca](https://github.com/bloznelis/typioca): a typing test +* [tz](https://github.com/oz/tz): a scheduling aid for people in multiple time zones * [ugm](https://github.com/ariasmn/ugm): a unix user and group browser +* [walk](https://github.com/antonmedv/walk): a terminal navigator * [wander](https://github.com/robinovitch61/wander): a HashiCorp Nomad terminal client * [WG Commander](https://github.com/AndrianBdn/wg-cmd): a TUI for a simple WireGuard VPN setup * [wishlist](https://github.com/charmbracelet/wishlist): an SSH directory diff --git a/vendor/github.com/charmbracelet/bubbletea/commands.go b/vendor/github.com/charmbracelet/bubbletea/commands.go index 7c30a12..164dad2 100644 --- a/vendor/github.com/charmbracelet/bubbletea/commands.go +++ b/vendor/github.com/charmbracelet/bubbletea/commands.go @@ -13,18 +13,22 @@ import ( // return tea.Batch(someCommand, someOtherCommand) // } func Batch(cmds ...Cmd) Cmd { - var validCmds []Cmd + var validCmds []Cmd //nolint:prealloc for _, c := range cmds { if c == nil { continue } validCmds = append(validCmds, c) } - if len(validCmds) == 0 { + switch len(validCmds) { + case 0: return nil - } - return func() Msg { - return BatchMsg(validCmds) + case 1: + return validCmds[0] + default: + return func() Msg { + return BatchMsg(validCmds) + } } } @@ -170,3 +174,20 @@ func Sequentially(cmds ...Cmd) Cmd { return nil } } + +// setWindowTitleMsg is an internal message used to set the window title. +type setWindowTitleMsg string + +// SetWindowTitle produces a command that sets the terminal title. +// +// For example: +// +// func (m model) Init() Cmd { +// // Set title. +// return tea.SetWindowTitle("My App") +// } +func SetWindowTitle(title string) Cmd { + return func() Msg { + return setWindowTitleMsg(title) + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go b/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go new file mode 100644 index 0000000..8e63a87 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go @@ -0,0 +1,14 @@ +//go:build !windows +// +build !windows + +package tea + +import ( + "io" + + "github.com/muesli/cancelreader" +) + +func newInputReader(r io.Reader) (cancelreader.CancelReader, error) { + return cancelreader.NewReader(r) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go b/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go new file mode 100644 index 0000000..5969721 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go @@ -0,0 +1,153 @@ +//go:build windows +// +build windows + +package tea + +import ( + "fmt" + "io" + "os" + "sync" + + "github.com/erikgeiser/coninput" + "github.com/muesli/cancelreader" + "golang.org/x/sys/windows" +) + +type conInputReader struct { + cancelMixin + + conin windows.Handle + cancelEvent windows.Handle + + originalMode uint32 + + // inputEvent holds the input event that was read in order to avoid + // unnecessary allocations. This re-use is possible because + // InputRecord.Unwarp which is called inparseInputMsgFromInputRecord + // returns an data structure that is independent of the passed InputRecord. + inputEvent []coninput.InputRecord +} + +var _ cancelreader.CancelReader = &conInputReader{} + +func newInputReader(r io.Reader) (cancelreader.CancelReader, error) { + fallback := func(io.Reader) (cancelreader.CancelReader, error) { + return cancelreader.NewReader(r) + } + if f, ok := r.(*os.File); !ok || f.Fd() != os.Stdin.Fd() { + return fallback(r) + } + + conin, err := coninput.NewStdinHandle() + if err != nil { + return fallback(r) + } + + originalMode, err := prepareConsole(conin, + windows.ENABLE_MOUSE_INPUT, + windows.ENABLE_WINDOW_INPUT, + windows.ENABLE_EXTENDED_FLAGS, + ) + if err != nil { + return nil, fmt.Errorf("failed to prepare console input: %w", err) + } + + cancelEvent, err := windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + return nil, fmt.Errorf("create stop event: %w", err) + } + + return &conInputReader{ + conin: conin, + cancelEvent: cancelEvent, + originalMode: originalMode, + }, nil +} + +// Cancel implements cancelreader.CancelReader. +func (r *conInputReader) Cancel() bool { + r.setCanceled() + + err := windows.SetEvent(r.cancelEvent) + if err != nil { + return false + } + + return true +} + +// Close implements cancelreader.CancelReader. +func (r *conInputReader) Close() error { + err := windows.CloseHandle(r.cancelEvent) + if err != nil { + return fmt.Errorf("closing cancel event handle: %w", err) + } + + if r.originalMode != 0 { + err := windows.SetConsoleMode(r.conin, r.originalMode) + if err != nil { + return fmt.Errorf("reset console mode: %w", err) + } + } + + return nil +} + +// Read implements cancelreader.CancelReader. +func (*conInputReader) Read(_ []byte) (n int, err error) { + return 0, nil +} + +func prepareConsole(input windows.Handle, modes ...uint32) (originalMode uint32, err error) { + err = windows.GetConsoleMode(input, &originalMode) + if err != nil { + return 0, fmt.Errorf("get console mode: %w", err) + } + + newMode := coninput.AddInputModes(0, modes...) + + err = windows.SetConsoleMode(input, newMode) + if err != nil { + return 0, fmt.Errorf("set console mode: %w", err) + } + + return originalMode, nil +} + +func waitForInput(conin, cancel windows.Handle) error { + event, err := windows.WaitForMultipleObjects([]windows.Handle{conin, cancel}, false, windows.INFINITE) + switch { + case windows.WAIT_OBJECT_0 <= event && event < windows.WAIT_OBJECT_0+2: + if event == windows.WAIT_OBJECT_0+1 { + return cancelreader.ErrCanceled + } + + if event == windows.WAIT_OBJECT_0 { + return nil + } + + return fmt.Errorf("unexpected wait object is ready: %d", event-windows.WAIT_OBJECT_0) + case windows.WAIT_ABANDONED <= event && event < windows.WAIT_ABANDONED+2: + return fmt.Errorf("abandoned") + case event == uint32(windows.WAIT_TIMEOUT): + return fmt.Errorf("timeout") + case event == windows.WAIT_FAILED: + return fmt.Errorf("failed") + default: + return fmt.Errorf("unexpected error: %w", err) + } +} + +// cancelMixin represents a goroutine-safe cancelation status. +type cancelMixin struct { + unsafeCanceled bool + lock sync.Mutex +} + +func (c *cancelMixin) setCanceled() { + c.lock.Lock() + defer c.lock.Unlock() + + c.unsafeCanceled = true +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key.go b/vendor/github.com/charmbracelet/bubbletea/key.go index 74f85ec..aac07d0 100644 --- a/vendor/github.com/charmbracelet/bubbletea/key.go +++ b/vendor/github.com/charmbracelet/bubbletea/key.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "regexp" + "strings" "unicode/utf8" ) @@ -54,6 +55,7 @@ type Key struct { Type KeyType Runes []rune Alt bool + Paste bool } // String returns a friendly string representation for a key. It's safe (and @@ -63,15 +65,28 @@ type Key struct { // fmt.Println(k) // // Output: enter func (k Key) String() (str string) { + var buf strings.Builder if k.Alt { - str += "alt+" + buf.WriteString("alt+") } if k.Type == KeyRunes { - str += string(k.Runes) - return str + if k.Paste { + // Note: bubbles/keys bindings currently do string compares to + // recognize shortcuts. Since pasted text should never activate + // shortcuts, we need to ensure that the binding code doesn't + // match Key events that result from pastes. We achieve this + // here by enclosing pastes in '[...]' so that the string + // comparison in Matches() fails in that case. + buf.WriteByte('[') + } + buf.WriteString(string(k.Runes)) + if k.Paste { + buf.WriteByte(']') + } + return buf.String() } else if s, ok := keyNames[k.Type]; ok { - str += s - return str + buf.WriteString(s) + return buf.String() } return "" } @@ -538,38 +553,86 @@ func (u unknownCSISequenceMsg) String() string { var spaceRunes = []rune{' '} -// readInputs reads keypress and mouse inputs from a TTY and produces messages +// readAnsiInputs reads keypress and mouse inputs from a TTY and produces messages // containing information about the key or mouse events accordingly. -func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { +func readAnsiInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { var buf [256]byte + var leftOverFromPrevIteration []byte +loop: for { // Read and block. numBytes, err := input.Read(buf[:]) if err != nil { - return err + return fmt.Errorf("error reading input: %w", err) } b := buf[:numBytes] + if leftOverFromPrevIteration != nil { + b = append(leftOverFromPrevIteration, b...) + } + + // If we had a short read (numBytes < len(buf)), we're sure that + // the end of this read is an event boundary, so there is no doubt + // if we are encountering the end of the buffer while parsing a message. + // However, if we've succeeded in filling up the buffer, there may + // be more data in the OS buffer ready to be read in, to complete + // the last message in the input. In that case, we will retry with + // the left over data in the next iteration. + canHaveMoreData := numBytes == len(buf) var i, w int for i, w = 0, 0; i < len(b); i += w { var msg Msg - w, msg = detectOneMsg(b[i:]) + w, msg = detectOneMsg(b[i:], canHaveMoreData) + if w == 0 { + // Expecting more bytes beyond the current buffer. Try waiting + // for more input. + leftOverFromPrevIteration = make([]byte, 0, len(b[i:])+len(buf)) + leftOverFromPrevIteration = append(leftOverFromPrevIteration, b[i:]...) + continue loop + } + select { case msgs <- msg: case <-ctx.Done(): - return ctx.Err() + err := ctx.Err() + if err != nil { + err = fmt.Errorf("found context error while reading input: %w", err) + } + return err } } + leftOverFromPrevIteration = nil } } -var unknownCSIRe = regexp.MustCompile(`^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]`) +var ( + unknownCSIRe = regexp.MustCompile(`^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]`) + mouseSGRRegex = regexp.MustCompile(`(\d+);(\d+);(\d+)([Mm])`) +) -func detectOneMsg(b []byte) (w int, msg Msg) { +func detectOneMsg(b []byte, canHaveMoreData bool) (w int, msg Msg) { // Detect mouse events. - if len(b) >= 6 && b[0] == '\x1b' && b[1] == '[' && b[2] == 'M' { - return 6, MouseMsg(parseX10MouseEvent(b)) + // X10 mouse events have a length of 6 bytes + const mouseEventX10Len = 6 + if len(b) >= mouseEventX10Len && b[0] == '\x1b' && b[1] == '[' { + switch b[2] { + case 'M': + return mouseEventX10Len, MouseMsg(parseX10MouseEvent(b)) + case '<': + if matchIndices := mouseSGRRegex.FindSubmatchIndex(b[3:]); matchIndices != nil { + // SGR mouse events length is the length of the match plus the length of the escape sequence + mouseEventSGRLen := matchIndices[1] + 3 + return mouseEventSGRLen, MouseMsg(parseSGRMouseEvent(b)) + } + } + } + + // Detect bracketed paste. + var foundbp bool + foundbp, w, msg = detectBracketedPaste(b) + if foundbp { + return } // Detect escape sequence and control characters other than NUL, @@ -613,6 +676,15 @@ func detectOneMsg(b []byte) (w int, msg Msg) { break } } + if i >= len(b) && canHaveMoreData { + // We have encountered the end of the input buffer. Alas, we can't + // be sure whether the data in the remainder of the buffer is + // complete (maybe there was a short read). Instead of sending anything + // dumb to the message channel, do a short read. The outer loop will + // handle this case by extending the buffer as necessary. + return 0, nil + } + // If we found at least one rune, we report the bunch of them as // a single KeyRunes or KeySpace event. if len(runes) > 0 { diff --git a/vendor/github.com/charmbracelet/bubbletea/key_other.go b/vendor/github.com/charmbracelet/bubbletea/key_other.go new file mode 100644 index 0000000..b8c4608 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/key_other.go @@ -0,0 +1,13 @@ +//go:build !windows +// +build !windows + +package tea + +import ( + "context" + "io" +) + +func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { + return readAnsiInputs(ctx, msgs, input) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_sequences.go b/vendor/github.com/charmbracelet/bubbletea/key_sequences.go index cc200f8..4ba0f79 100644 --- a/vendor/github.com/charmbracelet/bubbletea/key_sequences.go +++ b/vendor/github.com/charmbracelet/bubbletea/key_sequences.go @@ -1,6 +1,10 @@ package tea -import "sort" +import ( + "bytes" + "sort" + "unicode/utf8" +) // extSequences is used by the map-based algorithm below. It contains // the sequences plus their alternatives with an escape character @@ -69,3 +73,47 @@ func detectSequence(input []byte) (hasSeq bool, width int, msg Msg) { return false, 0, nil } + +// detectBracketedPaste detects an input pasted while bracketed +// paste mode was enabled. +// +// Note: this function is a no-op if bracketed paste was not enabled +// on the terminal, since in that case we'd never see this +// particular escape sequence. +func detectBracketedPaste(input []byte) (hasBp bool, width int, msg Msg) { + // Detect the start sequence. + const bpStart = "\x1b[200~" + if len(input) < len(bpStart) || string(input[:len(bpStart)]) != bpStart { + return false, 0, nil + } + + // Skip over the start sequence. + input = input[len(bpStart):] + + // If we saw the start sequence, then we must have an end sequence + // as well. Find it. + const bpEnd = "\x1b[201~" + idx := bytes.Index(input, []byte(bpEnd)) + inputLen := len(bpStart) + idx + len(bpEnd) + if idx == -1 { + // We have encountered the end of the input buffer without seeing + // the marker for the end of the bracketed paste. + // Tell the outer loop we have done a short read and we want more. + return true, 0, nil + } + + // The paste is everything in-between. + paste := input[:idx] + + // All there is in-between is runes, not to be interpreted further. + k := Key{Type: KeyRunes, Paste: true} + for len(paste) > 0 { + r, w := utf8.DecodeRune(paste) + if r != utf8.RuneError { + k.Runes = append(k.Runes, r) + } + paste = paste[w:] + } + + return true, inputLen, KeyMsg(k) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_windows.go b/vendor/github.com/charmbracelet/bubbletea/key_windows.go new file mode 100644 index 0000000..c4b8aa7 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/key_windows.go @@ -0,0 +1,277 @@ +//go:build windows +// +build windows + +package tea + +import ( + "context" + "fmt" + "io" + + "github.com/erikgeiser/coninput" + localereader "github.com/mattn/go-localereader" + "golang.org/x/sys/windows" +) + +func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { + if coninReader, ok := input.(*conInputReader); ok { + return readConInputs(ctx, msgs, coninReader.conin) + } + + return readAnsiInputs(ctx, msgs, localereader.NewReader(input)) +} + +func readConInputs(ctx context.Context, msgsch chan<- Msg, con windows.Handle) error { + var ps coninput.ButtonState // keep track of previous mouse state + for { + events, err := coninput.ReadNConsoleInputs(con, 16) + if err != nil { + return fmt.Errorf("read coninput events: %w", err) + } + + for _, event := range events { + var msgs []Msg + switch e := event.Unwrap().(type) { + case coninput.KeyEventRecord: + if !e.KeyDown || e.VirtualKeyCode == coninput.VK_SHIFT { + continue + } + + for i := 0; i < int(e.RepeatCount); i++ { + msgs = append(msgs, KeyMsg{ + Type: keyType(e), + Runes: []rune{e.Char}, + Alt: e.ControlKeyState.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED), + }) + } + case coninput.WindowBufferSizeEventRecord: + msgs = append(msgs, WindowSizeMsg{ + Width: int(e.Size.X), + Height: int(e.Size.Y), + }) + case coninput.MouseEventRecord: + event := mouseEvent(ps, e) + if event.Type != MouseUnknown { + msgs = append(msgs, event) + } + ps = e.ButtonState + case coninput.FocusEventRecord, coninput.MenuEventRecord: + // ignore + default: // unknown event + continue + } + + // Send all messages to the channel + for _, msg := range msgs { + select { + case msgsch <- msg: + case <-ctx.Done(): + err := ctx.Err() + if err != nil { + return fmt.Errorf("coninput context error: %w", err) + } + return err + } + } + } + } +} + +func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action MouseAction) { + btn := p ^ s + action = MouseActionPress + if btn&s == 0 { + action = MouseActionRelease + } + + if btn == 0 { + switch { + case s&coninput.FROM_LEFT_1ST_BUTTON_PRESSED > 0: + button = MouseButtonLeft + case s&coninput.FROM_LEFT_2ND_BUTTON_PRESSED > 0: + button = MouseButtonMiddle + case s&coninput.RIGHTMOST_BUTTON_PRESSED > 0: + button = MouseButtonRight + case s&coninput.FROM_LEFT_3RD_BUTTON_PRESSED > 0: + button = MouseButtonBackward + case s&coninput.FROM_LEFT_4TH_BUTTON_PRESSED > 0: + button = MouseButtonForward + } + return + } + + switch { + case btn == coninput.FROM_LEFT_1ST_BUTTON_PRESSED: // left button + button = MouseButtonLeft + case btn == coninput.RIGHTMOST_BUTTON_PRESSED: // right button + button = MouseButtonRight + case btn == coninput.FROM_LEFT_2ND_BUTTON_PRESSED: // middle button + button = MouseButtonMiddle + case btn == coninput.FROM_LEFT_3RD_BUTTON_PRESSED: // unknown (possibly mouse backward) + button = MouseButtonBackward + case btn == coninput.FROM_LEFT_4TH_BUTTON_PRESSED: // unknown (possibly mouse forward) + button = MouseButtonForward + } + + return button, action +} + +func mouseEvent(p coninput.ButtonState, e coninput.MouseEventRecord) MouseMsg { + ev := MouseMsg{ + X: int(e.MousePositon.X), + Y: int(e.MousePositon.Y), + Alt: e.ControlKeyState.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED), + Ctrl: e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED), + Shift: e.ControlKeyState.Contains(coninput.SHIFT_PRESSED), + } + switch e.EventFlags { + case coninput.CLICK, coninput.DOUBLE_CLICK: + ev.Button, ev.Action = mouseEventButton(p, e.ButtonState) + if ev.Action == MouseActionRelease { + ev.Type = MouseRelease + } + switch ev.Button { + case MouseButtonLeft: + ev.Type = MouseLeft + case MouseButtonMiddle: + ev.Type = MouseMiddle + case MouseButtonRight: + ev.Type = MouseRight + case MouseButtonBackward: + ev.Type = MouseBackward + case MouseButtonForward: + ev.Type = MouseForward + } + case coninput.MOUSE_WHEELED: + if e.WheelDirection > 0 { + ev.Button = MouseButtonWheelUp + ev.Type = MouseWheelUp + } else { + ev.Button = MouseButtonWheelDown + ev.Type = MouseWheelDown + } + case coninput.MOUSE_HWHEELED: + if e.WheelDirection > 0 { + ev.Button = MouseButtonWheelRight + ev.Type = MouseWheelRight + } else { + ev.Button = MouseButtonWheelLeft + ev.Type = MouseWheelLeft + } + case coninput.MOUSE_MOVED: + ev.Button, _ = mouseEventButton(p, e.ButtonState) + ev.Action = MouseActionMotion + ev.Type = MouseMotion + } + + return ev +} + +func keyType(e coninput.KeyEventRecord) KeyType { + code := e.VirtualKeyCode + + switch code { + case coninput.VK_RETURN: + return KeyEnter + case coninput.VK_BACK: + return KeyBackspace + case coninput.VK_TAB: + return KeyTab + case coninput.VK_SPACE: + return KeyRunes // this could be KeySpace but on unix space also produces KeyRunes + case coninput.VK_ESCAPE: + return KeyEscape + case coninput.VK_UP: + return KeyUp + case coninput.VK_DOWN: + return KeyDown + case coninput.VK_RIGHT: + return KeyRight + case coninput.VK_LEFT: + return KeyLeft + case coninput.VK_HOME: + return KeyHome + case coninput.VK_END: + return KeyEnd + case coninput.VK_PRIOR: + return KeyPgUp + case coninput.VK_NEXT: + return KeyPgDown + case coninput.VK_DELETE: + return KeyDelete + default: + if e.ControlKeyState&(coninput.LEFT_CTRL_PRESSED|coninput.RIGHT_CTRL_PRESSED) == 0 { + return KeyRunes + } + + switch e.Char { + case '@': + return KeyCtrlAt + case '\x01': + return KeyCtrlA + case '\x02': + return KeyCtrlB + case '\x03': + return KeyCtrlC + case '\x04': + return KeyCtrlD + case '\x05': + return KeyCtrlE + case '\x06': + return KeyCtrlF + case '\a': + return KeyCtrlG + case '\b': + return KeyCtrlH + case '\t': + return KeyCtrlI + case '\n': + return KeyCtrlJ + case '\v': + return KeyCtrlK + case '\f': + return KeyCtrlL + case '\r': + return KeyCtrlM + case '\x0e': + return KeyCtrlN + case '\x0f': + return KeyCtrlO + case '\x10': + return KeyCtrlP + case '\x11': + return KeyCtrlQ + case '\x12': + return KeyCtrlR + case '\x13': + return KeyCtrlS + case '\x14': + return KeyCtrlT + case '\x15': + return KeyCtrlU + case '\x16': + return KeyCtrlV + case '\x17': + return KeyCtrlW + case '\x18': + return KeyCtrlX + case '\x19': + return KeyCtrlY + case '\x1a': + return KeyCtrlZ + case '\x1b': + return KeyCtrlCloseBracket + case '\x1c': + return KeyCtrlBackslash + case '\x1f': + return KeyCtrlUnderscore + } + + switch code { + case coninput.VK_OEM_4: + return KeyCtrlOpenBracket + } + + return KeyRunes + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/logging.go b/vendor/github.com/charmbracelet/bubbletea/logging.go index 59258d4..a531181 100644 --- a/vendor/github.com/charmbracelet/bubbletea/logging.go +++ b/vendor/github.com/charmbracelet/bubbletea/logging.go @@ -1,6 +1,7 @@ package tea import ( + "fmt" "io" "log" "os" @@ -32,9 +33,9 @@ type LogOptionsSetter interface { // LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter. func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) { - f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644) + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:gomnd if err != nil { - return nil, err + return nil, fmt.Errorf("error opening file for logging: %w", err) } log.SetOutput(f) diff --git a/vendor/github.com/charmbracelet/bubbletea/mouse.go b/vendor/github.com/charmbracelet/bubbletea/mouse.go index fc66691..add8d02 100644 --- a/vendor/github.com/charmbracelet/bubbletea/mouse.go +++ b/vendor/github.com/charmbracelet/bubbletea/mouse.go @@ -1,5 +1,7 @@ package tea +import "strconv" + // MouseMsg contains information about a mouse event and are sent to a programs // update function when mouse activity occurs. Note that the mouse must first // be enabled in order for the mouse events to be received. @@ -13,11 +15,22 @@ func (m MouseMsg) String() string { // MouseEvent represents a mouse event, which could be a click, a scroll wheel // movement, a cursor movement, or a combination. type MouseEvent struct { - X int - Y int + X int + Y int + Shift bool + Alt bool + Ctrl bool + Action MouseAction + Button MouseButton + + // Deprecated: Use MouseAction & MouseButton instead. Type MouseEventType - Alt bool - Ctrl bool +} + +// IsWheel returns true if the mouse event is a wheel event. +func (m MouseEvent) IsWheel() bool { + return m.Button == MouseButtonWheelUp || m.Button == MouseButtonWheelDown || + m.Button == MouseButtonWheelLeft || m.Button == MouseButtonWheelRight } // String returns a string representation of a mouse event. @@ -28,38 +41,170 @@ func (m MouseEvent) String() (s string) { if m.Alt { s += "alt+" } - s += mouseEventTypes[m.Type] + if m.Shift { + s += "shift+" + } + + if m.Button == MouseButtonNone { + if m.Action == MouseActionMotion || m.Action == MouseActionRelease { + s += mouseActions[m.Action] + } else { + s += "unknown" + } + } else if m.IsWheel() { + s += mouseButtons[m.Button] + } else { + btn := mouseButtons[m.Button] + if btn != "" { + s += btn + } + act := mouseActions[m.Action] + if act != "" { + s += " " + act + } + } + return s } +// MouseAction represents the action that occurred during a mouse event. +type MouseAction int + +// Mouse event actions. +const ( + MouseActionPress MouseAction = iota + MouseActionRelease + MouseActionMotion +) + +var mouseActions = map[MouseAction]string{ + MouseActionPress: "press", + MouseActionRelease: "release", + MouseActionMotion: "motion", +} + +// MouseButton represents the button that was pressed during a mouse event. +type MouseButton int + +// Mouse event buttons +// +// This is based on X11 mouse button codes. +// +// 1 = left button +// 2 = middle button (pressing the scroll wheel) +// 3 = right button +// 4 = turn scroll wheel up +// 5 = turn scroll wheel down +// 6 = push scroll wheel left +// 7 = push scroll wheel right +// 8 = 4th button (aka browser backward button) +// 9 = 5th button (aka browser forward button) +// 10 +// 11 +// +// Other buttons are not supported. +const ( + MouseButtonNone MouseButton = iota + MouseButtonLeft + MouseButtonMiddle + MouseButtonRight + MouseButtonWheelUp + MouseButtonWheelDown + MouseButtonWheelLeft + MouseButtonWheelRight + MouseButtonBackward + MouseButtonForward + MouseButton10 + MouseButton11 +) + +var mouseButtons = map[MouseButton]string{ + MouseButtonNone: "none", + MouseButtonLeft: "left", + MouseButtonMiddle: "middle", + MouseButtonRight: "right", + MouseButtonWheelUp: "wheel up", + MouseButtonWheelDown: "wheel down", + MouseButtonWheelLeft: "wheel left", + MouseButtonWheelRight: "wheel right", + MouseButtonBackward: "backward", + MouseButtonForward: "forward", + MouseButton10: "button 10", + MouseButton11: "button 11", +} + // MouseEventType indicates the type of mouse event occurring. +// +// Deprecated: Use MouseAction & MouseButton instead. type MouseEventType int // Mouse event types. +// +// Deprecated: Use MouseAction & MouseButton instead. const ( MouseUnknown MouseEventType = iota MouseLeft MouseRight MouseMiddle - MouseRelease + MouseRelease // mouse button release (X10 only) MouseWheelUp MouseWheelDown + MouseWheelLeft + MouseWheelRight + MouseBackward + MouseForward MouseMotion ) -var mouseEventTypes = map[MouseEventType]string{ - MouseUnknown: "unknown", - MouseLeft: "left", - MouseRight: "right", - MouseMiddle: "middle", - MouseRelease: "release", - MouseWheelUp: "wheel up", - MouseWheelDown: "wheel down", - MouseMotion: "motion", +// Parse SGR-encoded mouse events; SGR extended mouse events. SGR mouse events +// look like: +// +// ESC [ < Cb ; Cx ; Cy (M or m) +// +// where: +// +// Cb is the encoded button code +// Cx is the x-coordinate of the mouse +// Cy is the y-coordinate of the mouse +// M is for button press, m is for button release +// +// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Extended-coordinates +func parseSGRMouseEvent(buf []byte) MouseEvent { + str := string(buf[3:]) + matches := mouseSGRRegex.FindStringSubmatch(str) + if len(matches) != 5 { + // Unreachable, we already checked the regex in `detectOneMsg`. + panic("invalid mouse event") + } + + b, _ := strconv.Atoi(matches[1]) + px := matches[2] + py := matches[3] + release := matches[4] == "m" + m := parseMouseButton(b, true) + + // Wheel buttons don't have release events + // Motion can be reported as a release event in some terminals (Windows Terminal) + if m.Action != MouseActionMotion && !m.IsWheel() && release { + m.Action = MouseActionRelease + m.Type = MouseRelease + } + + x, _ := strconv.Atoi(px) + y, _ := strconv.Atoi(py) + + // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). + m.X = x - 1 + m.Y = y - 1 + + return m } +const x10MouseByteOffset = 32 + // Parse X10-encoded mouse events; the simplest kind. The last release of X10 -// was December 1986, by the way. +// was December 1986, by the way. The original X10 mouse protocol limits the Cx +// and Cy coordinates to 223 (=255-032). // // X10 mouse events look like: // @@ -68,9 +213,22 @@ var mouseEventTypes = map[MouseEventType]string{ // See: http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking func parseX10MouseEvent(buf []byte) MouseEvent { v := buf[3:6] + m := parseMouseButton(int(v[0]), false) + + // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). + m.X = int(v[1]) - x10MouseByteOffset - 1 + m.Y = int(v[2]) - x10MouseByteOffset - 1 + + return m +} + +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Extended-coordinates +func parseMouseButton(b int, isSGR bool) MouseEvent { var m MouseEvent - const byteOffset = 32 - e := v[0] - byteOffset + e := b + if !isSGR { + e -= x10MouseByteOffset + } const ( bitShift = 0b0000_0100 @@ -78,55 +236,73 @@ func parseX10MouseEvent(buf []byte) MouseEvent { bitCtrl = 0b0001_0000 bitMotion = 0b0010_0000 bitWheel = 0b0100_0000 + bitAdd = 0b1000_0000 // additional buttons 8-11 bitsMask = 0b0000_0011 - - bitsLeft = 0b0000_0000 - bitsMiddle = 0b0000_0001 - bitsRight = 0b0000_0010 - bitsRelease = 0b0000_0011 - - bitsWheelUp = 0b0000_0000 - bitsWheelDown = 0b0000_0001 ) - if e&bitWheel != 0 { - // Check the low two bits. - switch e & bitsMask { - case bitsWheelUp: - m.Type = MouseWheelUp - case bitsWheelDown: - m.Type = MouseWheelDown - } + if e&bitAdd != 0 { + m.Button = MouseButtonBackward + MouseButton(e&bitsMask) + } else if e&bitWheel != 0 { + m.Button = MouseButtonWheelUp + MouseButton(e&bitsMask) } else { - // Check the low two bits. - // We do not separate clicking and dragging. - switch e & bitsMask { - case bitsLeft: - m.Type = MouseLeft - case bitsMiddle: - m.Type = MouseMiddle - case bitsRight: - m.Type = MouseRight - case bitsRelease: - if e&bitMotion != 0 { - m.Type = MouseMotion - } else { - m.Type = MouseRelease - } + m.Button = MouseButtonLeft + MouseButton(e&bitsMask) + // X10 reports a button release as 0b0000_0011 (3) + if e&bitsMask == bitsMask { + m.Action = MouseActionRelease + m.Button = MouseButtonNone } } - if e&bitAlt != 0 { - m.Alt = true - } - if e&bitCtrl != 0 { - m.Ctrl = true + // Motion bit doesn't get reported for wheel events. + if e&bitMotion != 0 && !m.IsWheel() { + m.Action = MouseActionMotion } - // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). - m.X = int(v[1]) - byteOffset - 1 - m.Y = int(v[2]) - byteOffset - 1 + // Modifiers + m.Alt = e&bitAlt != 0 + m.Ctrl = e&bitCtrl != 0 + m.Shift = e&bitShift != 0 + + // backward compatibility + switch { + case m.Button == MouseButtonLeft && m.Action == MouseActionPress: + m.Type = MouseLeft + case m.Button == MouseButtonMiddle && m.Action == MouseActionPress: + m.Type = MouseMiddle + case m.Button == MouseButtonRight && m.Action == MouseActionPress: + m.Type = MouseRight + case m.Button == MouseButtonNone && m.Action == MouseActionRelease: + m.Type = MouseRelease + case m.Button == MouseButtonWheelUp && m.Action == MouseActionPress: + m.Type = MouseWheelUp + case m.Button == MouseButtonWheelDown && m.Action == MouseActionPress: + m.Type = MouseWheelDown + case m.Button == MouseButtonWheelLeft && m.Action == MouseActionPress: + m.Type = MouseWheelLeft + case m.Button == MouseButtonWheelRight && m.Action == MouseActionPress: + m.Type = MouseWheelRight + case m.Button == MouseButtonBackward && m.Action == MouseActionPress: + m.Type = MouseBackward + case m.Button == MouseButtonForward && m.Action == MouseActionPress: + m.Type = MouseForward + case m.Action == MouseActionMotion: + m.Type = MouseMotion + switch m.Button { + case MouseButtonLeft: + m.Type = MouseLeft + case MouseButtonMiddle: + m.Type = MouseMiddle + case MouseButtonRight: + m.Type = MouseRight + case MouseButtonBackward: + m.Type = MouseBackward + case MouseButtonForward: + m.Type = MouseForward + } + default: + m.Type = MouseUnknown + } return m } diff --git a/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go b/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go index f5637aa..b9edeac 100644 --- a/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go +++ b/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go @@ -2,18 +2,23 @@ package tea type nilRenderer struct{} -func (n nilRenderer) start() {} -func (n nilRenderer) stop() {} -func (n nilRenderer) kill() {} -func (n nilRenderer) write(_ string) {} -func (n nilRenderer) repaint() {} -func (n nilRenderer) clearScreen() {} -func (n nilRenderer) altScreen() bool { return false } -func (n nilRenderer) enterAltScreen() {} -func (n nilRenderer) exitAltScreen() {} -func (n nilRenderer) showCursor() {} -func (n nilRenderer) hideCursor() {} -func (n nilRenderer) enableMouseCellMotion() {} -func (n nilRenderer) disableMouseCellMotion() {} -func (n nilRenderer) enableMouseAllMotion() {} -func (n nilRenderer) disableMouseAllMotion() {} +func (n nilRenderer) start() {} +func (n nilRenderer) stop() {} +func (n nilRenderer) kill() {} +func (n nilRenderer) write(_ string) {} +func (n nilRenderer) repaint() {} +func (n nilRenderer) clearScreen() {} +func (n nilRenderer) altScreen() bool { return false } +func (n nilRenderer) enterAltScreen() {} +func (n nilRenderer) exitAltScreen() {} +func (n nilRenderer) showCursor() {} +func (n nilRenderer) hideCursor() {} +func (n nilRenderer) enableMouseCellMotion() {} +func (n nilRenderer) disableMouseCellMotion() {} +func (n nilRenderer) enableMouseAllMotion() {} +func (n nilRenderer) disableMouseAllMotion() {} +func (n nilRenderer) enableBracketedPaste() {} +func (n nilRenderer) disableBracketedPaste() {} +func (n nilRenderer) enableMouseSGRMode() {} +func (n nilRenderer) disableMouseSGRMode() {} +func (n nilRenderer) bracketedPasteActive() bool { return false } diff --git a/vendor/github.com/charmbracelet/bubbletea/options.go b/vendor/github.com/charmbracelet/bubbletea/options.go index 249d3bf..e78a048 100644 --- a/vendor/github.com/charmbracelet/bubbletea/options.go +++ b/vendor/github.com/charmbracelet/bubbletea/options.go @@ -3,6 +3,7 @@ package tea import ( "context" "io" + "sync/atomic" "github.com/muesli/termenv" ) @@ -76,7 +77,7 @@ func WithoutCatchPanics() ProgramOption { // This is mainly useful for testing. func WithoutSignals() ProgramOption { return func(p *Program) { - p.ignoreSignals = true + atomic.StoreUint32(&p.ignoreSignals, 1) } } @@ -100,6 +101,13 @@ func WithAltScreen() ProgramOption { } } +// WithoutBracketedPaste starts the program with bracketed paste disabled. +func WithoutBracketedPaste() ProgramOption { + return func(p *Program) { + p.startupOptions |= withoutBracketedPaste + } +} + // WithMouseCellMotion starts the program with the mouse enabled in "cell // motion" mode. // @@ -107,6 +115,9 @@ func WithAltScreen() ProgramOption { // movement events are also captured if a mouse button is pressed (i.e., drag // events). Cell motion mode is better supported than all motion mode. // +// This will try to enable the mouse in extended mode (SGR), if that is not +// supported by the terminal it will fall back to normal mode (X10). +// // To enable mouse cell motion once the program has already started running use // the EnableMouseCellMotion command. To disable the mouse when the program is // running use the DisableMouse command. @@ -126,6 +137,9 @@ func WithMouseCellMotion() ProgramOption { // wheel, and motion events, which are delivered regardless of whether a mouse // button is pressed, effectively enabling support for hover interactions. // +// This will try to enable the mouse in extended mode (SGR), if that is not +// supported by the terminal it will fall back to normal mode (X10). +// // Many modern terminals support this, but not all. If in doubt, use // EnableMouseCellMotion instead. // @@ -201,7 +215,7 @@ func WithFilter(filter func(Model, Msg) Msg) ProgramOption { } } -// WithMaxFPS sets a custom maximum FPS at which the renderer should run. If +// WithFPS sets a custom maximum FPS at which the renderer should run. If // less than 1, the default value of 60 will be used. If over 120, the FPS // will be capped at 120. func WithFPS(fps int) ProgramOption { diff --git a/vendor/github.com/charmbracelet/bubbletea/renderer.go b/vendor/github.com/charmbracelet/bubbletea/renderer.go index 15ef22e..c4cb0f0 100644 --- a/vendor/github.com/charmbracelet/bubbletea/renderer.go +++ b/vendor/github.com/charmbracelet/bubbletea/renderer.go @@ -40,16 +40,33 @@ type renderer interface { // events if a mouse button is pressed (i.e., drag events). enableMouseCellMotion() - // DisableMouseCellMotion disables Mouse Cell Motion tracking. + // disableMouseCellMotion disables Mouse Cell Motion tracking. disableMouseCellMotion() - // EnableMouseAllMotion enables mouse click, release, wheel and motion + // enableMouseAllMotion enables mouse click, release, wheel and motion // events, regardless of whether a mouse button is pressed. Many modern // terminals support this, but not all. enableMouseAllMotion() - // DisableMouseAllMotion disables All Motion mouse tracking. + // disableMouseAllMotion disables All Motion mouse tracking. disableMouseAllMotion() + + // enableMouseSGRMode enables mouse extended mode (SGR). + enableMouseSGRMode() + + // disableMouseSGRMode disables mouse extended mode (SGR). + disableMouseSGRMode() + + // enableBracketedPaste enables bracketed paste, where characters + // inside the input are not interpreted when pasted as a whole. + enableBracketedPaste() + + // disableBracketedPaste disables bracketed paste. + disableBracketedPaste() + + // bracketedPasteActive reports whether bracketed paste mode is + // currently enabled. + bracketedPasteActive() bool } // repaintMsg forces a full repaint. diff --git a/vendor/github.com/charmbracelet/bubbletea/screen.go b/vendor/github.com/charmbracelet/bubbletea/screen.go index 899db3d..b34af56 100644 --- a/vendor/github.com/charmbracelet/bubbletea/screen.go +++ b/vendor/github.com/charmbracelet/bubbletea/screen.go @@ -116,6 +116,34 @@ func ShowCursor() Msg { // this message with ShowCursor. type showCursorMsg struct{} +// EnableBracketedPaste is a special command that tells the Bubble Tea program +// to accept bracketed paste input. +// +// Note that bracketed paste will be automatically disabled when the +// program quits. +func EnableBracketedPaste() Msg { + return enableBracketedPasteMsg{} +} + +// enableBracketedPasteMsg in an internal message signals that +// bracketed paste should be enabled. You can send an +// enableBracketedPasteMsg with EnableBracketedPaste. +type enableBracketedPasteMsg struct{} + +// DisableBracketedPaste is a special command that tells the Bubble Tea program +// to accept bracketed paste input. +// +// Note that bracketed paste will be automatically disabled when the +// program quits. +func DisableBracketedPaste() Msg { + return disableBracketedPasteMsg{} +} + +// disableBracketedPasteMsg in an internal message signals that +// bracketed paste should be disabled. You can send an +// disableBracketedPasteMsg with DisableBracketedPaste. +type disableBracketedPasteMsg struct{} + // EnterAltScreen enters the alternate screen buffer, which consumes the entire // terminal window. ExitAltScreen will return the terminal to its former state. // @@ -167,3 +195,8 @@ func (p *Program) EnableMouseAllMotion() { func (p *Program) DisableMouseAllMotion() { p.renderer.disableMouseAllMotion() } + +// SetWindowTitle sets the terminal window title. +func (p *Program) SetWindowTitle(title string) { + p.output.SetWindowTitle(title) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/signals_unix.go b/vendor/github.com/charmbracelet/bubbletea/signals_unix.go index 826f58b..4095403 100644 --- a/vendor/github.com/charmbracelet/bubbletea/signals_unix.go +++ b/vendor/github.com/charmbracelet/bubbletea/signals_unix.go @@ -1,5 +1,5 @@ -//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix -// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix || zos +// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix zos package tea diff --git a/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go b/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go index c6a1b61..4e63fd6 100644 --- a/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go +++ b/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go @@ -45,6 +45,9 @@ type standardRenderer struct { // essentially whether or not we're using the full size of the terminal altScreenActive bool + // whether or not we're currently using bracketed paste + bpActive bool + // renderer dimensions; usually the size of the window width int height int @@ -170,19 +173,18 @@ func (r *standardRenderer) flush() { skipLines := make(map[int]struct{}) flushQueuedMessages := len(r.queuedMessageLines) > 0 && !r.altScreenActive - // Add any queued messages to this render - if flushQueuedMessages { - newLines = append(r.queuedMessageLines, newLines...) - r.queuedMessageLines = []string{} - } - // Clear any lines we painted in the last render. if r.linesRendered > 0 { for i := r.linesRendered - 1; i > 0; i-- { - // If the number of lines we want to render hasn't increased and - // new line is the same as the old line we can skip rendering for - // this line as a performance optimization. - if (len(newLines) <= len(oldLines)) && (len(newLines) > i && len(oldLines) > i) && (newLines[i] == oldLines[i]) { + // if we are clearing queued messages, we want to clear all lines, since + // printing messages allows for native terminal word-wrap, we + // don't have control over the queued lines + if flushQueuedMessages { + out.ClearLine() + } else if (len(newLines) <= len(oldLines)) && (len(newLines) > i && len(oldLines) > i) && (newLines[i] == oldLines[i]) { + // If the number of lines we want to render hasn't increased and + // new line is the same as the old line we can skip rendering for + // this line as a performance optimization. skipLines[i] = struct{}{} } else if _, exists := r.ignoreLines[i]; !exists { out.ClearLine() @@ -208,10 +210,18 @@ func (r *standardRenderer) flush() { // Merge the set of lines we're skipping as a rendering optimization with // the set of lines we've explicitly asked the renderer to ignore. - if r.ignoreLines != nil { - for k, v := range r.ignoreLines { - skipLines[k] = v + for k, v := range r.ignoreLines { + skipLines[k] = v + } + + if flushQueuedMessages { + // Dump the lines we've queued up for printing + for _, line := range r.queuedMessageLines { + _, _ = out.WriteString(line) + _, _ = out.WriteString("\r\n") } + // clear the queued message lines + r.queuedMessageLines = []string{} } // Paint new lines @@ -398,6 +408,43 @@ func (r *standardRenderer) disableMouseAllMotion() { r.out.DisableMouseAllMotion() } +func (r *standardRenderer) enableMouseSGRMode() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.out.EnableMouseExtendedMode() +} + +func (r *standardRenderer) disableMouseSGRMode() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.out.DisableMouseExtendedMode() +} + +func (r *standardRenderer) enableBracketedPaste() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.out.EnableBracketedPaste() + r.bpActive = true +} + +func (r *standardRenderer) disableBracketedPaste() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.out.DisableBracketedPaste() + r.bpActive = false +} + +func (r *standardRenderer) bracketedPasteActive() bool { + r.mtx.Lock() + defer r.mtx.Unlock() + + return r.bpActive +} + // setIgnoredLines specifies lines not to be touched by the standard Bubble Tea // renderer. func (r *standardRenderer) setIgnoredLines(from int, to int) { diff --git a/vendor/github.com/charmbracelet/bubbletea/tea.go b/vendor/github.com/charmbracelet/bubbletea/tea.go index 7e642c9..6aaab64 100644 --- a/vendor/github.com/charmbracelet/bubbletea/tea.go +++ b/vendor/github.com/charmbracelet/bubbletea/tea.go @@ -18,13 +18,13 @@ import ( "os/signal" "runtime/debug" "sync" + "sync/atomic" "syscall" - "github.com/containerd/console" - "github.com/mattn/go-isatty" "github.com/muesli/cancelreader" "github.com/muesli/termenv" "golang.org/x/sync/errgroup" + "golang.org/x/term" ) // ErrProgramKilled is returned by [Program.Run] when the program got killed. @@ -80,7 +80,7 @@ func (i inputType) String() string { // generally set with ProgramOptions. // // The options here are treated as bits. -type startupOptions byte +type startupOptions int16 func (s startupOptions) has(option startupOptions) bool { return s&option != 0 @@ -92,26 +92,27 @@ const ( withMouseAllMotion withANSICompressor withoutSignalHandler - // Catching panics is incredibly useful for restoring the terminal to a // usable state after a panic occurs. When this is set, Bubble Tea will // recover from panics, print the stack trace, and disable raw mode. This // feature is on by default. withoutCatchPanics + withoutBracketedPaste ) -// handlers manages series of channels returned by various processes. It allows -// us to wait for those processes to terminate before exiting the program. -type handlers []chan struct{} +// channelHandlers manages the series of channels returned by various processes. +// It allows us to wait for those processes to terminate before exiting the +// program. +type channelHandlers []chan struct{} // Adds a channel to the list of handlers. We wait for all handlers to terminate // gracefully on shutdown. -func (h *handlers) add(ch chan struct{}) { +func (h *channelHandlers) add(ch chan struct{}) { *h = append(*h, ch) } // shutdown waits for all handlers to terminate. -func (h handlers) shutdown() { +func (h channelHandlers) shutdown() { var wg sync.WaitGroup for _, ch := range h { wg.Add(1) @@ -146,23 +147,18 @@ type Program struct { renderer renderer // where to read inputs from, this will usually be os.Stdin. - input io.Reader - cancelReader cancelreader.CancelReader - readLoopDone chan struct{} - console console.Console + input io.Reader + // tty is null if input is not a TTY. + tty *os.File + previousTtyState *term.State + cancelReader cancelreader.CancelReader + readLoopDone chan struct{} // was the altscreen active before releasing the terminal? altScreenWasActive bool - ignoreSignals bool + ignoreSignals uint32 - // Stores the original reference to stdin for cases where input is not a - // TTY on windows and we've automatically opened CONIN$ to receive input. - // When the program exits this will be restored. - // - // Lint ignore note: the linter will find false positive on unix systems - // as this value only comes into play on Windows, hence the ignore comment - // below. - windowsStdin *os.File //nolint:golint,structcheck,unused + bpWasActive bool // was the bracketed paste mode active before releasing the terminal? filter func(Model, Msg) Msg @@ -238,7 +234,7 @@ func (p *Program) handleSignals() chan struct{} { return case <-sig: - if !p.ignoreSignals { + if atomic.LoadUint32(&p.ignoreSignals) == 0 { p.msgs <- QuitMsg{} return } @@ -253,7 +249,7 @@ func (p *Program) handleSignals() chan struct{} { func (p *Program) handleResize() chan struct{} { ch := make(chan struct{}) - if f, ok := p.output.TTY().(*os.File); ok && isatty.IsTerminal(f.Fd()) { + if f, ok := p.output.TTY().(*os.File); ok && term.IsTerminal(int(f.Fd())) { // Get the initial terminal size and send it to the program. go p.checkResize() @@ -300,6 +296,12 @@ func (p *Program) handleCommands(cmds chan Cmd) chan struct{} { return ch } +func (p *Program) disableMouse() { + p.renderer.disableMouseCellMotion() + p.renderer.disableMouseAllMotion() + p.renderer.disableMouseSGRMode() +} + // eventLoop is the central message loop. It receives and handles the default // Bubble Tea messages, update the model and triggers redraws. func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { @@ -334,15 +336,18 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { case exitAltScreenMsg: p.renderer.exitAltScreen() - case enableMouseCellMotionMsg: - p.renderer.enableMouseCellMotion() - - case enableMouseAllMotionMsg: - p.renderer.enableMouseAllMotion() + case enableMouseCellMotionMsg, enableMouseAllMotionMsg: + switch msg.(type) { + case enableMouseCellMotionMsg: + p.renderer.enableMouseCellMotion() + case enableMouseAllMotionMsg: + p.renderer.enableMouseAllMotion() + } + // mouse mode (1006) is a no-op if the terminal doesn't support it. + p.renderer.enableMouseSGRMode() case disableMouseMsg: - p.renderer.disableMouseCellMotion() - p.renderer.disableMouseAllMotion() + p.disableMouse() case showCursorMsg: p.renderer.showCursor() @@ -350,6 +355,12 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { case hideCursorMsg: p.renderer.hideCursor() + case enableBracketedPasteMsg: + p.renderer.enableBracketedPaste() + + case disableBracketedPasteMsg: + p.renderer.disableBracketedPaste() + case execMsg: // NB: this blocks. p.exec(msg.cmd, msg.fn) @@ -387,6 +398,9 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { p.Send(msg) } }() + + case setWindowTitleMsg: + p.SetWindowTitle(string(msg)) } // Process internal messages for the renderer. @@ -406,7 +420,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { // terminated by either [Program.Quit], [Program.Kill], or its signal handler. // Returns the final model. func (p *Program) Run() (Model, error) { - handlers := handlers{} + handlers := channelHandlers{} cmds := make(chan Cmd) p.errs = make(chan error) p.finished = make(chan struct{}, 1) @@ -427,7 +441,7 @@ func (p *Program) Run() (Model, error) { if !isFile { break } - if isatty.IsTerminal(f.Fd()) { + if term.IsTerminal(int(f.Fd())) { break } @@ -483,10 +497,15 @@ func (p *Program) Run() (Model, error) { if p.startupOptions&withAltScreen != 0 { p.renderer.enterAltScreen() } + if p.startupOptions&withoutBracketedPaste == 0 { + p.renderer.enableBracketedPaste() + } if p.startupOptions&withMouseCellMotion != 0 { p.renderer.enableMouseCellMotion() + p.renderer.enableMouseSGRMode() } else if p.startupOptions&withMouseAllMotion != 0 { p.renderer.enableMouseAllMotion() + p.renderer.enableMouseSGRMode() } // Initialize the program. @@ -632,7 +651,7 @@ func (p *Program) shutdown(kill bool) { // ReleaseTerminal restores the original terminal state and cancels the input // reader. You can return control to the Program with RestoreTerminal. func (p *Program) ReleaseTerminal() error { - p.ignoreSignals = true + atomic.StoreUint32(&p.ignoreSignals, 1) p.cancelReader.Cancel() p.waitForReadLoop() @@ -641,6 +660,7 @@ func (p *Program) ReleaseTerminal() error { } p.altScreenWasActive = p.renderer.altScreen() + p.bpWasActive = p.renderer.bracketedPasteActive() return p.restoreTerminalState() } @@ -648,7 +668,7 @@ func (p *Program) ReleaseTerminal() error { // terminal to the former state when the program was running, and repaints. // Use it to reinitialize a Program after running ReleaseTerminal. func (p *Program) RestoreTerminal() error { - p.ignoreSignals = false + atomic.StoreUint32(&p.ignoreSignals, 0) if err := p.initTerminal(); err != nil { return err @@ -656,7 +676,6 @@ func (p *Program) RestoreTerminal() error { if err := p.initCancelReader(); err != nil { return err } - if p.altScreenWasActive { p.renderer.enterAltScreen() } else { @@ -666,6 +685,9 @@ func (p *Program) RestoreTerminal() error { if p.renderer != nil { p.renderer.start() } + if p.bpWasActive { + p.renderer.enableBracketedPaste() + } // If the output is a terminal, it may have been resized while another // process was at the foreground, in which case we may not have received diff --git a/vendor/github.com/charmbracelet/bubbletea/tty.go b/vendor/github.com/charmbracelet/bubbletea/tty.go index 05e21ca..847a4e6 100644 --- a/vendor/github.com/charmbracelet/bubbletea/tty.go +++ b/vendor/github.com/charmbracelet/bubbletea/tty.go @@ -2,29 +2,20 @@ package tea import ( "errors" + "fmt" "io" "os" "time" - isatty "github.com/mattn/go-isatty" - localereader "github.com/mattn/go-localereader" "github.com/muesli/cancelreader" "golang.org/x/term" ) func (p *Program) initTerminal() error { - err := p.initInput() - if err != nil { + if err := p.initInput(); err != nil { return err } - if p.console != nil { - err = p.console.SetRaw() - if err != nil { - return err - } - } - p.renderer.hideCursor() return nil } @@ -33,34 +24,37 @@ func (p *Program) initTerminal() error { // Bubble Tea program. func (p *Program) restoreTerminalState() error { if p.renderer != nil { + p.renderer.disableBracketedPaste() p.renderer.showCursor() - p.renderer.disableMouseCellMotion() - p.renderer.disableMouseAllMotion() + p.disableMouse() if p.renderer.altScreen() { p.renderer.exitAltScreen() // give the terminal a moment to catch up - time.Sleep(time.Millisecond * 10) + time.Sleep(time.Millisecond * 10) //nolint:gomnd } } - if p.console != nil { - err := p.console.Reset() - if err != nil { - return err + return p.restoreInput() +} + +// restoreInput restores the tty input to its original state. +func (p *Program) restoreInput() error { + if p.tty != nil && p.previousTtyState != nil { + if err := term.Restore(int(p.tty.Fd()), p.previousTtyState); err != nil { + return fmt.Errorf("error restoring console: %w", err) } } - - return p.restoreInput() + return nil } // initCancelReader (re)commences reading inputs. func (p *Program) initCancelReader() error { var err error - p.cancelReader, err = cancelreader.NewReader(p.input) + p.cancelReader, err = newInputReader(p.input) if err != nil { - return err + return fmt.Errorf("error creating cancelreader: %w", err) } p.readLoopDone = make(chan struct{}) @@ -72,8 +66,7 @@ func (p *Program) initCancelReader() error { func (p *Program) readLoop() { defer close(p.readLoopDone) - input := localereader.NewReader(p.cancelReader) - err := readInputs(p.ctx, p.msgs, input) + err := readInputs(p.ctx, p.msgs, p.cancelReader) if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) { select { case <-p.ctx.Done(): @@ -86,7 +79,7 @@ func (p *Program) readLoop() { func (p *Program) waitForReadLoop() { select { case <-p.readLoopDone: - case <-time.After(500 * time.Millisecond): + case <-time.After(500 * time.Millisecond): //nolint:gomnd // The read loop hangs, which means the input // cancelReader's cancel function has returned true even // though it was not able to cancel the read. @@ -99,7 +92,7 @@ var lastHeight, lastWidth int // via a WindowSizeMsg. func (p *Program) checkResize() { f, ok := p.output.TTY().(*os.File) - if !ok || !isatty.IsTerminal(f.Fd()) { + if !ok || !term.IsTerminal(int(f.Fd())) { // can't query window size return } diff --git a/vendor/github.com/charmbracelet/bubbletea/tty_unix.go b/vendor/github.com/charmbracelet/bubbletea/tty_unix.go index b6f5ffd..a93444d 100644 --- a/vendor/github.com/charmbracelet/bubbletea/tty_unix.go +++ b/vendor/github.com/charmbracelet/bubbletea/tty_unix.go @@ -1,42 +1,32 @@ -//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix -// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix || zos +// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix zos package tea import ( + "fmt" "os" - "github.com/containerd/console" + "golang.org/x/term" ) -func (p *Program) initInput() error { - // If input's a file, use console to manage it - if f, ok := p.input.(*os.File); ok { - c, err := console.ConsoleFromFile(f) +func (p *Program) initInput() (err error) { + // Check if input is a terminal + if f, ok := p.input.(*os.File); ok && term.IsTerminal(int(f.Fd())) { + p.tty = f + p.previousTtyState, err = term.MakeRaw(int(p.tty.Fd())) if err != nil { - return nil //nolint:nilerr // ignore error, this was just a test + return fmt.Errorf("error entering raw mode: %w", err) } - p.console = c } return nil } -// On unix systems, RestoreInput closes any TTYs we opened for input. Note that -// we don't do this on Windows as it causes the prompt to not be drawn until -// the terminal receives a keypress rather than appearing promptly after the -// program exits. -func (p *Program) restoreInput() error { - if p.console != nil { - return p.console.Reset() - } - return nil -} - func openInputTTY() (*os.File, error) { f, err := os.Open("/dev/tty") if err != nil { - return nil, err + return nil, fmt.Errorf("could not open a new TTY: %w", err) } return f, nil } diff --git a/vendor/github.com/charmbracelet/bubbletea/tty_windows.go b/vendor/github.com/charmbracelet/bubbletea/tty_windows.go index be415ae..10b6108 100644 --- a/vendor/github.com/charmbracelet/bubbletea/tty_windows.go +++ b/vendor/github.com/charmbracelet/bubbletea/tty_windows.go @@ -4,37 +4,36 @@ package tea import ( + "fmt" "os" - "github.com/containerd/console" + "golang.org/x/sys/windows" + "golang.org/x/term" ) -func (p *Program) initInput() error { - // If input's a file, use console to manage it - if f, ok := p.input.(*os.File); ok { - // Save a reference to the current stdin then replace stdin with our - // input. We do this so we can hand input off to containerd/console to - // set raw mode, and do it in this fashion because the method - // console.ConsoleFromFile isn't supported on Windows. - p.windowsStdin = os.Stdin - os.Stdin = f - - // Note: this will panic if it fails. - c := console.Current() - p.console = c +func (p *Program) initInput() (err error) { + // Save stdin state and enable VT input + // We enable VT processing using Termenv, but we also need to enable VT + // input here. + if f, ok := p.input.(*os.File); ok && term.IsTerminal(int(f.Fd())) { + p.tty = f + p.previousTtyState, err = term.MakeRaw(int(p.tty.Fd())) + if err != nil { + return err + } + + // Enable VT input + var mode uint32 + if err := windows.GetConsoleMode(windows.Handle(p.tty.Fd()), &mode); err != nil { + return fmt.Errorf("error getting console mode: %w", err) + } + + if err := windows.SetConsoleMode(windows.Handle(p.tty.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil { + return fmt.Errorf("error setting console mode: %w", err) + } } - return nil -} - -// restoreInput restores stdout in the event that we placed it aside to handle -// input with CONIN$, above. -func (p *Program) restoreInput() error { - if p.windowsStdin != nil { - os.Stdin = p.windowsStdin - } - - return nil + return } // Open the Windows equivalent of a TTY. diff --git a/vendor/github.com/containerd/console/.golangci.yml b/vendor/github.com/containerd/console/.golangci.yml deleted file mode 100644 index abe3d84..0000000 --- a/vendor/github.com/containerd/console/.golangci.yml +++ /dev/null @@ -1,20 +0,0 @@ -linters: - enable: - - gofmt - - goimports - - ineffassign - - misspell - - revive - - staticcheck - - structcheck - - unconvert - - unused - - varcheck - - vet - disable: - - errcheck - -run: - timeout: 3m - skip-dirs: - - vendor diff --git a/vendor/github.com/containerd/console/README.md b/vendor/github.com/containerd/console/README.md deleted file mode 100644 index 580b461..0000000 --- a/vendor/github.com/containerd/console/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# console - -[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/console)](https://pkg.go.dev/github.com/containerd/console) -[![Build Status](https://github.com/containerd/console/workflows/CI/badge.svg)](https://github.com/containerd/console/actions?query=workflow%3ACI) -[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/console)](https://goreportcard.com/report/github.com/containerd/console) - -Golang package for dealing with consoles. Light on deps and a simple API. - -## Modifying the current process - -```go -current := console.Current() -defer current.Reset() - -if err := current.SetRaw(); err != nil { -} -ws, err := current.Size() -current.Resize(ws) -``` - -## Project details - -console is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). -As a containerd sub-project, you will find the: - * [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md), - * [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS), - * and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md) - -information in our [`containerd/project`](https://github.com/containerd/project) repository. diff --git a/vendor/github.com/containerd/console/console.go b/vendor/github.com/containerd/console/console.go deleted file mode 100644 index 810a71f..0000000 --- a/vendor/github.com/containerd/console/console.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "errors" - "io" - "os" -) - -var ErrNotAConsole = errors.New("provided file is not a console") - -type File interface { - io.ReadWriteCloser - - // Fd returns its file descriptor - Fd() uintptr - // Name returns its file name - Name() string -} - -type Console interface { - File - - // Resize resizes the console to the provided window size - Resize(WinSize) error - // ResizeFrom resizes the calling console to the size of the - // provided console - ResizeFrom(Console) error - // SetRaw sets the console in raw mode - SetRaw() error - // DisableEcho disables echo on the console - DisableEcho() error - // Reset restores the console to its orignal state - Reset() error - // Size returns the window size of the console - Size() (WinSize, error) -} - -// WinSize specifies the window size of the console -type WinSize struct { - // Height of the console - Height uint16 - // Width of the console - Width uint16 - x uint16 - y uint16 -} - -// Current returns the current process' console -func Current() (c Console) { - var err error - // Usually all three streams (stdin, stdout, and stderr) - // are open to the same console, but some might be redirected, - // so try all three. - for _, s := range []*os.File{os.Stderr, os.Stdout, os.Stdin} { - if c, err = ConsoleFromFile(s); err == nil { - return c - } - } - // One of the std streams should always be a console - // for the design of this function. - panic(err) -} - -// ConsoleFromFile returns a console using the provided file -// nolint:revive -func ConsoleFromFile(f File) (Console, error) { - if err := checkConsole(f); err != nil { - return nil, err - } - return newMaster(f) -} diff --git a/vendor/github.com/containerd/console/console_linux.go b/vendor/github.com/containerd/console/console_linux.go deleted file mode 100644 index 28b77b7..0000000 --- a/vendor/github.com/containerd/console/console_linux.go +++ /dev/null @@ -1,281 +0,0 @@ -//go:build linux -// +build linux - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "io" - "os" - "sync" - - "golang.org/x/sys/unix" -) - -const ( - maxEvents = 128 -) - -// Epoller manages multiple epoll consoles using edge-triggered epoll api so we -// dont have to deal with repeated wake-up of EPOLLER or EPOLLHUP. -// For more details, see: -// - https://github.com/systemd/systemd/pull/4262 -// - https://github.com/moby/moby/issues/27202 -// -// Example usage of Epoller and EpollConsole can be as follow: -// -// epoller, _ := NewEpoller() -// epollConsole, _ := epoller.Add(console) -// go epoller.Wait() -// var ( -// b bytes.Buffer -// wg sync.WaitGroup -// ) -// wg.Add(1) -// go func() { -// io.Copy(&b, epollConsole) -// wg.Done() -// }() -// // perform I/O on the console -// epollConsole.Shutdown(epoller.CloseConsole) -// wg.Wait() -// epollConsole.Close() -type Epoller struct { - efd int - mu sync.Mutex - fdMapping map[int]*EpollConsole - closeOnce sync.Once -} - -// NewEpoller returns an instance of epoller with a valid epoll fd. -func NewEpoller() (*Epoller, error) { - efd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC) - if err != nil { - return nil, err - } - return &Epoller{ - efd: efd, - fdMapping: make(map[int]*EpollConsole), - }, nil -} - -// Add creates an epoll console based on the provided console. The console will -// be registered with EPOLLET (i.e. using edge-triggered notification) and its -// file descriptor will be set to non-blocking mode. After this, user should use -// the return console to perform I/O. -func (e *Epoller) Add(console Console) (*EpollConsole, error) { - sysfd := int(console.Fd()) - // Set sysfd to non-blocking mode - if err := unix.SetNonblock(sysfd, true); err != nil { - return nil, err - } - - ev := unix.EpollEvent{ - Events: unix.EPOLLIN | unix.EPOLLOUT | unix.EPOLLRDHUP | unix.EPOLLET, - Fd: int32(sysfd), - } - if err := unix.EpollCtl(e.efd, unix.EPOLL_CTL_ADD, sysfd, &ev); err != nil { - return nil, err - } - ef := &EpollConsole{ - Console: console, - sysfd: sysfd, - readc: sync.NewCond(&sync.Mutex{}), - writec: sync.NewCond(&sync.Mutex{}), - } - e.mu.Lock() - e.fdMapping[sysfd] = ef - e.mu.Unlock() - return ef, nil -} - -// Wait starts the loop to wait for its consoles' notifications and signal -// appropriate console that it can perform I/O. -func (e *Epoller) Wait() error { - events := make([]unix.EpollEvent, maxEvents) - for { - n, err := unix.EpollWait(e.efd, events, -1) - if err != nil { - // EINTR: The call was interrupted by a signal handler before either - // any of the requested events occurred or the timeout expired - if err == unix.EINTR { - continue - } - return err - } - for i := 0; i < n; i++ { - ev := &events[i] - // the console is ready to be read from - if ev.Events&(unix.EPOLLIN|unix.EPOLLHUP|unix.EPOLLERR) != 0 { - if epfile := e.getConsole(int(ev.Fd)); epfile != nil { - epfile.signalRead() - } - } - // the console is ready to be written to - if ev.Events&(unix.EPOLLOUT|unix.EPOLLHUP|unix.EPOLLERR) != 0 { - if epfile := e.getConsole(int(ev.Fd)); epfile != nil { - epfile.signalWrite() - } - } - } - } -} - -// CloseConsole unregisters the console's file descriptor from epoll interface -func (e *Epoller) CloseConsole(fd int) error { - e.mu.Lock() - defer e.mu.Unlock() - delete(e.fdMapping, fd) - return unix.EpollCtl(e.efd, unix.EPOLL_CTL_DEL, fd, &unix.EpollEvent{}) -} - -func (e *Epoller) getConsole(sysfd int) *EpollConsole { - e.mu.Lock() - f := e.fdMapping[sysfd] - e.mu.Unlock() - return f -} - -// Close closes the epoll fd -func (e *Epoller) Close() error { - closeErr := os.ErrClosed // default to "file already closed" - e.closeOnce.Do(func() { - closeErr = unix.Close(e.efd) - }) - return closeErr -} - -// EpollConsole acts like a console but registers its file descriptor with an -// epoll fd and uses epoll API to perform I/O. -type EpollConsole struct { - Console - readc *sync.Cond - writec *sync.Cond - sysfd int - closed bool -} - -// Read reads up to len(p) bytes into p. It returns the number of bytes read -// (0 <= n <= len(p)) and any error encountered. -// -// If the console's read returns EAGAIN or EIO, we assume that it's a -// temporary error because the other side went away and wait for the signal -// generated by epoll event to continue. -func (ec *EpollConsole) Read(p []byte) (n int, err error) { - var read int - ec.readc.L.Lock() - defer ec.readc.L.Unlock() - for { - read, err = ec.Console.Read(p[n:]) - n += read - if err != nil { - var hangup bool - if perr, ok := err.(*os.PathError); ok { - hangup = (perr.Err == unix.EAGAIN || perr.Err == unix.EIO) - } else { - hangup = (err == unix.EAGAIN || err == unix.EIO) - } - // if the other end disappear, assume this is temporary and wait for the - // signal to continue again. Unless we didnt read anything and the - // console is already marked as closed then we should exit - if hangup && !(n == 0 && len(p) > 0 && ec.closed) { - ec.readc.Wait() - continue - } - } - break - } - // if we didnt read anything then return io.EOF to end gracefully - if n == 0 && len(p) > 0 && err == nil { - err = io.EOF - } - // signal for others that we finished the read - ec.readc.Signal() - return n, err -} - -// Writes len(p) bytes from p to the console. It returns the number of bytes -// written from p (0 <= n <= len(p)) and any error encountered that caused -// the write to stop early. -// -// If writes to the console returns EAGAIN or EIO, we assume that it's a -// temporary error because the other side went away and wait for the signal -// generated by epoll event to continue. -func (ec *EpollConsole) Write(p []byte) (n int, err error) { - var written int - ec.writec.L.Lock() - defer ec.writec.L.Unlock() - for { - written, err = ec.Console.Write(p[n:]) - n += written - if err != nil { - var hangup bool - if perr, ok := err.(*os.PathError); ok { - hangup = (perr.Err == unix.EAGAIN || perr.Err == unix.EIO) - } else { - hangup = (err == unix.EAGAIN || err == unix.EIO) - } - // if the other end disappears, assume this is temporary and wait for the - // signal to continue again. - if hangup { - ec.writec.Wait() - continue - } - } - // unrecoverable error, break the loop and return the error - break - } - if n < len(p) && err == nil { - err = io.ErrShortWrite - } - // signal for others that we finished the write - ec.writec.Signal() - return n, err -} - -// Shutdown closes the file descriptor and signals call waiters for this fd. -// It accepts a callback which will be called with the console's fd. The -// callback typically will be used to do further cleanup such as unregister the -// console's fd from the epoll interface. -// User should call Shutdown and wait for all I/O operation to be finished -// before closing the console. -func (ec *EpollConsole) Shutdown(close func(int) error) error { - ec.readc.L.Lock() - defer ec.readc.L.Unlock() - ec.writec.L.Lock() - defer ec.writec.L.Unlock() - - ec.readc.Broadcast() - ec.writec.Broadcast() - ec.closed = true - return close(ec.sysfd) -} - -// signalRead signals that the console is readable. -func (ec *EpollConsole) signalRead() { - ec.readc.L.Lock() - ec.readc.Signal() - ec.readc.L.Unlock() -} - -// signalWrite signals that the console is writable. -func (ec *EpollConsole) signalWrite() { - ec.writec.L.Lock() - ec.writec.Signal() - ec.writec.L.Unlock() -} diff --git a/vendor/github.com/containerd/console/console_unix.go b/vendor/github.com/containerd/console/console_unix.go deleted file mode 100644 index 161f5d1..0000000 --- a/vendor/github.com/containerd/console/console_unix.go +++ /dev/null @@ -1,157 +0,0 @@ -//go:build darwin || freebsd || linux || netbsd || openbsd || zos -// +build darwin freebsd linux netbsd openbsd zos - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "golang.org/x/sys/unix" -) - -// NewPty creates a new pty pair -// The master is returned as the first console and a string -// with the path to the pty slave is returned as the second -func NewPty() (Console, string, error) { - f, err := openpt() - if err != nil { - return nil, "", err - } - slave, err := ptsname(f) - if err != nil { - return nil, "", err - } - if err := unlockpt(f); err != nil { - return nil, "", err - } - m, err := newMaster(f) - if err != nil { - return nil, "", err - } - return m, slave, nil -} - -type master struct { - f File - original *unix.Termios -} - -func (m *master) Read(b []byte) (int, error) { - return m.f.Read(b) -} - -func (m *master) Write(b []byte) (int, error) { - return m.f.Write(b) -} - -func (m *master) Close() error { - return m.f.Close() -} - -func (m *master) Resize(ws WinSize) error { - return tcswinsz(m.f.Fd(), ws) -} - -func (m *master) ResizeFrom(c Console) error { - ws, err := c.Size() - if err != nil { - return err - } - return m.Resize(ws) -} - -func (m *master) Reset() error { - if m.original == nil { - return nil - } - return tcset(m.f.Fd(), m.original) -} - -func (m *master) getCurrent() (unix.Termios, error) { - var termios unix.Termios - if err := tcget(m.f.Fd(), &termios); err != nil { - return unix.Termios{}, err - } - return termios, nil -} - -func (m *master) SetRaw() error { - rawState, err := m.getCurrent() - if err != nil { - return err - } - rawState = cfmakeraw(rawState) - rawState.Oflag = rawState.Oflag | unix.OPOST - return tcset(m.f.Fd(), &rawState) -} - -func (m *master) DisableEcho() error { - rawState, err := m.getCurrent() - if err != nil { - return err - } - rawState.Lflag = rawState.Lflag &^ unix.ECHO - return tcset(m.f.Fd(), &rawState) -} - -func (m *master) Size() (WinSize, error) { - return tcgwinsz(m.f.Fd()) -} - -func (m *master) Fd() uintptr { - return m.f.Fd() -} - -func (m *master) Name() string { - return m.f.Name() -} - -// checkConsole checks if the provided file is a console -func checkConsole(f File) error { - var termios unix.Termios - if tcget(f.Fd(), &termios) != nil { - return ErrNotAConsole - } - return nil -} - -func newMaster(f File) (Console, error) { - m := &master{ - f: f, - } - t, err := m.getCurrent() - if err != nil { - return nil, err - } - m.original = &t - return m, nil -} - -// ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair -// created by us acts normally. In particular, a not-very-well-known default of -// Linux unix98 ptys is that they have +onlcr by default. While this isn't a -// problem for terminal emulators, because we relay data from the terminal we -// also relay that funky line discipline. -func ClearONLCR(fd uintptr) error { - return setONLCR(fd, false) -} - -// SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair -// created by us acts as intended for a terminal emulator. -func SetONLCR(fd uintptr) error { - return setONLCR(fd, true) -} diff --git a/vendor/github.com/containerd/console/console_windows.go b/vendor/github.com/containerd/console/console_windows.go deleted file mode 100644 index f48e486..0000000 --- a/vendor/github.com/containerd/console/console_windows.go +++ /dev/null @@ -1,222 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "errors" - "fmt" - "os" - - "golang.org/x/sys/windows" -) - -var ( - vtInputSupported bool - ErrNotImplemented = errors.New("not implemented") -) - -func (m *master) initStdios() { - // Note: We discard console mode warnings, because in/out can be redirected. - // - // TODO: Investigate opening CONOUT$/CONIN$ to handle this correctly - - m.in = windows.Handle(os.Stdin.Fd()) - if err := windows.GetConsoleMode(m.in, &m.inMode); err == nil { - // Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it. - if err = windows.SetConsoleMode(m.in, m.inMode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err == nil { - vtInputSupported = true - } - // Unconditionally set the console mode back even on failure because SetConsoleMode - // remembers invalid bits on input handles. - windows.SetConsoleMode(m.in, m.inMode) - } - - m.out = windows.Handle(os.Stdout.Fd()) - if err := windows.GetConsoleMode(m.out, &m.outMode); err == nil { - if err := windows.SetConsoleMode(m.out, m.outMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil { - m.outMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING - } else { - windows.SetConsoleMode(m.out, m.outMode) - } - } - - m.err = windows.Handle(os.Stderr.Fd()) - if err := windows.GetConsoleMode(m.err, &m.errMode); err == nil { - if err := windows.SetConsoleMode(m.err, m.errMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil { - m.errMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING - } else { - windows.SetConsoleMode(m.err, m.errMode) - } - } -} - -type master struct { - in windows.Handle - inMode uint32 - - out windows.Handle - outMode uint32 - - err windows.Handle - errMode uint32 -} - -func (m *master) SetRaw() error { - if err := makeInputRaw(m.in, m.inMode); err != nil { - return err - } - - // Set StdOut and StdErr to raw mode, we ignore failures since - // windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of - // Windows. - - windows.SetConsoleMode(m.out, m.outMode|windows.DISABLE_NEWLINE_AUTO_RETURN) - - windows.SetConsoleMode(m.err, m.errMode|windows.DISABLE_NEWLINE_AUTO_RETURN) - - return nil -} - -func (m *master) Reset() error { - var errs []error - - for _, s := range []struct { - fd windows.Handle - mode uint32 - }{ - {m.in, m.inMode}, - {m.out, m.outMode}, - {m.err, m.errMode}, - } { - if err := windows.SetConsoleMode(s.fd, s.mode); err != nil { - // we can't just abort on the first error, otherwise we might leave - // the console in an unexpected state. - errs = append(errs, fmt.Errorf("unable to restore console mode: %w", err)) - } - } - - if len(errs) > 0 { - return errs[0] - } - - return nil -} - -func (m *master) Size() (WinSize, error) { - var info windows.ConsoleScreenBufferInfo - err := windows.GetConsoleScreenBufferInfo(m.out, &info) - if err != nil { - return WinSize{}, fmt.Errorf("unable to get console info: %w", err) - } - - winsize := WinSize{ - Width: uint16(info.Window.Right - info.Window.Left + 1), - Height: uint16(info.Window.Bottom - info.Window.Top + 1), - } - - return winsize, nil -} - -func (m *master) Resize(ws WinSize) error { - return ErrNotImplemented -} - -func (m *master) ResizeFrom(c Console) error { - return ErrNotImplemented -} - -func (m *master) DisableEcho() error { - mode := m.inMode &^ windows.ENABLE_ECHO_INPUT - mode |= windows.ENABLE_PROCESSED_INPUT - mode |= windows.ENABLE_LINE_INPUT - - if err := windows.SetConsoleMode(m.in, mode); err != nil { - return fmt.Errorf("unable to set console to disable echo: %w", err) - } - - return nil -} - -func (m *master) Close() error { - return nil -} - -func (m *master) Read(b []byte) (int, error) { - return os.Stdin.Read(b) -} - -func (m *master) Write(b []byte) (int, error) { - return os.Stdout.Write(b) -} - -func (m *master) Fd() uintptr { - return uintptr(m.in) -} - -// on windows, console can only be made from os.Std{in,out,err}, hence there -// isnt a single name here we can use. Return a dummy "console" value in this -// case should be sufficient. -func (m *master) Name() string { - return "console" -} - -// makeInputRaw puts the terminal (Windows Console) connected to the given -// file descriptor into raw mode -func makeInputRaw(fd windows.Handle, mode uint32) error { - // See - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx - - // Disable these modes - mode &^= windows.ENABLE_ECHO_INPUT - mode &^= windows.ENABLE_LINE_INPUT - mode &^= windows.ENABLE_MOUSE_INPUT - mode &^= windows.ENABLE_WINDOW_INPUT - mode &^= windows.ENABLE_PROCESSED_INPUT - - // Enable these modes - mode |= windows.ENABLE_EXTENDED_FLAGS - mode |= windows.ENABLE_INSERT_MODE - mode |= windows.ENABLE_QUICK_EDIT_MODE - - if vtInputSupported { - mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT - } - - if err := windows.SetConsoleMode(fd, mode); err != nil { - return fmt.Errorf("unable to set console to raw mode: %w", err) - } - - return nil -} - -func checkConsole(f File) error { - var mode uint32 - if err := windows.GetConsoleMode(windows.Handle(f.Fd()), &mode); err != nil { - return err - } - return nil -} - -func newMaster(f File) (Console, error) { - if f != os.Stdin && f != os.Stdout && f != os.Stderr { - return nil, errors.New("creating a console from a file is not supported on windows") - } - m := &master{} - m.initStdios() - return m, nil -} diff --git a/vendor/github.com/containerd/console/pty_freebsd_cgo.go b/vendor/github.com/containerd/console/pty_freebsd_cgo.go deleted file mode 100644 index 2236862..0000000 --- a/vendor/github.com/containerd/console/pty_freebsd_cgo.go +++ /dev/null @@ -1,46 +0,0 @@ -//go:build freebsd && cgo -// +build freebsd,cgo - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "fmt" - "os" -) - -/* -#include -#include -#include -*/ -import "C" - -// openpt allocates a new pseudo-terminal and establishes a connection with its -// control device. -func openpt() (*os.File, error) { - fd, err := C.posix_openpt(C.O_RDWR) - if err != nil { - return nil, fmt.Errorf("posix_openpt: %w", err) - } - if _, err := C.grantpt(fd); err != nil { - C.close(fd) - return nil, fmt.Errorf("grantpt: %w", err) - } - return os.NewFile(uintptr(fd), ""), nil -} diff --git a/vendor/github.com/containerd/console/pty_freebsd_nocgo.go b/vendor/github.com/containerd/console/pty_freebsd_nocgo.go deleted file mode 100644 index ceb90a4..0000000 --- a/vendor/github.com/containerd/console/pty_freebsd_nocgo.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build freebsd && !cgo -// +build freebsd,!cgo - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "os" -) - -// -// Implementing the functions below requires cgo support. Non-cgo stubs -// versions are defined below to enable cross-compilation of source code -// that depends on these functions, but the resultant cross-compiled -// binaries cannot actually be used. If the stub function(s) below are -// actually invoked they will display an error message and cause the -// calling process to exit. -// - -func openpt() (*os.File, error) { - panic("openpt() support requires cgo.") -} diff --git a/vendor/github.com/containerd/console/pty_unix.go b/vendor/github.com/containerd/console/pty_unix.go deleted file mode 100644 index f5a5b80..0000000 --- a/vendor/github.com/containerd/console/pty_unix.go +++ /dev/null @@ -1,31 +0,0 @@ -//go:build darwin || linux || netbsd || openbsd -// +build darwin linux netbsd openbsd - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "os" - - "golang.org/x/sys/unix" -) - -// openpt allocates a new pseudo-terminal by opening the /dev/ptmx device -func openpt() (*os.File, error) { - return os.OpenFile("/dev/ptmx", unix.O_RDWR|unix.O_NOCTTY|unix.O_CLOEXEC, 0) -} diff --git a/vendor/github.com/containerd/console/pty_zos.go b/vendor/github.com/containerd/console/pty_zos.go deleted file mode 100644 index 58f59ab..0000000 --- a/vendor/github.com/containerd/console/pty_zos.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build zos -// +build zos - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "fmt" - "os" -) - -// openpt allocates a new pseudo-terminal by opening the first available /dev/ptypXX device -func openpt() (*os.File, error) { - var f *os.File - var err error - for i := 0; ; i++ { - ptyp := fmt.Sprintf("/dev/ptyp%04d", i) - f, err = os.OpenFile(ptyp, os.O_RDWR, 0600) - if err == nil { - break - } - if os.IsNotExist(err) { - return nil, err - } - // else probably Resource Busy - } - return f, nil -} diff --git a/vendor/github.com/containerd/console/tc_darwin.go b/vendor/github.com/containerd/console/tc_darwin.go deleted file mode 100644 index 7871545..0000000 --- a/vendor/github.com/containerd/console/tc_darwin.go +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "fmt" - "os" - - "golang.org/x/sys/unix" -) - -const ( - cmdTcGet = unix.TIOCGETA - cmdTcSet = unix.TIOCSETA -) - -// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. -// unlockpt should be called before opening the slave side of a pty. -func unlockpt(f *os.File) error { - return unix.IoctlSetPointerInt(int(f.Fd()), unix.TIOCPTYUNLK, 0) -} - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCPTYGNAME) - if err != nil { - return "", err - } - return fmt.Sprintf("/dev/pts/%d", n), nil -} diff --git a/vendor/github.com/containerd/console/tc_freebsd_cgo.go b/vendor/github.com/containerd/console/tc_freebsd_cgo.go deleted file mode 100644 index 3328257..0000000 --- a/vendor/github.com/containerd/console/tc_freebsd_cgo.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build freebsd && cgo -// +build freebsd,cgo - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "fmt" - "os" - - "golang.org/x/sys/unix" -) - -/* -#include -#include -*/ -import "C" - -const ( - cmdTcGet = unix.TIOCGETA - cmdTcSet = unix.TIOCSETA -) - -// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. -// unlockpt should be called before opening the slave side of a pty. -func unlockpt(f *os.File) error { - fd := C.int(f.Fd()) - if _, err := C.unlockpt(fd); err != nil { - C.close(fd) - return fmt.Errorf("unlockpt: %w", err) - } - return nil -} - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN) - if err != nil { - return "", err - } - return fmt.Sprintf("/dev/pts/%d", n), nil -} diff --git a/vendor/github.com/containerd/console/tc_freebsd_nocgo.go b/vendor/github.com/containerd/console/tc_freebsd_nocgo.go deleted file mode 100644 index 18a9b9c..0000000 --- a/vendor/github.com/containerd/console/tc_freebsd_nocgo.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build freebsd && !cgo -// +build freebsd,!cgo - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "fmt" - "os" - - "golang.org/x/sys/unix" -) - -const ( - cmdTcGet = unix.TIOCGETA - cmdTcSet = unix.TIOCSETA -) - -// -// Implementing the functions below requires cgo support. Non-cgo stubs -// versions are defined below to enable cross-compilation of source code -// that depends on these functions, but the resultant cross-compiled -// binaries cannot actually be used. If the stub function(s) below are -// actually invoked they will display an error message and cause the -// calling process to exit. -// - -// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. -// unlockpt should be called before opening the slave side of a pty. -func unlockpt(f *os.File) error { - panic("unlockpt() support requires cgo.") -} - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN) - if err != nil { - return "", err - } - return fmt.Sprintf("/dev/pts/%d", n), nil -} diff --git a/vendor/github.com/containerd/console/tc_linux.go b/vendor/github.com/containerd/console/tc_linux.go deleted file mode 100644 index 7d552ea..0000000 --- a/vendor/github.com/containerd/console/tc_linux.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "fmt" - "os" - "unsafe" - - "golang.org/x/sys/unix" -) - -const ( - cmdTcGet = unix.TCGETS - cmdTcSet = unix.TCSETS -) - -// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. -// unlockpt should be called before opening the slave side of a pty. -func unlockpt(f *os.File) error { - var u int32 - // XXX do not use unix.IoctlSetPointerInt here, see commit dbd69c59b81. - if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 { - return err - } - return nil -} - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - var u uint32 - // XXX do not use unix.IoctlGetInt here, see commit dbd69c59b81. - if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 { - return "", err - } - return fmt.Sprintf("/dev/pts/%d", u), nil -} diff --git a/vendor/github.com/containerd/console/tc_netbsd.go b/vendor/github.com/containerd/console/tc_netbsd.go deleted file mode 100644 index 71227ae..0000000 --- a/vendor/github.com/containerd/console/tc_netbsd.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "bytes" - "os" - - "golang.org/x/sys/unix" -) - -const ( - cmdTcGet = unix.TIOCGETA - cmdTcSet = unix.TIOCSETA -) - -// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. -// unlockpt should be called before opening the slave side of a pty. -// This does not exist on NetBSD, it does not allocate controlling terminals on open -func unlockpt(f *os.File) error { - return nil -} - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - ptm, err := unix.IoctlGetPtmget(int(f.Fd()), unix.TIOCPTSNAME) - if err != nil { - return "", err - } - return string(ptm.Sn[:bytes.IndexByte(ptm.Sn[:], 0)]), nil -} diff --git a/vendor/github.com/containerd/console/tc_openbsd_cgo.go b/vendor/github.com/containerd/console/tc_openbsd_cgo.go deleted file mode 100644 index 0e76f6c..0000000 --- a/vendor/github.com/containerd/console/tc_openbsd_cgo.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build openbsd && cgo -// +build openbsd,cgo - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "os" - - "golang.org/x/sys/unix" -) - -//#include -import "C" - -const ( - cmdTcGet = unix.TIOCGETA - cmdTcSet = unix.TIOCSETA -) - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - ptspath, err := C.ptsname(C.int(f.Fd())) - if err != nil { - return "", err - } - return C.GoString(ptspath), nil -} - -// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. -// unlockpt should be called before opening the slave side of a pty. -func unlockpt(f *os.File) error { - if _, err := C.grantpt(C.int(f.Fd())); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/containerd/console/tc_openbsd_nocgo.go b/vendor/github.com/containerd/console/tc_openbsd_nocgo.go deleted file mode 100644 index dca9241..0000000 --- a/vendor/github.com/containerd/console/tc_openbsd_nocgo.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build openbsd && !cgo -// +build openbsd,!cgo - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -// -// Implementing the functions below requires cgo support. Non-cgo stubs -// versions are defined below to enable cross-compilation of source code -// that depends on these functions, but the resultant cross-compiled -// binaries cannot actually be used. If the stub function(s) below are -// actually invoked they will display an error message and cause the -// calling process to exit. -// - -package console - -import ( - "os" - - "golang.org/x/sys/unix" -) - -const ( - cmdTcGet = unix.TIOCGETA - cmdTcSet = unix.TIOCSETA -) - -func ptsname(f *os.File) (string, error) { - panic("ptsname() support requires cgo.") -} - -func unlockpt(f *os.File) error { - panic("unlockpt() support requires cgo.") -} diff --git a/vendor/github.com/containerd/console/tc_unix.go b/vendor/github.com/containerd/console/tc_unix.go deleted file mode 100644 index f5053b2..0000000 --- a/vendor/github.com/containerd/console/tc_unix.go +++ /dev/null @@ -1,92 +0,0 @@ -//go:build darwin || freebsd || linux || netbsd || openbsd || zos -// +build darwin freebsd linux netbsd openbsd zos - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "golang.org/x/sys/unix" -) - -func tcget(fd uintptr, p *unix.Termios) error { - termios, err := unix.IoctlGetTermios(int(fd), cmdTcGet) - if err != nil { - return err - } - *p = *termios - return nil -} - -func tcset(fd uintptr, p *unix.Termios) error { - return unix.IoctlSetTermios(int(fd), cmdTcSet, p) -} - -func tcgwinsz(fd uintptr) (WinSize, error) { - var ws WinSize - - uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) - if err != nil { - return ws, err - } - - // Translate from unix.Winsize to console.WinSize - ws.Height = uws.Row - ws.Width = uws.Col - ws.x = uws.Xpixel - ws.y = uws.Ypixel - return ws, nil -} - -func tcswinsz(fd uintptr, ws WinSize) error { - // Translate from console.WinSize to unix.Winsize - - var uws unix.Winsize - uws.Row = ws.Height - uws.Col = ws.Width - uws.Xpixel = ws.x - uws.Ypixel = ws.y - - return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &uws) -} - -func setONLCR(fd uintptr, enable bool) error { - var termios unix.Termios - if err := tcget(fd, &termios); err != nil { - return err - } - if enable { - // Set +onlcr so we can act like a real terminal - termios.Oflag |= unix.ONLCR - } else { - // Set -onlcr so we don't have to deal with \r. - termios.Oflag &^= unix.ONLCR - } - return tcset(fd, &termios) -} - -func cfmakeraw(t unix.Termios) unix.Termios { - t.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) - t.Oflag &^= unix.OPOST - t.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) - t.Cflag &^= (unix.CSIZE | unix.PARENB) - t.Cflag &^= unix.CS8 - t.Cc[unix.VMIN] = 1 - t.Cc[unix.VTIME] = 0 - - return t -} diff --git a/vendor/github.com/containerd/console/tc_zos.go b/vendor/github.com/containerd/console/tc_zos.go deleted file mode 100644 index fc90ba5..0000000 --- a/vendor/github.com/containerd/console/tc_zos.go +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package console - -import ( - "os" - "strings" - - "golang.org/x/sys/unix" -) - -const ( - cmdTcGet = unix.TCGETS - cmdTcSet = unix.TCSETS -) - -// unlockpt is a no-op on zos. -func unlockpt(_ *os.File) error { - return nil -} - -// ptsname retrieves the name of the first available pts for the given master. -func ptsname(f *os.File) (string, error) { - return "/dev/ttyp" + strings.TrimPrefix(f.Name(), "/dev/ptyp"), nil -} diff --git a/vendor/github.com/hajimehoshi/oto/.clang-format b/vendor/github.com/ebitengine/oto/v3/.clang-format similarity index 100% rename from vendor/github.com/hajimehoshi/oto/.clang-format rename to vendor/github.com/ebitengine/oto/v3/.clang-format diff --git a/vendor/github.com/ebitengine/oto/v3/.gitattributes b/vendor/github.com/ebitengine/oto/v3/.gitattributes new file mode 100644 index 0000000..8d7d19c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/.gitattributes @@ -0,0 +1 @@ +internal/oboe/** linguist-vendored \ No newline at end of file diff --git a/vendor/github.com/hajimehoshi/oto/.gitignore b/vendor/github.com/ebitengine/oto/v3/.gitignore similarity index 100% rename from vendor/github.com/hajimehoshi/oto/.gitignore rename to vendor/github.com/ebitengine/oto/v3/.gitignore diff --git a/vendor/github.com/hajimehoshi/oto/LICENSE b/vendor/github.com/ebitengine/oto/v3/LICENSE similarity index 100% rename from vendor/github.com/hajimehoshi/oto/LICENSE rename to vendor/github.com/ebitengine/oto/v3/LICENSE diff --git a/vendor/github.com/ebitengine/oto/v3/README.md b/vendor/github.com/ebitengine/oto/v3/README.md new file mode 100644 index 0000000..317189f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/README.md @@ -0,0 +1,234 @@ +# Oto (v3) + +[![Go Reference](https://pkg.go.dev/badge/github.com/ebitengine/oto/v3.svg)](https://pkg.go.dev/github.com/ebitengine/oto/v3) +[![Build Status](https://github.com/ebitengine/oto/actions/workflows/test.yml/badge.svg)](https://github.com/ebitengine/oto/actions?query=workflow%3Atest) + +A low-level library to play sound. + +- [Oto (v3)](#oto-v3) + - [Platforms](#platforms) + - [Prerequisite](#prerequisite) + - [macOS](#macos) + - [iOS](#ios) + - [Linux](#linux) + - [FreeBSD, OpenBSD](#freebsd-openbsd) + - [Usage](#usage) + - [Playing sounds from memory](#playing-sounds-from-memory) + - [Playing sounds by file streaming](#playing-sounds-by-file-streaming) + - [Advanced usage](#advanced-usage) + - [Crosscompiling](#crosscompiling) + +## Platforms + +- Windows (no Cgo required!) +- macOS (no Cgo required!) +- Linux +- FreeBSD +- OpenBSD +- Android +- iOS +- WebAssembly +- Nintendo Switch +- Xbox + +## Prerequisite + +On some platforms you will need a C/C++ compiler in your path that Go can use. + +- iOS: On newer macOS versions type `clang` on your terminal and a dialog with installation instructions will appear if you don't have it + - If you get an error with clang use xcode instead `xcode-select --install` +- Linux and other Unix systems: Should be installed by default, but if not try [GCC](https://gcc.gnu.org/) or [Clang](https://releases.llvm.org/download.html) + +### macOS + +Oto requires `AudioToolbox.framework`, but this is automatically linked. + +### iOS + +Oto requires these frameworks: + +- `AVFoundation.framework` +- `AudioToolbox.framework` + +Add them to "Linked Frameworks and Libraries" on your Xcode project. + +### Linux + +ALSA is required. On Ubuntu or Debian, run this command: + +```sh +apt install libasound2-dev +``` + +On RedHat-based linux distributions, run: + +```sh +dnf install alsa-lib-devel +``` + +In most cases this command must be run by root user or through `sudo` command. + +### FreeBSD, OpenBSD + +BSD systems are not tested well. If ALSA works, Oto should work. + +## Usage + +The two main components of Oto are a `Context` and `Players`. The context handles interactions with +the OS and audio drivers, and as such there can only be **one** context in your program. + +From a context you can create any number of different players, where each player is given an `io.Reader` that +it reads bytes representing sounds from and plays. + +Note that a single `io.Reader` must **not** be used by multiple players. + +### Playing sounds from memory + +The following is an example of loading and playing an MP3 file: + +```go +package main + +import ( + "time" + "os" + + "github.com/ebitengine/oto/v3" + "github.com/hajimehoshi/go-mp3" +) + +func main() { + // Read the mp3 file into memory + fileBytes, err := os.ReadFile("./my-file.mp3") + if err != nil { + panic("reading my-file.mp3 failed: " + err.Error()) + } + + // Convert the pure bytes into a reader object that can be used with the mp3 decoder + fileBytesReader := bytes.NewReader(fileBytes) + + // Decode file + decodedMp3, err := mp3.NewDecoder(fileBytesReader) + if err != nil { + panic("mp3.NewDecoder failed: " + err.Error()) + } + + // Prepare an Oto context (this will use your default audio device) that will + // play all our sounds. Its configuration can't be changed later. + + op := &oto.NewContextOptions{} + + // Usually 44100 or 48000. Other values might cause distortions in Oto + op.SampleRate = 44100 + + // Number of channels (aka locations) to play sounds from. Either 1 or 2. + // 1 is mono sound, and 2 is stereo (most speakers are stereo). + op.ChannelCount = 2 + + // Format of the source. go-mp3's format is signed 16bit integers. + op.Format = oto.FormatSignedInt16LE + + // Remember that you should **not** create more than one context + otoCtx, readyChan, err := oto.NewContext(op) + if err != nil { + panic("oto.NewContext failed: " + err.Error()) + } + // It might take a bit for the hardware audio devices to be ready, so we wait on the channel. + <-readyChan + + // Create a new 'player' that will handle our sound. Paused by default. + player := otoCtx.NewPlayer(decodedMp3) + + // Play starts playing the sound and returns without waiting for it (Play() is async). + player.Play() + + // We can wait for the sound to finish playing using something like this + for player.IsPlaying() { + time.Sleep(time.Millisecond) + } + + // Now that the sound finished playing, we can restart from the beginning (or go to any location in the sound) using seek + // newPos, err := player.(io.Seeker).Seek(0, io.SeekStart) + // if err != nil{ + // panic("player.Seek failed: " + err.Error()) + // } + // println("Player is now at position:", newPos) + // player.Play() + + // If you don't want the player/sound anymore simply close + err = player.Close() + if err != nil { + panic("player.Close failed: " + err.Error()) + } +} +``` + +### Playing sounds by file streaming + +The above example loads the entire file into memory and then plays it. This is great for smaller files +but might be an issue if you are playing a long song since it would take too much memory and too long to load. + +In such cases you might want to stream the file. Luckily this is very simple, just use `os.Open`: + +```go +package main + +import ( + "bytes" + "os" + "time" + + "github.com/hajimehoshi/go-mp3" + "github.com/hajimehoshi/oto/v3" +) + +func main() { + // Open the file for reading. Do NOT close before you finish playing! + file, err := os.Open("./my-file.mp3") + if err != nil { + panic("opening my-file.mp3 failed: " + err.Error()) + } + + // Decode file. This process is done as the file plays so it won't + // load the whole thing into memory. + decodedMp3, err := mp3.NewDecoder(file) + if err != nil { + panic("mp3.NewDecoder failed: " + err.Error()) + } + + // Rest is the same... + + // Close file only after you finish playing + file.Close() +} +``` + +The only thing to note about streaming is that the *file* object must be kept alive, otherwise +you might just play static. + +To keep it alive not only must you be careful about when you close it, but you might need to keep a reference +to the original file object alive (by for example keeping it in a struct). + +### Advanced usage + +Players have their own internal audio data buffer, so while for example 200 bytes have been read from the `io.Reader` that +doesn't mean they were all played from the audio device. + +Data is moved from io.Reader->internal buffer->audio device, and when the internal buffer moves data to the audio device +is not guaranteed, so there might be a small delay. The amount of data in the buffer can be retrieved +using `Player.UnplayedBufferSize()`. + +The size of the underlying buffer of a player can also be set by type-asserting the player object: + +```go +myPlayer.(oto.BufferSizeSetter).SetBufferSize(newBufferSize) +``` + +This works because players implement a `Player` interface and a `BufferSizeSetter` interface. + +## Crosscompiling + +Crosscompiling to macOS or Windows is as easy as setting `GOOS=darwin` or `GOOS=windows`, respectively. + +To crosscompile for other platforms, make sure the libraries for the target architecture are installed, and set +`CGO_ENABLED=1` as Go disables [Cgo](https://golang.org/cmd/cgo/#hdr-Using_cgo_with_the_go_command) on crosscompiles by default. diff --git a/vendor/github.com/ebitengine/oto/v3/api_darwin.go b/vendor/github.com/ebitengine/oto/v3/api_darwin.go new file mode 100644 index 0000000..795bf84 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/api_darwin.go @@ -0,0 +1,95 @@ +// Copyright 2022 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "unsafe" + + "github.com/ebitengine/purego" +) + +const ( + avAudioSessionErrorCodeCannotStartPlaying = 0x21706c61 // '!pla' + avAudioSessionErrorCodeCannotInterruptOthers = 0x21696e74 // '!int' + avAudioSessionErrorCodeSiriIsRecording = 0x73697269 // 'siri' +) + +const ( + kAudioFormatLinearPCM = 0x6C70636D //'lpcm' +) + +const ( + kAudioFormatFlagIsFloat = 1 << 0 // 0x1 +) + +type _AudioStreamBasicDescription struct { + mSampleRate float64 + mFormatID uint32 + mFormatFlags uint32 + mBytesPerPacket uint32 + mFramesPerPacket uint32 + mBytesPerFrame uint32 + mChannelsPerFrame uint32 + mBitsPerChannel uint32 + mReserved uint32 +} + +type _AudioQueueRef uintptr + +type _AudioTimeStamp uintptr + +type _AudioStreamPacketDescription struct { + mStartOffset int64 + mVariableFramesInPacket uint32 + mDataByteSize uint32 +} + +type _AudioQueueBufferRef *_AudioQueueBuffer + +type _AudioQueueBuffer struct { + mAudioDataBytesCapacity uint32 + mAudioData uintptr // void* + mAudioDataByteSize uint32 + mUserData uintptr // void* + + mPacketDescriptionCapacity uint32 + mPacketDescriptions *_AudioStreamPacketDescription + mPacketDescriptionCount uint32 +} + +type _AudioQueueOutputCallback func(inUserData unsafe.Pointer, inAQ _AudioQueueRef, inBuffer _AudioQueueBufferRef) + +func initializeAPI() error { + toolbox, err := purego.Dlopen("/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox", purego.RTLD_LAZY|purego.RTLD_GLOBAL) + if err != nil { + return err + } + purego.RegisterLibFunc(&_AudioQueueNewOutput, toolbox, "AudioQueueNewOutput") + purego.RegisterLibFunc(&_AudioQueueAllocateBuffer, toolbox, "AudioQueueAllocateBuffer") + purego.RegisterLibFunc(&_AudioQueueEnqueueBuffer, toolbox, "AudioQueueEnqueueBuffer") + purego.RegisterLibFunc(&_AudioQueueStart, toolbox, "AudioQueueStart") + purego.RegisterLibFunc(&_AudioQueuePause, toolbox, "AudioQueuePause") + return nil +} + +var _AudioQueueNewOutput func(inFormat *_AudioStreamBasicDescription, inCallbackProc _AudioQueueOutputCallback, inUserData unsafe.Pointer, inCallbackRunLoop uintptr, inCallbackRunLoopMod uintptr, inFlags uint32, outAQ *_AudioQueueRef) uintptr + +var _AudioQueueAllocateBuffer func(inAQ _AudioQueueRef, inBufferByteSize uint32, outBuffer *_AudioQueueBufferRef) uintptr + +var _AudioQueueEnqueueBuffer func(inAQ _AudioQueueRef, inBuffer _AudioQueueBufferRef, inNumPacketDescs uint32, inPackets []_AudioStreamPacketDescription) uintptr + +var _AudioQueueStart func(inAQ _AudioQueueRef, inStartTime *_AudioTimeStamp) uintptr + +var _AudioQueuePause func(inAQ _AudioQueueRef) uintptr diff --git a/vendor/github.com/ebitengine/oto/v3/api_wasapi_windows.go b/vendor/github.com/ebitengine/oto/v3/api_wasapi_windows.go new file mode 100644 index 0000000..b5a051a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/api_wasapi_windows.go @@ -0,0 +1,479 @@ +// Copyright 2022 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "fmt" + "runtime" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + ole32 = windows.NewLazySystemDLL("ole32") +) + +var ( + procCoCreateInstance = ole32.NewProc("CoCreateInstance") +) + +type _REFERENCE_TIME int64 + +var ( + uuidIAudioClient2 = windows.GUID{0x726778cd, 0xf60a, 0x4eda, [...]byte{0x82, 0xde, 0xe4, 0x76, 0x10, 0xcd, 0x78, 0xaa}} + uuidIAudioRenderClient = windows.GUID{0xf294acfc, 0x3146, 0x4483, [...]byte{0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2}} + uuidIMMDeviceEnumerator = windows.GUID{0xa95664d2, 0x9614, 0x4f35, [...]byte{0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6}} + uuidMMDeviceEnumerator = windows.GUID{0xbcde0395, 0xe52f, 0x467c, [...]byte{0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e}} +) + +const ( + _AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM = 0x80000000 + _AUDCLNT_STREAMFLAGS_EVENTCALLBACK = 0x00040000 + _AUDCLNT_STREAMFLAGS_NOPERSIST = 0x00080000 + _COINIT_APARTMENTTHREADED = 0x2 + _COINIT_MULTITHREADED = 0 + _REFTIMES_PER_SEC = 10000000 + _SPEAKER_FRONT_CENTER = 0x4 + _SPEAKER_FRONT_LEFT = 0x1 + _SPEAKER_FRONT_RIGHT = 0x2 + _WAVE_FORMAT_EXTENSIBLE = 0xfffe +) + +var ( + _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = windows.GUID{0x00000003, 0x0000, 0x0010, [...]byte{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} + _KSDATAFORMAT_SUBTYPE_PCM = windows.GUID{0x00000001, 0x0000, 0x0010, [...]byte{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} +) + +type _AUDCLNT_ERR uint32 + +const ( + _AUDCLNT_E_DEVICE_INVALIDATED _AUDCLNT_ERR = 0x88890004 + _AUDCLNT_E_NOT_INITIALIZED _AUDCLNT_ERR = 0x88890001 + _AUDCLNT_E_RESOURCES_INVALIDATED _AUDCLNT_ERR = 0x88890026 +) + +func isAudclntErr(hresult uint32) bool { + return hresult&0xffff0000 == (1<<31)|(windows.FACILITY_AUDCLNT<<16) +} + +func (e _AUDCLNT_ERR) Error() string { + switch e { + case _AUDCLNT_E_DEVICE_INVALIDATED: + return "AUDCLNT_E_DEVICE_INVALIDATED" + case _AUDCLNT_E_RESOURCES_INVALIDATED: + return "AUDCLNT_E_RESOURCES_INVALIDATED" + default: + return fmt.Sprintf("AUDCLNT_ERR(%d)", e) + } +} + +type _AUDCLNT_SHAREMODE int32 + +const ( + _AUDCLNT_SHAREMODE_SHARED _AUDCLNT_SHAREMODE = 0 + _AUDCLNT_SHAREMODE_EXCLUSIVE _AUDCLNT_SHAREMODE = 1 +) + +type _AUDCLNT_STREAMOPTIONS int32 + +const ( + _AUDCLNT_STREAMOPTIONS_NONE _AUDCLNT_STREAMOPTIONS = 0x0 + _AUDCLNT_STREAMOPTIONS_RAW _AUDCLNT_STREAMOPTIONS = 0x1 + _AUDCLNT_STREAMOPTIONS_MATCH_FORMAT _AUDCLNT_STREAMOPTIONS = 0x2 + _AUDCLNT_STREAMOPTIONS_AMBISONICS _AUDCLNT_STREAMOPTIONS = 0x4 +) + +type _AUDIO_STREAM_CATEGORY int32 + +const ( + _AudioCategory_Other _AUDIO_STREAM_CATEGORY = 0 + _AudioCategory_ForegroundOnlyMedia _AUDIO_STREAM_CATEGORY = 1 + _AudioCategory_BackgroundCapableMedia _AUDIO_STREAM_CATEGORY = 2 + _AudioCategory_Communications _AUDIO_STREAM_CATEGORY = 3 + _AudioCategory_Alerts _AUDIO_STREAM_CATEGORY = 4 + _AudioCategory_SoundEffects _AUDIO_STREAM_CATEGORY = 5 + _AudioCategory_GameEffects _AUDIO_STREAM_CATEGORY = 6 + _AudioCategory_GameMedia _AUDIO_STREAM_CATEGORY = 7 + _AudioCategory_GameChat _AUDIO_STREAM_CATEGORY = 8 + _AudioCategory_Speech _AUDIO_STREAM_CATEGORY = 9 + _AudioCategory_Movie _AUDIO_STREAM_CATEGORY = 10 + _AudioCategory_Media _AUDIO_STREAM_CATEGORY = 11 +) + +type _CLSCTX int32 + +const ( + _CLSCTX_INPROC_SERVER _CLSCTX = 0x00000001 + _CLSCTX_INPROC_HANDLER _CLSCTX = 0x00000002 + _CLSCTX_LOCAL_SERVER _CLSCTX = 0x00000004 + _CLSCTX_REMOTE_SERVER _CLSCTX = 0x00000010 + _CLSCTX_ALL = _CLSCTX_INPROC_SERVER | _CLSCTX_INPROC_HANDLER | _CLSCTX_LOCAL_SERVER | _CLSCTX_REMOTE_SERVER +) + +type _EDataFlow int32 + +const ( + eRender _EDataFlow = 0 +) + +type _ERole int32 + +const ( + eConsole _ERole = 0 +) + +type _WIN32_ERR uint32 + +const ( + _E_NOTFOUND _WIN32_ERR = 0x80070490 +) + +func isWin32Err(hresult uint32) bool { + return hresult&0xffff0000 == (1<<31)|(windows.FACILITY_WIN32<<16) +} + +func (e _WIN32_ERR) Error() string { + switch e { + case _E_NOTFOUND: + return "E_NOTFOUND" + default: + return fmt.Sprintf("HRESULT(%d)", e) + } +} + +type _AudioClientProperties struct { + cbSize uint32 + bIsOffload int32 + eCategory _AUDIO_STREAM_CATEGORY + Options _AUDCLNT_STREAMOPTIONS +} + +type _PROPVARIANT struct { + // TODO: Implmeent this +} + +type _WAVEFORMATEXTENSIBLE struct { + wFormatTag uint16 + nChannels uint16 + nSamplesPerSec uint32 + nAvgBytesPerSec uint32 + nBlockAlign uint16 + wBitsPerSample uint16 + cbSize uint16 + Samples uint16 // union + dwChannelMask uint32 + SubFormat windows.GUID +} + +func _CoCreateInstance(rclsid *windows.GUID, pUnkOuter unsafe.Pointer, dwClsContext uint32, riid *windows.GUID) (unsafe.Pointer, error) { + var v unsafe.Pointer + r, _, _ := procCoCreateInstance.Call(uintptr(unsafe.Pointer(rclsid)), uintptr(pUnkOuter), uintptr(dwClsContext), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(&v))) + runtime.KeepAlive(rclsid) + runtime.KeepAlive(riid) + if uint32(r) != uint32(windows.S_OK) { + return nil, fmt.Errorf("oto: CoCreateInstance failed: HRESULT(%d)", uint32(r)) + } + return v, nil +} + +type _IAudioClient2 struct { + vtbl *_IAudioClient2_Vtbl +} + +type _IAudioClient2_Vtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr + + Initialize uintptr + GetBufferSize uintptr + GetStreamLatency uintptr + GetCurrentPadding uintptr + IsFormatSupported uintptr + GetMixFormat uintptr + GetDevicePeriod uintptr + Start uintptr + Stop uintptr + Reset uintptr + SetEventHandle uintptr + GetService uintptr + IsOffloadCapable uintptr + SetClientProperties uintptr + GetBufferSizeLimits uintptr +} + +func (i *_IAudioClient2) GetBufferSize() (uint32, error) { + var numBufferFrames uint32 + r, _, _ := syscall.Syscall(i.vtbl.GetBufferSize, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&numBufferFrames)), 0) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return 0, fmt.Errorf("oto: IAudioClient2::GetBufferSize failed: %w", _AUDCLNT_ERR(r)) + } + return 0, fmt.Errorf("oto: IAudioClient2::GetBufferSize failed: HRESULT(%d)", uint32(r)) + } + return numBufferFrames, nil +} + +func (i *_IAudioClient2) GetCurrentPadding() (uint32, error) { + var numPaddingFrames uint32 + r, _, _ := syscall.Syscall(i.vtbl.GetCurrentPadding, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&numPaddingFrames)), 0) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return 0, fmt.Errorf("oto: IAudioClient2::GetCurrentPadding failed: %w", _AUDCLNT_ERR(r)) + } + return 0, fmt.Errorf("oto: IAudioClient2::GetCurrentPadding failed: HRESULT(%d)", uint32(r)) + } + return numPaddingFrames, nil +} + +func (i *_IAudioClient2) GetDevicePeriod() (_REFERENCE_TIME, _REFERENCE_TIME, error) { + var defaultDevicePeriod _REFERENCE_TIME + var minimumDevicePeriod _REFERENCE_TIME + r, _, _ := syscall.Syscall(i.vtbl.GetDevicePeriod, 3, uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(&defaultDevicePeriod)), uintptr(unsafe.Pointer(&minimumDevicePeriod))) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return 0, 0, fmt.Errorf("oto: IAudioClient2::GetDevicePeriod failed: %w", _AUDCLNT_ERR(r)) + } + return 0, 0, fmt.Errorf("oto: IAudioClient2::GetDevicePeriod failed: HRESULT(%d)", uint32(r)) + } + return defaultDevicePeriod, minimumDevicePeriod, nil +} + +func (i *_IAudioClient2) GetService(riid *windows.GUID) (unsafe.Pointer, error) { + var v unsafe.Pointer + r, _, _ := syscall.Syscall(i.vtbl.GetService, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(&v))) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return nil, fmt.Errorf("oto: IAudioClient2::GetService failed: %w", _AUDCLNT_ERR(r)) + } + return nil, fmt.Errorf("oto: IAudioClient2::GetService failed: HRESULT(%d)", uint32(r)) + } + return v, nil +} + +func (i *_IAudioClient2) Initialize(shareMode _AUDCLNT_SHAREMODE, streamFlags uint32, hnsBufferDuration _REFERENCE_TIME, hnsPeriodicity _REFERENCE_TIME, pFormat *_WAVEFORMATEXTENSIBLE, audioSessionGuid *windows.GUID) error { + var r uintptr + if unsafe.Sizeof(uintptr(0)) == 8 { + // 64bits + r, _, _ = syscall.Syscall9(i.vtbl.Initialize, 7, uintptr(unsafe.Pointer(i)), + uintptr(shareMode), uintptr(streamFlags), uintptr(hnsBufferDuration), + uintptr(hnsPeriodicity), uintptr(unsafe.Pointer(pFormat)), uintptr(unsafe.Pointer(audioSessionGuid)), + 0, 0) + } else { + // 32bits + r, _, _ = syscall.Syscall9(i.vtbl.Initialize, 9, uintptr(unsafe.Pointer(i)), + uintptr(shareMode), uintptr(streamFlags), uintptr(hnsBufferDuration), + uintptr(hnsBufferDuration>>32), uintptr(hnsPeriodicity), uintptr(hnsPeriodicity>>32), + uintptr(unsafe.Pointer(pFormat)), uintptr(unsafe.Pointer(audioSessionGuid))) + } + runtime.KeepAlive(pFormat) + runtime.KeepAlive(audioSessionGuid) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return fmt.Errorf("oto: IAudioClient2::Initialize failed: %w", _AUDCLNT_ERR(r)) + } + return fmt.Errorf("oto: IAudioClient2::Initialize failed: HRESULT(%d)", uint32(r)) + } + return nil +} + +func (i *_IAudioClient2) IsFormatSupported(shareMode _AUDCLNT_SHAREMODE, pFormat *_WAVEFORMATEXTENSIBLE) (*_WAVEFORMATEXTENSIBLE, error) { + var closestMatch *_WAVEFORMATEXTENSIBLE + r, _, _ := syscall.Syscall6(i.vtbl.IsFormatSupported, 4, uintptr(unsafe.Pointer(i)), + uintptr(shareMode), uintptr(unsafe.Pointer(pFormat)), uintptr(unsafe.Pointer(&closestMatch)), + 0, 0) + if uint32(r) != uint32(windows.S_OK) { + if uint32(r) == uint32(windows.S_FALSE) { + var r _WAVEFORMATEXTENSIBLE + if closestMatch != nil { + r = *closestMatch + windows.CoTaskMemFree(unsafe.Pointer(closestMatch)) + } + return &r, nil + } + if isAudclntErr(uint32(r)) { + return nil, fmt.Errorf("oto: IAudioClient2::IsFormatSupported failed: %w", _AUDCLNT_ERR(r)) + } + return nil, fmt.Errorf("oto: IAudioClient2::IsFormatSupported failed: HRESULT(%d)", uint32(r)) + } + return nil, nil +} + +func (i *_IAudioClient2) Release() uint32 { + r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0) + return uint32(r) +} + +func (i *_IAudioClient2) SetClientProperties(pProperties *_AudioClientProperties) error { + r, _, _ := syscall.Syscall(i.vtbl.SetClientProperties, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(pProperties)), 0) + runtime.KeepAlive(pProperties) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return fmt.Errorf("oto: IAudioClient2::SetClientProperties failed: %w", _AUDCLNT_ERR(r)) + } + return fmt.Errorf("oto: IAudioClient2::SetClientProperties failed: HRESULT(%d)", uint32(r)) + } + return nil +} + +func (i *_IAudioClient2) SetEventHandle(eventHandle windows.Handle) error { + r, _, _ := syscall.Syscall(i.vtbl.SetEventHandle, 2, uintptr(unsafe.Pointer(i)), uintptr(eventHandle), 0) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return fmt.Errorf("oto: IAudioClient2::SetEventHandle failed: %w", _AUDCLNT_ERR(r)) + } + return fmt.Errorf("oto: IAudioClient2::SetEventHandle failed: HRESULT(%d)", uint32(r)) + } + return nil +} + +func (i *_IAudioClient2) Start() error { + r, _, _ := syscall.Syscall(i.vtbl.Start, 1, uintptr(unsafe.Pointer(i)), 0, 0) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return fmt.Errorf("oto: IAudioClient2::Start failed: %w", _AUDCLNT_ERR(r)) + } + return fmt.Errorf("oto: IAudioClient2::Start failed: HRESULT(%d)", uint32(r)) + } + return nil +} + +func (i *_IAudioClient2) Stop() (bool, error) { + r, _, _ := syscall.Syscall(i.vtbl.Stop, 1, uintptr(unsafe.Pointer(i)), 0, 0) + if uint32(r) != uint32(windows.S_OK) && uint32(r) != uint32(windows.S_FALSE) { + if isAudclntErr(uint32(r)) { + return false, fmt.Errorf("oto: IAudioClient2::Stop failed: %w", _AUDCLNT_ERR(r)) + } + return false, fmt.Errorf("oto: IAudioClient2::Stop failed: HRESULT(%d)", uint32(r)) + } + return uint32(r) == uint32(windows.S_OK), nil +} + +type _IAudioRenderClient struct { + vtbl *_IAudioRenderClient_Vtbl +} + +type _IAudioRenderClient_Vtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr + + GetBuffer uintptr + ReleaseBuffer uintptr +} + +func (i *_IAudioRenderClient) GetBuffer(numFramesRequested uint32) (*byte, error) { + var data *byte + r, _, _ := syscall.Syscall(i.vtbl.GetBuffer, 3, uintptr(unsafe.Pointer(i)), uintptr(numFramesRequested), uintptr(unsafe.Pointer(&data))) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return nil, fmt.Errorf("oto: IAudioRenderClient::GetBuffer failed: %w", _AUDCLNT_ERR(r)) + } + return nil, fmt.Errorf("oto: IAudioRenderClient::GetBuffer failed: HRESULT(%d)", uint32(r)) + } + return data, nil +} + +func (i *_IAudioRenderClient) Release() uint32 { + r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0) + return uint32(r) +} + +func (i *_IAudioRenderClient) ReleaseBuffer(numFramesWritten uint32, dwFlags uint32) error { + r, _, _ := syscall.Syscall(i.vtbl.ReleaseBuffer, 3, uintptr(unsafe.Pointer(i)), uintptr(numFramesWritten), uintptr(dwFlags)) + if uint32(r) != uint32(windows.S_OK) { + if isAudclntErr(uint32(r)) { + return fmt.Errorf("oto: IAudioRenderClient::ReleaseBuffer failed: %w", _AUDCLNT_ERR(r)) + } + return fmt.Errorf("oto: IAudioRenderClient::ReleaseBuffer failed: HRESULT(%d)", uint32(r)) + } + return nil +} + +type _IMMDevice struct { + vtbl *_IMMDevice_Vtbl +} + +type _IMMDevice_Vtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr + + Activate uintptr + OpenPropertyStore uintptr + GetId uintptr + GetState uintptr +} + +func (i *_IMMDevice) Activate(iid *windows.GUID, dwClsCtx uint32, pActivationParams *_PROPVARIANT) (unsafe.Pointer, error) { + var v unsafe.Pointer + r, _, _ := syscall.Syscall6(i.vtbl.Activate, 5, uintptr(unsafe.Pointer(i)), + uintptr(unsafe.Pointer(iid)), uintptr(dwClsCtx), uintptr(unsafe.Pointer(pActivationParams)), uintptr(unsafe.Pointer(&v)), 0) + runtime.KeepAlive(iid) + runtime.KeepAlive(pActivationParams) + if uint32(r) != uint32(windows.S_OK) { + return nil, fmt.Errorf("oto: IMMDevice::Activate failed: HRESULT(%d)", uint32(r)) + } + return v, nil +} + +func (i *_IMMDevice) GetId() (string, error) { + var strId *uint16 + r, _, _ := syscall.Syscall(i.vtbl.GetId, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&strId)), 0) + if uint32(r) != uint32(windows.S_OK) { + return "", fmt.Errorf("oto: IMMDevice::GetId failed: HRESULT(%d)", uint32(r)) + } + return windows.UTF16PtrToString(strId), nil +} + +func (i *_IMMDevice) Release() { + syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0) +} + +type _IMMDeviceEnumerator struct { + vtbl *_IMMDeviceEnumerator_Vtbl +} + +type _IMMDeviceEnumerator_Vtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr + + EnumAudioEndpoints uintptr + GetDefaultAudioEndpoint uintptr + GetDevice uintptr + RegisterEndpointNotificationCallback uintptr + UnregisterEndpointNotificationCallback uintptr +} + +func (i *_IMMDeviceEnumerator) GetDefaultAudioEndPoint(dataFlow _EDataFlow, role _ERole) (*_IMMDevice, error) { + var endPoint *_IMMDevice + r, _, _ := syscall.Syscall6(i.vtbl.GetDefaultAudioEndpoint, 4, uintptr(unsafe.Pointer(i)), + uintptr(dataFlow), uintptr(role), uintptr(unsafe.Pointer(&endPoint)), 0, 0) + if uint32(r) != uint32(windows.S_OK) { + if isWin32Err(uint32(r)) { + return nil, fmt.Errorf("oto: IMMDeviceEnumerator::GetDefaultAudioEndPoint failed: %w", _E_NOTFOUND) + } + return nil, fmt.Errorf("oto: IMMDeviceEnumerator::GetDefaultAudioEndPoint failed: HRESULT(%d)", uint32(r)) + } + return endPoint, nil +} + +func (i *_IMMDeviceEnumerator) Release() { + syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0) +} diff --git a/vendor/github.com/ebitengine/oto/v3/api_winmm_windows.go b/vendor/github.com/ebitengine/oto/v3/api_winmm_windows.go new file mode 100644 index 0000000..821299c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/api_winmm_windows.go @@ -0,0 +1,174 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "fmt" + "runtime" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + winmm = windows.NewLazySystemDLL("winmm") +) + +var ( + procWaveOutOpen = winmm.NewProc("waveOutOpen") + procWaveOutClose = winmm.NewProc("waveOutClose") + procWaveOutPrepareHeader = winmm.NewProc("waveOutPrepareHeader") + procWaveOutUnprepareHeader = winmm.NewProc("waveOutUnprepareHeader") + procWaveOutWrite = winmm.NewProc("waveOutWrite") +) + +type _WAVEHDR struct { + lpData uintptr + dwBufferLength uint32 + dwBytesRecorded uint32 + dwUser uintptr + dwFlags uint32 + dwLoops uint32 + lpNext uintptr + reserved uintptr +} + +type _WAVEFORMATEX struct { + wFormatTag uint16 + nChannels uint16 + nSamplesPerSec uint32 + nAvgBytesPerSec uint32 + nBlockAlign uint16 + wBitsPerSample uint16 + cbSize uint16 +} + +const ( + _WAVE_FORMAT_IEEE_FLOAT = 3 + _WHDR_INQUEUE = 16 +) + +type _MMRESULT uint + +const ( + _MMSYSERR_NOERROR _MMRESULT = 0 + _MMSYSERR_ERROR _MMRESULT = 1 + _MMSYSERR_BADDEVICEID _MMRESULT = 2 + _MMSYSERR_ALLOCATED _MMRESULT = 4 + _MMSYSERR_INVALIDHANDLE _MMRESULT = 5 + _MMSYSERR_NODRIVER _MMRESULT = 6 + _MMSYSERR_NOMEM _MMRESULT = 7 + _WAVERR_BADFORMAT _MMRESULT = 32 + _WAVERR_STILLPLAYING _MMRESULT = 33 + _WAVERR_UNPREPARED _MMRESULT = 34 + _WAVERR_SYNC _MMRESULT = 35 +) + +func (m _MMRESULT) Error() string { + switch m { + case _MMSYSERR_NOERROR: + return "MMSYSERR_NOERROR" + case _MMSYSERR_ERROR: + return "MMSYSERR_ERROR" + case _MMSYSERR_BADDEVICEID: + return "MMSYSERR_BADDEVICEID" + case _MMSYSERR_ALLOCATED: + return "MMSYSERR_ALLOCATED" + case _MMSYSERR_INVALIDHANDLE: + return "MMSYSERR_INVALIDHANDLE" + case _MMSYSERR_NODRIVER: + return "MMSYSERR_NODRIVER" + case _MMSYSERR_NOMEM: + return "MMSYSERR_NOMEM" + case _WAVERR_BADFORMAT: + return "WAVERR_BADFORMAT" + case _WAVERR_STILLPLAYING: + return "WAVERR_STILLPLAYING" + case _WAVERR_UNPREPARED: + return "WAVERR_UNPREPARED" + case _WAVERR_SYNC: + return "WAVERR_SYNC" + } + return fmt.Sprintf("MMRESULT (%d)", m) +} + +func waveOutOpen(f *_WAVEFORMATEX, callback uintptr) (uintptr, error) { + const ( + waveMapper = 0xffffffff + callbackFunction = 0x30000 + ) + var w uintptr + var fdwOpen uintptr + if callback != 0 { + fdwOpen |= callbackFunction + } + r, _, e := procWaveOutOpen.Call(uintptr(unsafe.Pointer(&w)), waveMapper, uintptr(unsafe.Pointer(f)), + callback, 0, fdwOpen) + runtime.KeepAlive(f) + if _MMRESULT(r) != _MMSYSERR_NOERROR { + if e != nil && e != windows.ERROR_SUCCESS { + return 0, fmt.Errorf("oto: waveOutOpen failed: %w", e) + } + return 0, fmt.Errorf("oto: waveOutOpen failed: %w", _MMRESULT(r)) + } + return w, nil +} + +func waveOutClose(hwo uintptr) error { + r, _, e := procWaveOutClose.Call(hwo) + if _MMRESULT(r) != _MMSYSERR_NOERROR { + if e != nil && e != windows.ERROR_SUCCESS { + return fmt.Errorf("oto: waveOutClose failed: %w", e) + } + return fmt.Errorf("oto: waveOutClose failed: %w", _MMRESULT(r)) + } + return nil +} + +func waveOutPrepareHeader(hwo uintptr, pwh *_WAVEHDR) error { + r, _, e := procWaveOutPrepareHeader.Call(hwo, uintptr(unsafe.Pointer(pwh)), unsafe.Sizeof(_WAVEHDR{})) + runtime.KeepAlive(pwh) + if _MMRESULT(r) != _MMSYSERR_NOERROR { + if e != nil && e != windows.ERROR_SUCCESS { + return fmt.Errorf("oto: waveOutPrepareHeader failed: %w", e) + } + return fmt.Errorf("oto: waveOutPrepareHeader failed: %w", _MMRESULT(r)) + } + return nil +} + +func waveOutUnprepareHeader(hwo uintptr, pwh *_WAVEHDR) error { + r, _, e := procWaveOutUnprepareHeader.Call(hwo, uintptr(unsafe.Pointer(pwh)), unsafe.Sizeof(_WAVEHDR{})) + runtime.KeepAlive(pwh) + if _MMRESULT(r) != _MMSYSERR_NOERROR { + if e != nil && e != windows.ERROR_SUCCESS { + return fmt.Errorf("oto: waveOutUnprepareHeader failed: %w", e) + } + return fmt.Errorf("oto: waveOutUnprepareHeader failed: %w", _MMRESULT(r)) + } + return nil +} + +func waveOutWrite(hwo uintptr, pwh *_WAVEHDR) error { + r, _, e := procWaveOutWrite.Call(hwo, uintptr(unsafe.Pointer(pwh)), unsafe.Sizeof(_WAVEHDR{})) + runtime.KeepAlive(pwh) + if _MMRESULT(r) != _MMSYSERR_NOERROR { + if e != nil && e != windows.ERROR_SUCCESS { + return fmt.Errorf("oto: waveOutWrite failed: %w", e) + } + return fmt.Errorf("oto: waveOutWrite failed: %w", _MMRESULT(r)) + } + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/context.go b/vendor/github.com/ebitengine/oto/v3/context.go new file mode 100644 index 0000000..b91ae5c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/context.go @@ -0,0 +1,181 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "fmt" + "io" + "sync" + "time" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +var ( + contextCreated bool + contextCreationMutex sync.Mutex +) + +// Context is the main object in Oto. It interacts with the audio drivers. +// +// To play sound with Oto, first create a context. Then use the context to create +// an arbitrary number of players. Then use the players to play sound. +// +// Creating multiple contexts is NOT supported. +type Context struct { + context *context +} + +// Format is the format of sources. +type Format int + +const ( + // FormatFloat32LE is the format of 32 bits floats little endian. + FormatFloat32LE Format = iota + + // FormatUnsignedInt8 is the format of 8 bits integers. + FormatUnsignedInt8 + + //FormatSignedInt16LE is the format of 16 bits integers little endian. + FormatSignedInt16LE +) + +// NewContextOptions represents options for NewContext. +type NewContextOptions struct { + // SampleRate specifies the number of samples that should be played during one second. + // Usual numbers are 44100 or 48000. One context has only one sample rate. You cannot play multiple audio + // sources with different sample rates at the same time. + SampleRate int + + // ChannelCount specifies the number of channels. One channel is mono playback. Two + // channels are stereo playback. No other values are supported. + ChannelCount int + + // Format specifies the format of sources. + Format Format + + // BufferSize specifies a buffer size in the underlying device. + // + // If 0 is specified, the driver's default buffer size is used. + // Set BufferSize to adjust the buffer size if you want to adjust latency or reduce noises. + // Too big buffer size can increase the latency time. + // On the other hand, too small buffer size can cause glitch noises due to buffer shortage. + BufferSize time.Duration +} + +// NewContext creates a new context with given options. +// A context creates and holds ready-to-use Player objects. +// NewContext returns a context, a channel that is closed when the context is ready, and an error if it exists. +// +// Creating multiple contexts is NOT supported. +func NewContext(options *NewContextOptions) (*Context, chan struct{}, error) { + contextCreationMutex.Lock() + defer contextCreationMutex.Unlock() + + if contextCreated { + return nil, nil, fmt.Errorf("oto: context is already created") + } + contextCreated = true + + var bufferSizeInBytes int + if options.BufferSize != 0 { + // The underying driver always uses 32bit floats. + bytesPerSample := options.ChannelCount * 4 + bytesPerSecond := options.SampleRate * bytesPerSample + bufferSizeInBytes = int(int64(options.BufferSize) * int64(bytesPerSecond) / int64(time.Second)) + bufferSizeInBytes = bufferSizeInBytes / bytesPerSample * bytesPerSample + } + ctx, ready, err := newContext(options.SampleRate, options.ChannelCount, mux.Format(options.Format), bufferSizeInBytes) + if err != nil { + return nil, nil, err + } + return &Context{context: ctx}, ready, nil +} + +// NewPlayer creates a new, ready-to-use Player belonging to the Context. +// It is safe to create multiple players. +// +// The format of r is as follows: +// +// [data] = [sample 1] [sample 2] [sample 3] ... +// [sample *] = [channel 1] [channel 2] ... +// [channel *] = [byte 1] [byte 2] ... +// +// Byte ordering is little endian. +// +// A player has some amount of an underlying buffer. +// Read data from r is queued to the player's underlying buffer. +// The underlying buffer is consumed by its playing. +// Then, r's position and the current playing position don't necessarily match. +// If you want to clear the underlying buffer for some reasons e.g., you want to seek the position of r, +// call the player's Reset function. +// +// You cannot share r by multiple players. +// +// The returned player implements Player, BufferSizeSetter, and io.Seeker. +// You can modify the buffer size of a player by the SetBufferSize function. +// A small buffer size is useful if you want to play a real-time PCM for example. +// Note that the audio quality might be affected if you modify the buffer size. +// +// If r does not implement io.Seeker, the returned player's Seek returns an error. +// +// NewPlayer is concurrent-safe. +// +// All the functions of a Player returned by NewPlayer are concurrent-safe. +func (c *Context) NewPlayer(r io.Reader) *Player { + return &Player{ + player: c.context.mux.NewPlayer(r), + } +} + +// Suspend suspends the entire audio play. +// +// Suspend is concurrent-safe. +func (c *Context) Suspend() error { + return c.context.Suspend() +} + +// Resume resumes the entire audio play, which was suspended by Suspend. +// +// Resume is concurrent-safe. +func (c *Context) Resume() error { + return c.context.Resume() +} + +// Err returns the current error. +// +// Err is concurrent-safe. +func (c *Context) Err() error { + return c.context.Err() +} + +type atomicError struct { + err error + m sync.Mutex +} + +func (a *atomicError) TryStore(err error) { + a.m.Lock() + defer a.m.Unlock() + if a.err == nil { + a.err = err + } +} + +func (a *atomicError) Load() error { + a.m.Lock() + defer a.m.Unlock() + return a.err +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_android.go b/vendor/github.com/ebitengine/oto/v3/driver_android.go new file mode 100644 index 0000000..52e33f5 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_android.go @@ -0,0 +1,49 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "github.com/ebitengine/oto/v3/internal/mux" + "github.com/ebitengine/oto/v3/internal/oboe" +) + +type context struct { + mux *mux.Mux +} + +func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeInBytes int) (*context, chan struct{}, error) { + ready := make(chan struct{}) + close(ready) + + c := &context{ + mux: mux.New(sampleRate, channelCount, format), + } + if err := oboe.Play(sampleRate, channelCount, c.mux.ReadFloat32s, bufferSizeInBytes); err != nil { + return nil, nil, err + } + return c, ready, nil +} + +func (c *context) Suspend() error { + return oboe.Suspend() +} + +func (c *context) Resume() error { + return oboe.Resume() +} + +func (c *context) Err() error { + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_darwin.go b/vendor/github.com/ebitengine/oto/v3/driver_darwin.go new file mode 100644 index 0000000..5ccf35a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_darwin.go @@ -0,0 +1,263 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "fmt" + "sync" + "time" + "unsafe" + + "github.com/ebitengine/purego/objc" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +const ( + float32SizeInBytes = 4 + + bufferCount = 4 + + noErr = 0 +) + +func newAudioQueue(sampleRate, channelCount int, oneBufferSizeInBytes int) (_AudioQueueRef, []_AudioQueueBufferRef, error) { + desc := _AudioStreamBasicDescription{ + mSampleRate: float64(sampleRate), + mFormatID: uint32(kAudioFormatLinearPCM), + mFormatFlags: uint32(kAudioFormatFlagIsFloat), + mBytesPerPacket: uint32(channelCount * float32SizeInBytes), + mFramesPerPacket: 1, + mBytesPerFrame: uint32(channelCount * float32SizeInBytes), + mChannelsPerFrame: uint32(channelCount), + mBitsPerChannel: uint32(8 * float32SizeInBytes), + } + + var audioQueue _AudioQueueRef + if osstatus := _AudioQueueNewOutput( + &desc, + render, + nil, + 0, //CFRunLoopRef + 0, //CFStringRef + 0, + &audioQueue); osstatus != noErr { + return 0, nil, fmt.Errorf("oto: AudioQueueNewFormat with StreamFormat failed: %d", osstatus) + } + + bufs := make([]_AudioQueueBufferRef, 0, bufferCount) + for len(bufs) < cap(bufs) { + var buf _AudioQueueBufferRef + if osstatus := _AudioQueueAllocateBuffer(audioQueue, uint32(oneBufferSizeInBytes), &buf); osstatus != noErr { + return 0, nil, fmt.Errorf("oto: AudioQueueAllocateBuffer failed: %d", osstatus) + } + buf.mAudioDataByteSize = uint32(oneBufferSizeInBytes) + bufs = append(bufs, buf) + } + + return audioQueue, bufs, nil +} + +type context struct { + audioQueue _AudioQueueRef + unqueuedBuffers []_AudioQueueBufferRef + + oneBufferSizeInBytes int + + cond *sync.Cond + + mux *mux.Mux + err atomicError +} + +// TODO: Convert the error code correctly. +// See https://stackoverflow.com/questions/2196869/how-do-you-convert-an-iphone-osstatus-code-to-something-useful + +var theContext *context + +func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeInBytes int) (*context, chan struct{}, error) { + var oneBufferSizeInBytes int + if bufferSizeInBytes != 0 { + oneBufferSizeInBytes = bufferSizeInBytes / bufferCount + } else { + oneBufferSizeInBytes = defaultOneBufferSizeInBytes + } + bytesPerSample := channelCount * 4 + oneBufferSizeInBytes = oneBufferSizeInBytes / bytesPerSample * bytesPerSample + + ready := make(chan struct{}) + + c := &context{ + cond: sync.NewCond(&sync.Mutex{}), + mux: mux.New(sampleRate, channelCount, format), + oneBufferSizeInBytes: oneBufferSizeInBytes, + } + theContext = c + + if err := initializeAPI(); err != nil { + return nil, nil, err + } + + go func() { + defer close(ready) + + q, bs, err := newAudioQueue(sampleRate, channelCount, oneBufferSizeInBytes) + if err != nil { + c.err.TryStore(err) + return + } + c.audioQueue = q + c.unqueuedBuffers = bs + + if err := setNotificationHandler(); err != nil { + c.err.TryStore(err) + return + } + + var retryCount int + try: + if osstatus := _AudioQueueStart(c.audioQueue, nil); osstatus != noErr { + if osstatus == avAudioSessionErrorCodeCannotStartPlaying && retryCount < 100 { + // TODO: use sleepTime() after investigating when this error happens. + time.Sleep(10 * time.Millisecond) + retryCount++ + goto try + } + c.err.TryStore(fmt.Errorf("oto: AudioQueueStart failed at newContext: %d", osstatus)) + return + } + + go c.loop() + }() + + return c, ready, nil +} + +func (c *context) wait() bool { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + for len(c.unqueuedBuffers) == 0 && c.err.Load() == nil { + c.cond.Wait() + } + return c.err.Load() == nil +} + +func (c *context) loop() { + buf32 := make([]float32, c.oneBufferSizeInBytes/4) + for { + if !c.wait() { + return + } + c.appendBuffer(buf32) + } +} + +func (c *context) appendBuffer(buf32 []float32) { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if c.err.Load() != nil { + return + } + + buf := c.unqueuedBuffers[0] + copy(c.unqueuedBuffers, c.unqueuedBuffers[1:]) + c.unqueuedBuffers = c.unqueuedBuffers[:len(c.unqueuedBuffers)-1] + + c.mux.ReadFloat32s(buf32) + copy(unsafe.Slice((*float32)(unsafe.Pointer(buf.mAudioData)), buf.mAudioDataByteSize/float32SizeInBytes), buf32) + + if osstatus := _AudioQueueEnqueueBuffer(c.audioQueue, buf, 0, nil); osstatus != noErr { + c.err.TryStore(fmt.Errorf("oto: AudioQueueEnqueueBuffer failed: %d", osstatus)) + } +} + +func (c *context) Suspend() error { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if err := c.err.Load(); err != nil { + return err.(error) + } + if osstatus := _AudioQueuePause(c.audioQueue); osstatus != noErr { + return fmt.Errorf("oto: AudioQueuePause failed: %d", osstatus) + } + return nil +} + +func (c *context) Resume() error { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if err := c.err.Load(); err != nil { + return err.(error) + } + + var retryCount int +try: + if osstatus := _AudioQueueStart(c.audioQueue, nil); osstatus != noErr { + if (osstatus == avAudioSessionErrorCodeCannotStartPlaying || + osstatus == avAudioSessionErrorCodeCannotInterruptOthers) && + retryCount < 30 { + // It is uncertain that this error is temporary or not. Then let's use exponential-time sleeping. + time.Sleep(sleepTime(retryCount)) + retryCount++ + goto try + } + if osstatus == avAudioSessionErrorCodeSiriIsRecording { + // As this error should be temporary, it should be OK to use a short time for sleep anytime. + time.Sleep(10 * time.Millisecond) + goto try + } + return fmt.Errorf("oto: AudioQueueStart failed at Resume: %d", osstatus) + } + return nil +} + +func (c *context) Err() error { + if err := c.err.Load(); err != nil { + return err.(error) + } + return nil +} + +func render(inUserData unsafe.Pointer, inAQ _AudioQueueRef, inBuffer _AudioQueueBufferRef) { + theContext.cond.L.Lock() + defer theContext.cond.L.Unlock() + theContext.unqueuedBuffers = append(theContext.unqueuedBuffers, inBuffer) + theContext.cond.Signal() +} + +func setGlobalPause(self objc.ID, _cmd objc.SEL, notification objc.ID) { + theContext.Suspend() +} + +func setGlobalResume(self objc.ID, _cmd objc.SEL, notification objc.ID) { + theContext.Resume() +} + +func sleepTime(count int) time.Duration { + switch count { + case 0: + return 10 * time.Millisecond + case 1: + return 20 * time.Millisecond + case 2: + return 50 * time.Millisecond + default: + return 100 * time.Millisecond + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_ios.go b/vendor/github.com/ebitengine/oto/v3/driver_ios.go new file mode 100644 index 0000000..d7a8e3f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_ios.go @@ -0,0 +1,30 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build darwin && ios + +package oto + +// 12288 seems necessary at least on iPod touch (7th). +// With 48000[Hz] stereo, the maximum delay is (12288*4[buffers] / 4 / 2)[samples] / 48000 [Hz] = 100[ms]. +// '4' is float32 size in bytes. '2' is a number of channels for stereo. + +const defaultOneBufferSizeInBytes = 12288 + +func setNotificationHandler() error { + // AVAudioSessionInterruptionNotification is not reliable on iOS. Rely on + // applicationWillResignActive and applicationDidBecomeActive instead. See + // https://stackoverflow.com/questions/24404463/ios-siri-not-available-does-not-return-avaudiosessioninterruptionoptionshouldre + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_js.go b/vendor/github.com/ebitengine/oto/v3/driver_js.go new file mode 100644 index 0000000..cae41f7 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_js.go @@ -0,0 +1,141 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "errors" + "runtime" + "syscall/js" + "unsafe" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +type context struct { + audioContext js.Value + scriptProcessor js.Value + scriptProcessorCallback js.Func + ready bool + callbacks map[string]js.Func + + mux *mux.Mux +} + +func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeInBytes int) (*context, chan struct{}, error) { + ready := make(chan struct{}) + + class := js.Global().Get("AudioContext") + if !class.Truthy() { + class = js.Global().Get("webkitAudioContext") + } + if !class.Truthy() { + return nil, nil, errors.New("oto: AudioContext or webkitAudioContext was not found") + } + options := js.Global().Get("Object").New() + options.Set("sampleRate", sampleRate) + + d := &context{ + audioContext: class.New(options), + mux: mux.New(sampleRate, channelCount, format), + } + + if bufferSizeInBytes == 0 { + // 4096 was not great at least on Safari 15. + bufferSizeInBytes = 8192 * channelCount + } + + buf32 := make([]float32, bufferSizeInBytes/4) + chBuf32 := make([][]float32, channelCount) + for i := range chBuf32 { + chBuf32[i] = make([]float32, len(buf32)/channelCount) + } + + // TODO: Use AudioWorklet if available. + sp := d.audioContext.Call("createScriptProcessor", bufferSizeInBytes/4/channelCount, 0, channelCount) + f := js.FuncOf(func(this js.Value, arguments []js.Value) any { + d.mux.ReadFloat32s(buf32) + for i := 0; i < channelCount; i++ { + for j := range chBuf32[i] { + chBuf32[i][j] = buf32[j*channelCount+i] + } + } + + buf := arguments[0].Get("outputBuffer") + if buf.Get("copyToChannel").Truthy() { + for i := 0; i < channelCount; i++ { + buf.Call("copyToChannel", float32SliceToTypedArray(chBuf32[i]), i, 0) + } + } else { + // copyToChannel is not defined on Safari 11. + for i := 0; i < channelCount; i++ { + buf.Call("getChannelData", i).Call("set", float32SliceToTypedArray(chBuf32[i])) + } + } + return nil + }) + sp.Call("addEventListener", "audioprocess", f) + d.scriptProcessor = sp + d.scriptProcessorCallback = f + + sp.Call("connect", d.audioContext.Get("destination")) + + setCallback := func(event string) js.Func { + var f js.Func + f = js.FuncOf(func(this js.Value, arguments []js.Value) any { + if !d.ready { + d.audioContext.Call("resume") + d.ready = true + close(ready) + } + js.Global().Get("document").Call("removeEventListener", event, f) + return nil + }) + js.Global().Get("document").Call("addEventListener", event, f) + d.callbacks[event] = f + return f + } + + // Browsers require user interaction to start the audio. + // https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio + d.callbacks = map[string]js.Func{} + setCallback("touchend") + setCallback("keyup") + setCallback("mouseup") + + return d, ready, nil +} + +func (c *context) Suspend() error { + c.audioContext.Call("suspend") + return nil +} + +func (c *context) Resume() error { + c.audioContext.Call("resume") + return nil +} + +func (c *context) Err() error { + return nil +} + +func float32SliceToTypedArray(s []float32) js.Value { + bs := unsafe.Slice((*byte)(unsafe.Pointer(&s[0])), len(s)*4) + a := js.Global().Get("Uint8Array").New(len(bs)) + js.CopyBytesToJS(a, bs) + runtime.KeepAlive(s) + buf := a.Get("buffer") + return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4) +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_macos.go b/vendor/github.com/ebitengine/oto/v3/driver_macos.go new file mode 100644 index 0000000..65bca94 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_macos.go @@ -0,0 +1,78 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build darwin && !ios + +package oto + +import ( + "unsafe" + + "github.com/ebitengine/purego" + "github.com/ebitengine/purego/objc" +) + +const defaultOneBufferSizeInBytes = 2048 + +// setNotificationHandler sets a handler for sleep/wake notifications. +func setNotificationHandler() error { + appkit, err := purego.Dlopen("/System/Library/Frameworks/AppKit.framework/Versions/Current/AppKit", purego.RTLD_GLOBAL) + if err != nil { + return err + } + + // Create the Observer object + var class objc.Class + class, err = objc.RegisterClass("OtoNotificationObserver", objc.GetClass("NSObject"), nil, nil, + []objc.MethodDef{ + { + Cmd: objc.RegisterName("receiveSleepNote:"), + Fn: setGlobalPause, + }, + { + Cmd: objc.RegisterName("receiveWakeNote:"), + Fn: setGlobalResume, + }, + }) + + observer := objc.ID(class).Send(objc.RegisterName("new")) + + notificationCenter := objc.ID(objc.GetClass("NSWorkspace")).Send(objc.RegisterName("sharedWorkspace")).Send(objc.RegisterName("notificationCenter")) + + // Dlsym returns a pointer to the object so dereference it + s, err := purego.Dlsym(appkit, "NSWorkspaceWillSleepNotification") + if err != nil { + return err + } + + notificationCenter.Send(objc.RegisterName("addObserver:selector:name:object:"), + observer, + objc.RegisterName("receiveSleepNote:"), + *(*uintptr)(unsafe.Pointer(s)), + 0, + ) + + s, err = purego.Dlsym(appkit, "NSWorkspaceDidWakeNotification") + if err != nil { + return err + } + + notificationCenter.Send(objc.RegisterName("addObserver:selector:name:object:"), + observer, + objc.RegisterName("receiveWakeNote:"), + *(*uintptr)(unsafe.Pointer(s)), + 0, + ) + return nil +} diff --git a/vendor/github.com/hajimehoshi/oto/driver_macos.go b/vendor/github.com/ebitengine/oto/v3/driver_nintendosdk.cpp similarity index 58% rename from vendor/github.com/hajimehoshi/oto/driver_macos.go rename to vendor/github.com/ebitengine/oto/v3/driver_nintendosdk.cpp index 5a2ab84..0d4ecae 100644 --- a/vendor/github.com/hajimehoshi/oto/driver_macos.go +++ b/vendor/github.com/ebitengine/oto/v3/driver_nintendosdk.cpp @@ -1,4 +1,4 @@ -// Copyright 2019 The Oto Authors +// Copyright 2022 The Oto Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,16 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build darwin && !ios && !js -// +build darwin,!ios,!js +//go:build nintendosdk -package oto +// The actual implementaiton will be provided by -overlay. -// #cgo LDFLAGS: -framework AppKit -// -// #import -import "C" +#include + +typedef void (*oto_OnReadCallbackType)(float *buf, size_t length); -func componentSubType() C.OSType { - return C.kAudioUnitSubType_DefaultOutput -} +extern "C" void oto_OpenAudio(int sample_rate, int channel_num, + oto_OnReadCallbackType on_read_callback, + int buffer_size_in_bytes) {} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_nintendosdk.go b/vendor/github.com/ebitengine/oto/v3/driver_nintendosdk.go new file mode 100644 index 0000000..3b3f4c7 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_nintendosdk.go @@ -0,0 +1,74 @@ +// Copyright 2022 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build nintendosdk + +package oto + +// #cgo !darwin LDFLAGS: -Wl,-unresolved-symbols=ignore-all +// #cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup +// +// typedef void (*oto_OnReadCallbackType)(float* buf, size_t length); +// +// void oto_OpenAudio(int sample_rate, int channel_num, oto_OnReadCallbackType on_read_callback, int buffer_size_in_bytes); +// +// void oto_OnReadCallback(float* buf, size_t length); +// static void oto_OpenProxy(int sample_rate, int channel_num, int buffer_size_in_bytes) { +// oto_OpenAudio(sample_rate, channel_num, oto_OnReadCallback, buffer_size_in_bytes); +// } +import "C" + +import ( + "unsafe" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +//export oto_OnReadCallback +func oto_OnReadCallback(buf *C.float, length C.size_t) { + theContext.mux.ReadFloat32s(unsafe.Slice((*float32)(unsafe.Pointer(buf)), length)) +} + +type context struct { + mux *mux.Mux +} + +var theContext *context + +func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeInBytes int) (*context, chan struct{}, error) { + ready := make(chan struct{}) + close(ready) + + c := &context{ + mux: mux.New(sampleRate, channelCount, format), + } + theContext = c + C.oto_OpenProxy(C.int(sampleRate), C.int(channelCount), C.int(bufferSizeInBytes)) + + return c, ready, nil +} + +func (c *context) Suspend() error { + // Do nothing so far. + return nil +} + +func (c *context) Resume() error { + // Do nothing so far. + return nil +} + +func (c *context) Err() error { + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_unix.go b/vendor/github.com/ebitengine/oto/v3/driver_unix.go new file mode 100644 index 0000000..b1fc21d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_unix.go @@ -0,0 +1,278 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !android && !darwin && !js && !windows && !nintendosdk + +package oto + +// #cgo pkg-config: alsa +// +// #include +import "C" + +import ( + "fmt" + "strings" + "sync" + "unsafe" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +type context struct { + channelCount int + + suspended bool + + handle *C.snd_pcm_t + + cond *sync.Cond + + mux *mux.Mux + err atomicError + + ready chan struct{} +} + +var theContext *context + +func alsaError(name string, err C.int) error { + return fmt.Errorf("oto: ALSA error at %s: %s", name, C.GoString(C.snd_strerror(err))) +} + +func deviceCandidates() []string { + const getAllDevices = -1 + + cPCMInterfaceName := C.CString("pcm") + defer C.free(unsafe.Pointer(cPCMInterfaceName)) + + var hints *unsafe.Pointer + err := C.snd_device_name_hint(getAllDevices, cPCMInterfaceName, &hints) + if err != 0 { + return []string{"default", "plug:default"} + } + defer C.snd_device_name_free_hint(hints) + + var devices []string + + cIoHintName := C.CString("IOID") + defer C.free(unsafe.Pointer(cIoHintName)) + cNameHintName := C.CString("NAME") + defer C.free(unsafe.Pointer(cNameHintName)) + + for it := hints; *it != nil; it = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(it)) + unsafe.Sizeof(uintptr(0)))) { + io := C.snd_device_name_get_hint(*it, cIoHintName) + defer func() { + if io != nil { + C.free(unsafe.Pointer(io)) + } + }() + if C.GoString(io) == "Input" { + continue + } + + name := C.snd_device_name_get_hint(*it, cNameHintName) + defer func() { + if name != nil { + C.free(unsafe.Pointer(name)) + } + }() + if name == nil { + continue + } + goName := C.GoString(name) + if goName == "null" { + continue + } + if goName == "default" { + continue + } + devices = append(devices, goName) + } + + devices = append([]string{"default", "plug:default"}, devices...) + + return devices +} + +func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeInBytes int) (*context, chan struct{}, error) { + c := &context{ + channelCount: channelCount, + cond: sync.NewCond(&sync.Mutex{}), + mux: mux.New(sampleRate, channelCount, format), + ready: make(chan struct{}), + } + theContext = c + + go func() { + defer close(c.ready) + + // Open a default ALSA audio device for blocking stream playback + type openError struct { + device string + err C.int + } + var openErrs []openError + var found bool + + for _, name := range deviceCandidates() { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + if err := C.snd_pcm_open(&c.handle, cname, C.SND_PCM_STREAM_PLAYBACK, 0); err < 0 { + openErrs = append(openErrs, openError{ + device: name, + err: err, + }) + continue + } + found = true + break + } + if !found { + var msgs []string + for _, e := range openErrs { + msgs = append(msgs, fmt.Sprintf("%q: %s", e.device, C.GoString(C.snd_strerror(e.err)))) + } + c.err.TryStore(fmt.Errorf("oto: ALSA error at snd_pcm_open: %s", strings.Join(msgs, ", "))) + return + } + + // TODO: Should snd_pcm_hw_params_set_periods be called explicitly? + const periods = 2 + var periodSize C.snd_pcm_uframes_t + if bufferSizeInBytes != 0 { + periodSize = C.snd_pcm_uframes_t(bufferSizeInBytes / (channelCount * 4 * periods)) + } else { + periodSize = C.snd_pcm_uframes_t(1024) + } + bufferSize := periodSize * periods + if err := c.alsaPcmHwParams(sampleRate, channelCount, &bufferSize, &periodSize); err != nil { + c.err.TryStore(err) + return + } + + go func() { + buf32 := make([]float32, int(periodSize)*channelCount) + for { + if !c.readAndWrite(buf32) { + return + } + } + }() + }() + + return c, c.ready, nil +} + +func (c *context) alsaPcmHwParams(sampleRate, channelCount int, bufferSize, periodSize *C.snd_pcm_uframes_t) error { + var params *C.snd_pcm_hw_params_t + C.snd_pcm_hw_params_malloc(¶ms) + defer C.free(unsafe.Pointer(params)) + + if err := C.snd_pcm_hw_params_any(c.handle, params); err < 0 { + return alsaError("snd_pcm_hw_params_any", err) + } + if err := C.snd_pcm_hw_params_set_access(c.handle, params, C.SND_PCM_ACCESS_RW_INTERLEAVED); err < 0 { + return alsaError("snd_pcm_hw_params_set_access", err) + } + if err := C.snd_pcm_hw_params_set_format(c.handle, params, C.SND_PCM_FORMAT_FLOAT_LE); err < 0 { + return alsaError("snd_pcm_hw_params_set_format", err) + } + if err := C.snd_pcm_hw_params_set_channels(c.handle, params, C.unsigned(channelCount)); err < 0 { + return alsaError("snd_pcm_hw_params_set_channels", err) + } + if err := C.snd_pcm_hw_params_set_rate_resample(c.handle, params, 1); err < 0 { + return alsaError("snd_pcm_hw_params_set_rate_resample", err) + } + sr := C.unsigned(sampleRate) + if err := C.snd_pcm_hw_params_set_rate_near(c.handle, params, &sr, nil); err < 0 { + return alsaError("snd_pcm_hw_params_set_rate_near", err) + } + if err := C.snd_pcm_hw_params_set_buffer_size_near(c.handle, params, bufferSize); err < 0 { + return alsaError("snd_pcm_hw_params_set_buffer_size_near", err) + } + if err := C.snd_pcm_hw_params_set_period_size_near(c.handle, params, periodSize, nil); err < 0 { + return alsaError("snd_pcm_hw_params_set_period_size_near", err) + } + if err := C.snd_pcm_hw_params(c.handle, params); err < 0 { + return alsaError("snd_pcm_hw_params", err) + } + return nil +} + +func (c *context) readAndWrite(buf32 []float32) bool { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + for c.suspended && c.err.Load() == nil { + c.cond.Wait() + } + if c.err.Load() != nil { + return false + } + + c.mux.ReadFloat32s(buf32) + + for len(buf32) > 0 { + n := C.snd_pcm_writei(c.handle, unsafe.Pointer(&buf32[0]), C.snd_pcm_uframes_t(len(buf32)/c.channelCount)) + if n < 0 { + n = C.long(C.snd_pcm_recover(c.handle, C.int(n), 1)) + } + if n < 0 { + c.err.TryStore(alsaError("snd_pcm_writei or snd_pcm_recover", C.int(n))) + return false + } + buf32 = buf32[int(n)*c.channelCount:] + } + return true +} + +func (c *context) Suspend() error { + <-c.ready + + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if err := c.err.Load(); err != nil { + return err.(error) + } + + c.suspended = true + + // Do not use snd_pcm_pause as not all devices support this. + // Do not use snd_pcm_drop as this might hang (https://github.com/libsdl-org/SDL/blob/a5c610b0a3857d3138f3f3da1f6dc3172c5ea4a8/src/audio/alsa/SDL_alsa_audio.c#L478). + return nil +} + +func (c *context) Resume() error { + <-c.ready + + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if err := c.err.Load(); err != nil { + return err.(error) + } + + c.suspended = false + c.cond.Signal() + return nil +} + +func (c *context) Err() error { + if err := c.err.Load(); err != nil { + return err.(error) + } + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_wasapi_windows.go b/vendor/github.com/ebitengine/oto/v3/driver_wasapi_windows.go new file mode 100644 index 0000000..bfe4a3e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_wasapi_windows.go @@ -0,0 +1,470 @@ +// Copyright 2022 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "errors" + "fmt" + "runtime" + "sync" + "syscall" + "time" + "unsafe" + + "golang.org/x/sys/windows" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +type comThread struct { + funcCh chan func() +} + +func newCOMThread() (*comThread, error) { + funcCh := make(chan func()) + errCh := make(chan error) + go func() { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // S_FALSE is returned when CoInitializeEx is nested. This is a successful case. + if err := windows.CoInitializeEx(0, windows.COINIT_MULTITHREADED); err != nil && !errors.Is(err, syscall.Errno(windows.S_FALSE)) { + errCh <- err + } + // CoUninitialize should be called even when CoInitializeEx returns S_FALSE. + defer windows.CoUninitialize() + + close(errCh) + + for f := range funcCh { + f() + } + }() + + if err := <-errCh; err != nil { + return nil, err + } + + return &comThread{ + funcCh: funcCh, + }, nil +} + +func (c *comThread) Run(f func()) { + ch := make(chan struct{}) + c.funcCh <- func() { + f() + close(ch) + } + <-ch +} + +type wasapiContext struct { + sampleRate int + channelCount int + mux *mux.Mux + bufferSizeInBytes int + + comThread *comThread + err atomicError + suspended bool + suspendedCond *sync.Cond + + sampleReadyEvent windows.Handle + client *_IAudioClient2 + bufferFrames uint32 + renderClient *_IAudioRenderClient + currentDeviceID string + enumerator *_IMMDeviceEnumerator + + buf []float32 + + m sync.Mutex +} + +var ( + errDeviceSwitched = errors.New("oto: device switched") + errFormatNotSupported = errors.New("oto: the specified format is not supported (there is the closest format instead)") +) + +func newWASAPIContext(sampleRate, channelCount int, mux *mux.Mux, bufferSizeInBytes int) (context *wasapiContext, ferr error) { + t, err := newCOMThread() + if err != nil { + return nil, err + } + + c := &wasapiContext{ + sampleRate: sampleRate, + channelCount: channelCount, + mux: mux, + bufferSizeInBytes: bufferSizeInBytes, + comThread: t, + suspendedCond: sync.NewCond(&sync.Mutex{}), + } + + ev, err := windows.CreateEventEx(nil, nil, 0, windows.EVENT_ALL_ACCESS) + if err != nil { + return nil, err + } + defer func() { + if ferr != nil { + windows.CloseHandle(ev) + } + }() + c.sampleReadyEvent = ev + + if err := c.start(); err != nil { + return nil, err + } + + return c, nil +} + +func (c *wasapiContext) isDeviceSwitched() (bool, error) { + // If the audio is suspended, do nothing. + if c.isSuspended() { + return false, nil + } + + var switched bool + var cerr error + c.comThread.Run(func() { + device, err := c.enumerator.GetDefaultAudioEndPoint(eRender, eConsole) + if err != nil { + cerr = err + return + } + defer device.Release() + + id, err := device.GetId() + if err != nil { + cerr = err + return + } + + if c.currentDeviceID == id { + return + } + switched = true + }) + + return switched, cerr +} + +func (c *wasapiContext) start() error { + var cerr error + c.comThread.Run(func() { + if err := c.startOnCOMThread(); err != nil { + cerr = err + return + } + }) + if cerr != nil { + return cerr + } + + go func() { + if err := c.loop(); err != nil { + if !errors.Is(err, _AUDCLNT_E_DEVICE_INVALIDATED) && !errors.Is(err, _AUDCLNT_E_RESOURCES_INVALIDATED) && !errors.Is(err, errDeviceSwitched) { + c.err.TryStore(err) + return + } + + if err := c.restart(); err != nil { + c.err.TryStore(err) + return + } + } + }() + + return nil +} + +func (c *wasapiContext) startOnCOMThread() (ferr error) { + if c.enumerator == nil { + e, err := _CoCreateInstance(&uuidMMDeviceEnumerator, nil, uint32(_CLSCTX_ALL), &uuidIMMDeviceEnumerator) + if err != nil { + return err + } + c.enumerator = (*_IMMDeviceEnumerator)(e) + defer func() { + if ferr != nil { + c.enumerator.Release() + c.enumerator = nil + } + }() + } + + device, err := c.enumerator.GetDefaultAudioEndPoint(eRender, eConsole) + if err != nil { + if errors.Is(err, _E_NOTFOUND) { + return errDeviceNotFound + } + return err + } + defer device.Release() + + id, err := device.GetId() + if err != nil { + return err + } + c.currentDeviceID = id + + if c.client != nil { + c.client.Release() + c.client = nil + } + + client, err := device.Activate(&uuidIAudioClient2, uint32(_CLSCTX_ALL), nil) + if err != nil { + return err + } + c.client = (*_IAudioClient2)(client) + + if err := c.client.SetClientProperties(&_AudioClientProperties{ + cbSize: uint32(unsafe.Sizeof(_AudioClientProperties{})), + bIsOffload: 0, // false + eCategory: _AudioCategory_Other, // In the example, AudioCategory_ForegroundOnlyMedia was used, but this value is deprecated. + }); err != nil { + return err + } + + // Check the format is supported by WASAPI. + // Stereo with 48000 [Hz] is likely supported, but mono and/or other sample rates are unlikely supported. + // Fallback to WinMM in this case anyway. + const bitsPerSample = 32 + nBlockAlign := c.channelCount * bitsPerSample / 8 + var channelMask uint32 + switch c.channelCount { + case 1: + channelMask = _SPEAKER_FRONT_CENTER + case 2: + channelMask = _SPEAKER_FRONT_LEFT | _SPEAKER_FRONT_RIGHT + } + f := &_WAVEFORMATEXTENSIBLE{ + wFormatTag: _WAVE_FORMAT_EXTENSIBLE, + nChannels: uint16(c.channelCount), + nSamplesPerSec: uint32(c.sampleRate), + nAvgBytesPerSec: uint32(c.sampleRate * nBlockAlign), + nBlockAlign: uint16(nBlockAlign), + wBitsPerSample: bitsPerSample, + cbSize: 0x16, + Samples: bitsPerSample, + dwChannelMask: channelMask, + SubFormat: _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, + } + + var bufferSizeIn100ns _REFERENCE_TIME + if c.bufferSizeInBytes != 0 { + bufferSizeInFrames := int64(c.bufferSizeInBytes) / int64(nBlockAlign) + bufferSizeIn100ns = _REFERENCE_TIME(1e7 * bufferSizeInFrames / int64(c.sampleRate)) + } else { + // The default buffer size can be too small and might cause glitch noises. + // Specify 50[ms] as the buffer size. + bufferSizeIn100ns = _REFERENCE_TIME(50 * time.Millisecond / 100) + } + + // Even if the sample rate and/or the number of channels are not supported by the audio driver, + // AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM should convert the sample rate automatically (#215). + if err := c.client.Initialize(_AUDCLNT_SHAREMODE_SHARED, + _AUDCLNT_STREAMFLAGS_EVENTCALLBACK|_AUDCLNT_STREAMFLAGS_NOPERSIST|_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM, + bufferSizeIn100ns, 0, f, nil); err != nil { + return err + } + + frames, err := c.client.GetBufferSize() + if err != nil { + return err + } + c.bufferFrames = frames + + if c.renderClient != nil { + c.renderClient.Release() + c.renderClient = nil + } + + renderClient, err := c.client.GetService(&uuidIAudioRenderClient) + if err != nil { + return err + } + c.renderClient = (*_IAudioRenderClient)(renderClient) + + if err := c.client.SetEventHandle(c.sampleReadyEvent); err != nil { + return err + } + + // TODO: Should some errors be allowed? See WASAPIManager.cpp in the official example SimpleWASAPIPlaySound. + + if err := c.client.Start(); err != nil { + return err + } + + return nil +} + +func (c *wasapiContext) loop() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // S_FALSE is returned when CoInitializeEx is nested. This is a successful case. + if err := windows.CoInitializeEx(0, windows.COINIT_MULTITHREADED); err != nil && !errors.Is(err, syscall.Errno(windows.S_FALSE)) { + _, _ = c.client.Stop() + return err + } + // CoUninitialize should be called even when CoInitializeEx returns S_FALSE. + defer windows.CoUninitialize() + + if err := c.loopOnRenderThread(); err != nil { + _, _ = c.client.Stop() + return err + } + + return nil +} + +func (c *wasapiContext) loopOnRenderThread() error { + last := time.Now() + for { + c.suspendedCond.L.Lock() + for c.suspended { + c.suspendedCond.Wait() + } + c.suspendedCond.L.Unlock() + + evt, err := windows.WaitForSingleObject(c.sampleReadyEvent, windows.INFINITE) + if err != nil { + return err + } + if evt != windows.WAIT_OBJECT_0 { + return fmt.Errorf("oto: WaitForSingleObject failed: returned value: %d", evt) + } + + if err := c.writeOnRenderThread(); err != nil { + return err + } + + // Checking the current default audio device might be an expensive operation. + // Check this repeatedly but with some time interval. + if now := time.Now(); now.Sub(last) >= 500*time.Millisecond { + switched, err := c.isDeviceSwitched() + if err != nil { + return err + } + if switched { + return errDeviceSwitched + } + last = now + } + } +} + +func (c *wasapiContext) writeOnRenderThread() error { + c.m.Lock() + defer c.m.Unlock() + + paddingFrames, err := c.client.GetCurrentPadding() + if err != nil { + return err + } + + frames := c.bufferFrames - paddingFrames + if frames <= 0 { + return nil + } + + // Get the destination buffer. + dstBuf, err := c.renderClient.GetBuffer(frames) + if err != nil { + return err + } + + // Calculate the buffer size. + if buflen := int(frames) * c.channelCount; cap(c.buf) < buflen { + c.buf = make([]float32, buflen) + } else { + c.buf = c.buf[:buflen] + } + + // Read the buffer from the players. + c.mux.ReadFloat32s(c.buf) + + // Copy the read buf to the destination buffer. + copy(unsafe.Slice((*float32)(unsafe.Pointer(dstBuf)), len(c.buf)), c.buf) + + // Release the buffer. + if err := c.renderClient.ReleaseBuffer(frames, 0); err != nil { + return err + } + + c.buf = c.buf[:0] + return nil +} + +func (c *wasapiContext) Suspend() error { + c.suspendedCond.L.Lock() + c.suspended = true + c.suspendedCond.L.Unlock() + c.suspendedCond.Signal() + + return nil +} + +func (c *wasapiContext) Resume() error { + c.suspendedCond.L.Lock() + c.suspended = false + c.suspendedCond.L.Unlock() + c.suspendedCond.Signal() + + return nil +} + +func (c *wasapiContext) isSuspended() bool { + c.suspendedCond.L.Lock() + defer c.suspendedCond.L.Unlock() + return c.suspended +} + +func (c *wasapiContext) Err() error { + return c.err.Load() +} + +func (c *wasapiContext) restart() error { + // Probably the driver is missing temporarily e.g. plugging out the headset. + // Recreate the device. + +retry: + c.suspendedCond.L.Lock() + for c.suspended { + c.suspendedCond.Wait() + } + c.suspendedCond.L.Unlock() + + if err := c.start(); err != nil { + // When a device is switched, the new device might not support the desired format, + // or all the audio devices might be disconnected. + // Instead of aborting this context, let's wait for the next device switch. + if !errors.Is(err, errFormatNotSupported) && !errors.Is(err, errDeviceNotFound) { + return err + } + + // Just read the buffer and discard it. Then, retry to search the device. + var buf32 [4096]float32 + sleep := time.Duration(float64(time.Second) * float64(len(buf32)) / float64(c.channelCount) / float64(c.sampleRate)) + c.mux.ReadFloat32s(buf32[:]) + time.Sleep(sleep) + goto retry + } + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_windows.go b/vendor/github.com/ebitengine/oto/v3/driver_windows.go new file mode 100644 index 0000000..1a5abe1 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_windows.go @@ -0,0 +1,163 @@ +// Copyright 2022 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "errors" + "fmt" + "time" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +var errDeviceNotFound = errors.New("oto: device not found") + +type context struct { + sampleRate int + channelCount int + + mux *mux.Mux + + wasapiContext *wasapiContext + winmmContext *winmmContext + nullContext *nullContext + + ready chan struct{} + err atomicError +} + +func newContext(sampleRate int, channelCount int, format mux.Format, bufferSizeInBytes int) (*context, chan struct{}, error) { + ctx := &context{ + sampleRate: sampleRate, + channelCount: channelCount, + mux: mux.New(sampleRate, channelCount, format), + ready: make(chan struct{}), + } + + // Initializing drivers might take some time. Do this asynchronously. + go func() { + defer close(ctx.ready) + + xc, err0 := newWASAPIContext(sampleRate, channelCount, ctx.mux, bufferSizeInBytes) + if err0 == nil { + ctx.wasapiContext = xc + return + } + + wc, err1 := newWinMMContext(sampleRate, channelCount, ctx.mux, bufferSizeInBytes) + if err1 == nil { + ctx.winmmContext = wc + return + } + + if errors.Is(err0, errDeviceNotFound) && errors.Is(err1, errDeviceNotFound) { + ctx.nullContext = newNullContext(sampleRate, channelCount, ctx.mux) + return + } + + ctx.err.TryStore(fmt.Errorf("oto: initialization failed: WASAPI: %v, WinMM: %v", err0, err1)) + }() + + return ctx, ctx.ready, nil +} + +func (c *context) Suspend() error { + <-c.ready + if c.wasapiContext != nil { + return c.wasapiContext.Suspend() + } + if c.winmmContext != nil { + return c.winmmContext.Suspend() + } + if c.nullContext != nil { + return c.nullContext.Suspend() + } + return nil +} + +func (c *context) Resume() error { + <-c.ready + if c.wasapiContext != nil { + return c.wasapiContext.Resume() + } + if c.winmmContext != nil { + return c.winmmContext.Resume() + } + if c.nullContext != nil { + return c.nullContext.Resume() + } + return nil +} + +func (c *context) Err() error { + if err := c.err.Load(); err != nil { + return err + } + + select { + case <-c.ready: + default: + return nil + } + + if c.wasapiContext != nil { + return c.wasapiContext.Err() + } + if c.winmmContext != nil { + return c.winmmContext.Err() + } + if c.nullContext != nil { + return c.nullContext.Err() + } + return nil +} + +type nullContext struct { + suspended bool +} + +func newNullContext(sampleRate int, channelCount int, mux *mux.Mux) *nullContext { + c := &nullContext{} + go c.loop(sampleRate, channelCount, mux) + return c +} + +func (c *nullContext) loop(sampleRate int, channelCount int, mux *mux.Mux) { + var buf32 [4096]float32 + sleep := time.Duration(float64(time.Second) * float64(len(buf32)) / float64(channelCount) / float64(sampleRate)) + for { + if c.suspended { + time.Sleep(time.Second) + continue + } + + mux.ReadFloat32s(buf32[:]) + time.Sleep(sleep) + } +} + +func (c *nullContext) Suspend() error { + c.suspended = true + return nil +} + +func (c *nullContext) Resume() error { + c.suspended = false + return nil +} + +func (*nullContext) Err() error { + return nil +} diff --git a/vendor/github.com/ebitengine/oto/v3/driver_winmm_windows.go b/vendor/github.com/ebitengine/oto/v3/driver_winmm_windows.go new file mode 100644 index 0000000..04f935e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/driver_winmm_windows.go @@ -0,0 +1,297 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "errors" + "fmt" + "sync" + "time" + "unsafe" + + "golang.org/x/sys/windows" + + "github.com/ebitengine/oto/v3/internal/mux" +) + +// Avoid goroutines on Windows (hajimehoshi/ebiten#1768). +// Apparently, switching contexts might take longer than other platforms. + +const defaultHeaderBufferSize = 4096 + +type header struct { + waveOut uintptr + buffer []float32 + waveHdr *_WAVEHDR +} + +func newHeader(waveOut uintptr, bufferSizeInBytes int) (*header, error) { + h := &header{ + waveOut: waveOut, + buffer: make([]float32, bufferSizeInBytes/4), + } + h.waveHdr = &_WAVEHDR{ + lpData: uintptr(unsafe.Pointer(&h.buffer[0])), + dwBufferLength: uint32(bufferSizeInBytes), + } + if err := waveOutPrepareHeader(waveOut, h.waveHdr); err != nil { + return nil, err + } + return h, nil +} + +func (h *header) Write(data []float32) error { + copy(h.buffer, data) + if err := waveOutWrite(h.waveOut, h.waveHdr); err != nil { + return err + } + return nil +} + +func (h *header) IsQueued() bool { + return h.waveHdr.dwFlags&_WHDR_INQUEUE != 0 +} + +func (h *header) Close() error { + return waveOutUnprepareHeader(h.waveOut, h.waveHdr) +} + +type winmmContext struct { + sampleRate int + channelCount int + bufferSizeInBytes int + + waveOut uintptr + headers []*header + + buf32 []float32 + + mux *mux.Mux + err atomicError + loopEndCh chan error + + cond *sync.Cond + + suspended bool + suspendedCond *sync.Cond +} + +var theWinMMContext *winmmContext + +func newWinMMContext(sampleRate, channelCount int, mux *mux.Mux, bufferSizeInBytes int) (*winmmContext, error) { + // winmm.dll is not available on Xbox. + if err := winmm.Load(); err != nil { + return nil, fmt.Errorf("oto: loading winmm.dll failed: %w", err) + } + + c := &winmmContext{ + sampleRate: sampleRate, + channelCount: channelCount, + bufferSizeInBytes: bufferSizeInBytes, + mux: mux, + cond: sync.NewCond(&sync.Mutex{}), + suspendedCond: sync.NewCond(&sync.Mutex{}), + } + theWinMMContext = c + + if err := c.start(); err != nil { + return nil, err + } + return c, nil +} + +func (c *winmmContext) start() error { + const bitsPerSample = 32 + nBlockAlign := c.channelCount * bitsPerSample / 8 + f := &_WAVEFORMATEX{ + wFormatTag: _WAVE_FORMAT_IEEE_FLOAT, + nChannels: uint16(c.channelCount), + nSamplesPerSec: uint32(c.sampleRate), + nAvgBytesPerSec: uint32(c.sampleRate * nBlockAlign), + nBlockAlign: uint16(nBlockAlign), + wBitsPerSample: bitsPerSample, + } + + // TOOD: What about using an event instead of a callback? PortAudio and other libraries do that. + w, err := waveOutOpen(f, waveOutOpenCallback) + if errors.Is(err, windows.ERROR_NOT_FOUND) { + // This can happen when no device is found (#77). + return errDeviceNotFound + } + if errors.Is(err, _MMSYSERR_BADDEVICEID) { + // This can happen when no device is found (hajimehoshi/ebiten#2316). + return errDeviceNotFound + } + if err != nil { + return err + } + + headerBufferSize := defaultHeaderBufferSize + if c.bufferSizeInBytes != 0 { + headerBufferSize = c.bufferSizeInBytes + } + + c.waveOut = w + c.headers = make([]*header, 0, 6) + for len(c.headers) < cap(c.headers) { + h, err := newHeader(c.waveOut, headerBufferSize) + if err != nil { + return err + } + c.headers = append(c.headers, h) + } + + c.buf32 = make([]float32, headerBufferSize/4) + go c.loop() + + return nil +} + +func (c *winmmContext) Suspend() error { + c.suspendedCond.L.Lock() + c.suspended = true + c.suspendedCond.L.Unlock() + c.suspendedCond.Signal() + + return nil +} + +func (c *winmmContext) Resume() (ferr error) { + c.suspendedCond.L.Lock() + c.suspended = false + c.suspendedCond.L.Unlock() + c.suspendedCond.Signal() + + return nil +} + +func (c *winmmContext) Err() error { + if err := c.err.Load(); err != nil { + return err.(error) + } + return nil +} + +func (c *winmmContext) isHeaderAvailable() bool { + for _, h := range c.headers { + if !h.IsQueued() { + return true + } + } + return false +} + +var waveOutOpenCallback = windows.NewCallback(func(hwo, uMsg, dwInstance, dwParam1, dwParam2 uintptr) uintptr { + // Queuing a header in this callback might not work especially when a headset is connected or disconnected. + // Just signal the condition vairable and don't do other things. + const womDone = 0x3bd + if uMsg != womDone { + return 0 + } + theWinMMContext.cond.Signal() + return 0 +}) + +func (c *winmmContext) waitUntilHeaderAvailable() bool { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + for !c.isHeaderAvailable() && c.err.Load() == nil && c.loopEndCh == nil { + c.cond.Wait() + } + return c.err.Load() == nil && c.loopEndCh == nil +} + +func (c *winmmContext) loop() { + defer func() { + if err := c.closeLoop(); err != nil { + c.err.TryStore(err) + } + }() + for { + c.suspendedCond.L.Lock() + for c.suspended { + c.suspendedCond.Wait() + } + c.suspendedCond.L.Unlock() + + if !c.waitUntilHeaderAvailable() { + return + } + c.appendBuffers() + } +} + +func (c *winmmContext) closeLoop() (ferr error) { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + defer func() { + if c.loopEndCh != nil { + if ferr != nil { + c.loopEndCh <- ferr + ferr = nil + } + close(c.loopEndCh) + c.loopEndCh = nil + } + }() + + for _, h := range c.headers { + if err := h.Close(); err != nil { + return err + } + } + c.headers = nil + + if err := waveOutClose(c.waveOut); err != nil { + return err + } + c.waveOut = 0 + return nil +} + +func (c *winmmContext) appendBuffers() { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if c.err.Load() != nil { + return + } + + c.mux.ReadFloat32s(c.buf32) + + for _, h := range c.headers { + if h.IsQueued() { + continue + } + + if err := h.Write(c.buf32); err != nil { + switch { + case errors.Is(err, _MMSYSERR_NOMEM): + continue + case errors.Is(err, _MMSYSERR_NODRIVER): + sleep := time.Duration(float64(time.Second) * float64(len(c.buf32)) / float64(c.channelCount) / float64(c.sampleRate)) + time.Sleep(sleep) + return + case errors.Is(err, windows.ERROR_NOT_FOUND): + // This error can happen when e.g. a new HDMI connection is detected (#51). + // TODO: Retry later. + } + c.err.TryStore(fmt.Errorf("oto: Queueing the header failed: %v", err)) + } + return + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/mux/mux.go b/vendor/github.com/ebitengine/oto/v3/internal/mux/mux.go new file mode 100644 index 0000000..28df789 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/mux/mux.go @@ -0,0 +1,560 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package mux offers APIs for a low-level multiplexer of audio players. +// Usually you don't have to use this. +package mux + +import ( + "errors" + "fmt" + "io" + "math" + "runtime" + "sync" + "time" +) + +// Format must sync with oto's Format. +type Format int + +const ( + FormatFloat32LE Format = iota + FormatUnsignedInt8 + FormatSignedInt16LE +) + +func (f Format) ByteLength() int { + switch f { + case FormatFloat32LE: + return 4 + case FormatUnsignedInt8: + return 1 + case FormatSignedInt16LE: + return 2 + } + panic(fmt.Sprintf("mux: unexpected format: %d", f)) +} + +// Mux is a low-level multiplexer of audio players. +type Mux struct { + sampleRate int + channelCount int + format Format + + players map[*playerImpl]struct{} + buf []float32 + cond *sync.Cond +} + +// New creates a new Mux. +func New(sampleRate int, channelCount int, format Format) *Mux { + m := &Mux{ + sampleRate: sampleRate, + channelCount: channelCount, + format: format, + cond: sync.NewCond(&sync.Mutex{}), + } + go m.loop() + return m +} + +func (m *Mux) shouldWait() bool { + for p := range m.players { + if p.canReadSourceToBuffer() { + return false + } + } + return true +} + +func (m *Mux) wait() { + m.cond.L.Lock() + defer m.cond.L.Unlock() + + for m.shouldWait() { + m.cond.Wait() + } +} + +func (m *Mux) loop() { + var players []*playerImpl + for { + m.wait() + + m.cond.L.Lock() + for i := range players { + players[i] = nil + } + players = players[:0] + for p := range m.players { + players = append(players, p) + } + m.cond.L.Unlock() + + allZero := true + for _, p := range players { + n := p.readSourceToBuffer() + if n != 0 { + allZero = false + } + } + + // Sleeping is necessary especially on browsers. + // Sometimes a player continues to read 0 bytes from the source and this loop can be a busy loop in such case. + if allZero { + time.Sleep(time.Millisecond) + } + } +} + +func (m *Mux) addPlayer(player *playerImpl) { + m.cond.L.Lock() + defer m.cond.L.Unlock() + + if m.players == nil { + m.players = map[*playerImpl]struct{}{} + } + m.players[player] = struct{}{} + m.cond.Signal() +} + +func (m *Mux) removePlayer(player *playerImpl) { + m.cond.L.Lock() + defer m.cond.L.Unlock() + + delete(m.players, player) + m.cond.Signal() +} + +// ReadFloat32s fills buf with the multiplexed data of the players as float32 values. +func (m *Mux) ReadFloat32s(buf []float32) { + m.cond.L.Lock() + players := make([]*playerImpl, 0, len(m.players)) + for p := range m.players { + players = append(players, p) + } + m.cond.L.Unlock() + + for i := range buf { + buf[i] = 0 + } + for _, p := range players { + p.readBufferAndAdd(buf) + } + m.cond.Signal() +} + +type Player struct { + p *playerImpl +} + +type playerState int + +const ( + playerPaused playerState = iota + playerPlay + playerClosed +) + +type playerImpl struct { + mux *Mux + src io.Reader + prevVolume float64 + volume float64 + err error + state playerState + tmpbuf []byte + buf []byte + eof bool + bufferSize int + + m sync.Mutex +} + +func (m *Mux) NewPlayer(src io.Reader) *Player { + pl := &Player{ + p: &playerImpl{ + mux: m, + src: src, + prevVolume: 1, + volume: 1, + bufferSize: m.defaultBufferSize(), + }, + } + runtime.SetFinalizer(pl, (*Player).Close) + return pl +} + +func (p *Player) Err() error { + return p.p.Err() +} + +func (p *playerImpl) Err() error { + p.m.Lock() + defer p.m.Unlock() + + return p.err +} + +func (p *Player) Play() { + p.p.Play() +} + +func (p *playerImpl) Play() { + // Goroutines don't work effiently on Windows. Avoid using them (hajimehoshi/ebiten#1768). + if runtime.GOOS == "windows" { + p.m.Lock() + defer p.m.Unlock() + + p.playImpl() + } else { + ch := make(chan struct{}) + go func() { + p.m.Lock() + defer p.m.Unlock() + + close(ch) + p.playImpl() + }() + <-ch + } +} + +func (p *Player) SetBufferSize(bufferSize int) { + p.p.setBufferSize(bufferSize) +} + +func (p *playerImpl) setBufferSize(bufferSize int) { + p.m.Lock() + defer p.m.Unlock() + + orig := p.bufferSize + p.bufferSize = bufferSize + if bufferSize == 0 { + p.bufferSize = p.mux.defaultBufferSize() + } + if orig != p.bufferSize { + p.tmpbuf = nil + } +} + +func (p *playerImpl) ensureTmpBuf() []byte { + if p.tmpbuf == nil { + p.tmpbuf = make([]byte, p.bufferSize) + } + return p.tmpbuf +} + +// read reads the source to buf. +// read unlocks the mutex temporarily and locks when reading finishes. +// This avoids locking during an external function call Read (#188). +// +// When read is called, the mutex m must be locked. +func (p *playerImpl) read(buf []byte) (int, error) { + p.m.Unlock() + defer p.m.Lock() + return p.src.Read(buf) +} + +// addToPlayers adds p to the players set. +// +// When addToPlayers is called, the mutex m must be locked. +func (p *playerImpl) addToPlayers() { + p.m.Unlock() + defer p.m.Lock() + p.mux.addPlayer(p) +} + +// removeFromPlayers removes p from the players set. +// +// When removeFromPlayers is called, the mutex m must be locked. +func (p *playerImpl) removeFromPlayers() { + p.m.Unlock() + defer p.m.Lock() + p.mux.removePlayer(p) +} + +func (p *playerImpl) playImpl() { + if p.err != nil { + return + } + if p.state != playerPaused { + return + } + p.state = playerPlay + + if !p.eof { + buf := p.ensureTmpBuf() + for len(p.buf) < p.bufferSize { + n, err := p.read(buf) + if err != nil && err != io.EOF { + p.setErrorImpl(err) + return + } + p.buf = append(p.buf, buf[:n]...) + if err == io.EOF { + p.eof = true + break + } + } + } + + if p.eof && len(p.buf) == 0 { + p.state = playerPaused + } + + p.addToPlayers() +} + +func (p *Player) Pause() { + p.p.Pause() +} + +func (p *playerImpl) Pause() { + p.m.Lock() + defer p.m.Unlock() + + if p.state != playerPlay { + return + } + p.state = playerPaused +} + +func (p *Player) Seek(offset int64, whence int) (int64, error) { + return p.p.Seek(offset, whence) +} + +func (p *playerImpl) Seek(offset int64, whence int) (int64, error) { + p.m.Lock() + defer p.m.Unlock() + + // If a player is playing, keep playing even after this seeking. + if p.state == playerPlay { + defer p.playImpl() + } + + // Reset the internal buffer. + p.resetImpl() + + // Check if the source implements io.Seeker. + s, ok := p.src.(io.Seeker) + if !ok { + return 0, errors.New("mux: the source must implement io.Seeker") + } + return s.Seek(offset, whence) +} + +func (p *Player) Reset() { + p.p.Reset() +} + +func (p *playerImpl) Reset() { + p.m.Lock() + defer p.m.Unlock() + p.resetImpl() +} + +func (p *playerImpl) resetImpl() { + if p.state == playerClosed { + return + } + p.state = playerPaused + p.buf = p.buf[:0] + p.eof = false +} + +func (p *Player) IsPlaying() bool { + return p.p.IsPlaying() +} + +func (p *playerImpl) IsPlaying() bool { + p.m.Lock() + defer p.m.Unlock() + return p.state == playerPlay +} + +func (p *Player) Volume() float64 { + return p.p.Volume() +} + +func (p *playerImpl) Volume() float64 { + p.m.Lock() + defer p.m.Unlock() + return p.volume +} + +func (p *Player) SetVolume(volume float64) { + p.p.SetVolume(volume) +} + +func (p *playerImpl) SetVolume(volume float64) { + p.m.Lock() + defer p.m.Unlock() + p.volume = volume + if p.state != playerPlay { + p.prevVolume = volume + } +} + +func (p *Player) BufferedSize() int { + return p.p.BufferedSize() +} + +func (p *playerImpl) BufferedSize() int { + p.m.Lock() + defer p.m.Unlock() + return len(p.buf) +} + +func (p *Player) Close() error { + runtime.SetFinalizer(p, nil) + return p.p.Close() +} + +func (p *playerImpl) Close() error { + p.m.Lock() + defer p.m.Unlock() + return p.closeImpl() +} + +func (p *playerImpl) closeImpl() error { + p.removeFromPlayers() + + if p.state == playerClosed { + return p.err + } + p.state = playerClosed + p.buf = nil + return p.err +} + +func (p *playerImpl) readBufferAndAdd(buf []float32) int { + p.m.Lock() + defer p.m.Unlock() + + if p.state != playerPlay { + return 0 + } + + format := p.mux.format + bitDepthInBytes := format.ByteLength() + n := len(p.buf) / bitDepthInBytes + if n > len(buf) { + n = len(buf) + } + + prevVolume := float32(p.prevVolume) + volume := float32(p.volume) + + channelCount := p.mux.channelCount + rateDenom := float32(n / channelCount) + + src := p.buf[:n*bitDepthInBytes] + + for i := 0; i < n; i++ { + var v float32 + switch format { + case FormatFloat32LE: + v = math.Float32frombits(uint32(src[4*i]) | uint32(src[4*i+1])<<8 | uint32(src[4*i+2])<<16 | uint32(src[4*i+3])<<24) + case FormatUnsignedInt8: + v8 := src[i] + v = float32(v8-(1<<7)) / (1 << 7) + case FormatSignedInt16LE: + v16 := int16(src[2*i]) | (int16(src[2*i+1]) << 8) + v = float32(v16) / (1 << 15) + default: + panic(fmt.Sprintf("mux: unexpected format: %d", format)) + } + if volume == prevVolume { + buf[i] += v * volume + } else { + rate := float32(i/channelCount) / rateDenom + if rate > 1 { + rate = 1 + } + buf[i] += v * (volume*rate + prevVolume*(1-rate)) + } + } + + p.prevVolume = p.volume + + copy(p.buf, p.buf[n*bitDepthInBytes:]) + p.buf = p.buf[:len(p.buf)-n*bitDepthInBytes] + + if p.eof && len(p.buf) == 0 { + p.state = playerPaused + } + + return n +} + +func (p *playerImpl) canReadSourceToBuffer() bool { + p.m.Lock() + defer p.m.Unlock() + + if p.eof { + return false + } + return len(p.buf) < p.bufferSize +} + +func (p *playerImpl) readSourceToBuffer() int { + p.m.Lock() + defer p.m.Unlock() + + if p.err != nil { + return 0 + } + if p.state == playerClosed { + return 0 + } + + if len(p.buf) >= p.bufferSize { + return 0 + } + + buf := p.ensureTmpBuf() + n, err := p.read(buf) + + if err != nil && err != io.EOF { + p.setErrorImpl(err) + return 0 + } + + p.buf = append(p.buf, buf[:n]...) + if err == io.EOF { + p.eof = true + if len(p.buf) == 0 { + p.state = playerPaused + } + } + return n +} + +func (p *playerImpl) setErrorImpl(err error) { + p.err = err + p.closeImpl() +} + +// TODO: The term 'buffer' is confusing. Name each buffer with good terms. + +// defaultBufferSize returns the default size of the buffer for the audio source. +// This buffer is used when unreading on pausing the player. +func (m *Mux) defaultBufferSize() int { + bytesPerSample := m.channelCount * m.format.ByteLength() + s := m.sampleRate * bytesPerSample / 2 // 0.5[s] + // Align s in multiples of bytes per sample, or a buffer could have extra bytes. + return s / bytesPerSample * bytesPerSample +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/.clang-format b/vendor/github.com/ebitengine/oto/v3/internal/oboe/.clang-format new file mode 100644 index 0000000..9d15924 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: false diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/LICENSE-oboe b/vendor/github.com/ebitengine/oto/v3/internal/oboe/LICENSE-oboe new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/LICENSE-oboe @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/README-oboe.md b/vendor/github.com/ebitengine/oto/v3/internal/oboe/README-oboe.md new file mode 100644 index 0000000..44acf9f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/README-oboe.md @@ -0,0 +1,54 @@ +# Oboe [![Build CI](https://github.com/google/oboe/workflows/Build%20CI/badge.svg)](https://github.com/google/oboe/actions) + +[![Introduction to Oboe video](docs/images/getting-started-video.jpg)](https://www.youtube.com/watch?v=csfHAbr5ilI&list=PLWz5rJ2EKKc_duWv9IPNvx9YBudNMmLSa) + +Oboe is a C++ library which makes it easy to build high-performance audio apps on Android. It was created primarily to allow developers to target a simplified API that works across multiple API levels back to API level 16 (Jelly Bean). + +## Features +- Compatible with API 16 onwards - runs on 99% of Android devices +- Chooses the audio API (OpenSL ES on API 16+ or AAudio on API 27+) which will give the best audio performance on the target Android device +- Automatic latency tuning +- Modern C++ allowing you to write clean, elegant code +- Workarounds for some known issues +- [Used by popular apps and frameworks](https://github.com/google/oboe/wiki/AppsUsingOboe) + +## Documentation +- [Getting Started Guide](docs/GettingStarted.md) +- [Full Guide to Oboe](docs/FullGuide.md) +- [API reference](https://google.github.io/oboe) +- [Tech Notes](docs/notes/) +- [History of Audio features/bugs by Android version](docs/AndroidAudioHistory.md) +- [Migration guide for apps using OpenSL ES](docs/OpenSLESMigration.md) +- [Frequently Asked Questions](docs/FAQ.md) (FAQ) +- [Our roadmap](https://github.com/google/oboe/milestones) - Vote on a feature/issue by adding a thumbs up to the first comment. + +### Community +- Reddit: [r/androidaudiodev](https://www.reddit.com/r/androidaudiodev/) +- StackOverflow: [#oboe](https://stackoverflow.com/questions/tagged/oboe) + +## Testing +- [**OboeTester** app for measuring latency, glitches, etc.](apps/OboeTester/docs) +- [Oboe unit tests](tests) + +## Videos +- [Getting started with Oboe](https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_duWv9IPNvx9YBudNMmLSa) +- [Low Latency Audio - Because Your Ears Are Worth It](https://www.youtube.com/watch?v=8vOf_fDtur4) (Android Dev Summit '18) +- [Winning on Android](https://www.youtube.com/watch?v=tWBojmBpS74) - How to optimize an Android audio app. (ADC '18) + +## Sample code and apps +- Sample apps can be found in the [samples directory](samples). +- A complete "effects processor" app called FXLab can be found in the [apps/fxlab folder](apps/fxlab). +- Also check out the [Rhythm Game codelab](https://developer.android.com/codelabs/musicalgame-using-oboe?hl=en#0). + +### Third party sample code +- [Ableton Link integration demo](https://github.com/jbloit/AndroidLinkAudio) (author: jbloit) + +## Contributing +We would love to receive your pull requests. Before we can though, please read the [contributing](CONTRIBUTING.md) guidelines. + +## Version history +View the [releases page](../../releases). + +## License +[LICENSE](LICENSE) + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.cpp new file mode 100644 index 0000000..48b9699 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.cpp @@ -0,0 +1,191 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "binding_android.h" + +#include "_cgo_export.h" +#include "oboe_oboe_Oboe_android.h" + +#include +#include +#include +#include +#include + +namespace { + +class Player; + +class Stream : public oboe::AudioStreamDataCallback { +public: + // GetInstance returns the instance of Stream. Only one Stream object is used + // in one process. It is because multiple streams can be problematic in both + // AAudio and OpenSL (#1656, #1660). + static Stream &GetInstance(); + + const char *Play(int sample_rate, int channel_num, int buffer_size_in_bytes); + const char *Pause(); + const char *Resume(); + const char *Close(); + const char *AppendBuffer(float *buf, size_t len); + + oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboe_stream, + void *audio_data, + int32_t num_frames) override; + +private: + Stream(); + void Loop(int num_frames); + + int sample_rate_ = 0; + int channel_num_ = 0; + + std::shared_ptr stream_; + + // All the member variables other than the thread must be initialized before + // the thread. + std::vector buf_; + std::mutex mutex_; + std::condition_variable cond_; + std::unique_ptr thread_; +}; + +Stream &Stream::GetInstance() { + static Stream *stream = new Stream(); + return *stream; +} + +const char *Stream::Play(int sample_rate, int channel_num, + int buffer_size_in_bytes) { + sample_rate_ = sample_rate; + channel_num_ = channel_num; + + if (!stream_) { + oboe::AudioStreamBuilder builder; + builder.setDirection(oboe::Direction::Output) + ->setPerformanceMode(oboe::PerformanceMode::LowLatency) + ->setSharingMode(oboe::SharingMode::Shared) + ->setFormat(oboe::AudioFormat::Float) + ->setChannelCount(channel_num_) + ->setSampleRate(sample_rate_) + ->setDataCallback(this); + if (buffer_size_in_bytes) { + int buffer_size_in_frames = buffer_size_in_bytes / channel_num / 4; + builder.setBufferCapacityInFrames(buffer_size_in_frames); + } + oboe::Result result = builder.openStream(stream_); + if (result != oboe::Result::OK) { + return oboe::convertToText(result); + } + } + if (stream_->getSharingMode() != oboe::SharingMode::Shared) { + return "oboe::SharingMode::Shared is not available"; + } + + int num_frames = stream_->getBufferSizeInFrames(); + thread_ = + std::make_unique([this, num_frames]() { Loop(num_frames); }); + + // What if the buffer size is not enough? + if (oboe::Result result = stream_->start(); result != oboe::Result::OK) { + return oboe::convertToText(result); + } + return nullptr; +} + +const char *Stream::Pause() { + if (!stream_) { + return nullptr; + } + if (oboe::Result result = stream_->pause(); result != oboe::Result::OK) { + return oboe::convertToText(result); + } + return nullptr; +} + +const char *Stream::Resume() { + if (!stream_) { + return "Play is not called yet at Resume"; + } + if (oboe::Result result = stream_->start(); result != oboe::Result::OK) { + return oboe::convertToText(result); + } + return nullptr; +} + +const char *Stream::Close() { + // Nobody calls this so far. + if (!stream_) { + return nullptr; + } + if (oboe::Result result = stream_->stop(); result != oboe::Result::OK) { + return oboe::convertToText(result); + } + if (oboe::Result result = stream_->close(); result != oboe::Result::OK) { + return oboe::convertToText(result); + } + stream_.reset(); + return nullptr; +} + +oboe::DataCallbackResult Stream::onAudioReady(oboe::AudioStream *oboe_stream, + void *audio_data, + int32_t num_frames) { + size_t num = num_frames * channel_num_; + // TODO: Do not use a lock in onAudioReady. + // https://google.github.io/oboe/reference/classoboe_1_1_audio_stream_data_callback.html#ad8a3a9f609df5fd3a5d885cbe1b2204d + { + std::unique_lock lock{mutex_}; + cond_.wait(lock, [this, num] { return buf_.size() >= num; }); + std::copy(buf_.begin(), buf_.begin() + num, + reinterpret_cast(audio_data)); + buf_.erase(buf_.begin(), buf_.begin() + num); + cond_.notify_one(); + } + return oboe::DataCallbackResult::Continue; +} + +Stream::Stream() = default; + +void Stream::Loop(int num_frames) { + std::vector tmp(num_frames * channel_num_ * 3); + for (;;) { + { + std::unique_lock lock{mutex_}; + cond_.wait(lock, [this, &tmp] { return buf_.size() < tmp.size(); }); + } + oto_oboe_read(&tmp[0], tmp.size()); + { + std::lock_guard lock{mutex_}; + buf_.insert(buf_.end(), tmp.begin(), tmp.end()); + cond_.notify_one(); + } + } +} + +} // namespace + +extern "C" { + +const char *oto_oboe_Play(int sample_rate, int channel_num, + int buffer_size_in_bytes) { + return Stream::GetInstance().Play(sample_rate, channel_num, + buffer_size_in_bytes); +} + +const char *oto_oboe_Suspend() { return Stream::GetInstance().Pause(); } + +const char *oto_oboe_Resume() { return Stream::GetInstance().Resume(); } + +} // extern "C" diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.go b/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.go new file mode 100644 index 0000000..0fceb71 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.go @@ -0,0 +1,60 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oboe + +// Disable AAudio (hajimehoshi/ebiten#1634). +// AAudio doesn't care about plugging in/out of a headphone. +// See https://github.com/google/oboe/wiki/TechNote_Disconnect + +// #cgo CXXFLAGS: -std=c++17 -DOBOE_ENABLE_AAUDIO=0 +// #cgo LDFLAGS: -llog -lOpenSLES -static-libstdc++ +// +// #include "binding_android.h" +import "C" + +import ( + "fmt" + "unsafe" +) + +var theReadFunc func(buf []float32) + +func Play(sampleRate int, channelCount int, readFunc func(buf []float32), bufferSizeInBytes int) error { + // Play can invoke the callback. Set the callback before Play. + theReadFunc = readFunc + if msg := C.oto_oboe_Play(C.int(sampleRate), C.int(channelCount), C.int(bufferSizeInBytes)); msg != nil { + return fmt.Errorf("oboe: Play failed: %s", C.GoString(msg)) + } + return nil +} + +func Suspend() error { + if msg := C.oto_oboe_Suspend(); msg != nil { + return fmt.Errorf("oboe: Suspend failed: %s", C.GoString(msg)) + } + return nil +} + +func Resume() error { + if msg := C.oto_oboe_Resume(); msg != nil { + return fmt.Errorf("oboe: Resume failed: %s", C.GoString(msg)) + } + return nil +} + +//export oto_oboe_read +func oto_oboe_read(buf *C.float, len C.size_t) { + theReadFunc(unsafe.Slice((*float32)(unsafe.Pointer(buf)), len)) +} diff --git a/vendor/github.com/hajimehoshi/oto/driver_ios.go b/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.h similarity index 56% rename from vendor/github.com/hajimehoshi/oto/driver_ios.go rename to vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.h index ed4a7c0..82c5c07 100644 --- a/vendor/github.com/hajimehoshi/oto/driver_ios.go +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/binding_android.h @@ -1,4 +1,4 @@ -// Copyright 2019 The Oto Authors +// Copyright 2021 The Oto Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,16 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build darwin && ios && !js -// +build darwin,ios,!js +#ifndef OBOE_ANDROID_H_ +#define OBOE_ANDROID_H_ -package oto +#include +#include +#include -// #cgo LDFLAGS: -framework Foundation -framework AVFoundation -framework UIKit -// -// #import -import "C" +#ifdef __cplusplus +extern "C" { +#endif + +typedef uintptr_t PlayerID; -func componentSubType() C.OSType { - return C.kAudioUnitSubType_RemoteIO +const char *oto_oboe_Play(int sample_rate, int channel_num, + int buffer_size_in_bytes); +const char *oto_oboe_Suspend(); +const char *oto_oboe_Resume(); + +#ifdef __cplusplus } +#endif + +#endif // OBOE_ANDROID_H_ diff --git a/vendor/github.com/hajimehoshi/oto/pipe_notgopherjs.go b/vendor/github.com/ebitengine/oto/v3/internal/oboe/generate.go similarity index 75% rename from vendor/github.com/hajimehoshi/oto/pipe_notgopherjs.go rename to vendor/github.com/ebitengine/oto/v3/internal/oboe/generate.go index 8399281..0f6dbe1 100644 --- a/vendor/github.com/hajimehoshi/oto/pipe_notgopherjs.go +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/generate.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Oto Authors +// Copyright 2021 The Oto Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,15 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !js || (js && wasm) -// +build !js js,wasm +//go:generate go run gen.go -package oto - -import ( - "io" -) - -func pipe() (io.ReadCloser, io.WriteCloser) { - return io.Pipe() -} +package oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioExtensions_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioExtensions_android.h new file mode 100644 index 0000000..3bbccf9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioExtensions_android.h @@ -0,0 +1,179 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_AAUDIO_EXTENSIONS_H +#define OBOE_AAUDIO_EXTENSIONS_H + +#include +#include + +#include + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_Oboe_android.h" +#include "oboe_aaudio_AAudioLoader_android.h" + +namespace oboe { + +#define LIB_AAUDIO_NAME "libaaudio.so" +#define FUNCTION_IS_MMAP "AAudioStream_isMMapUsed" +#define FUNCTION_SET_MMAP_POLICY "AAudio_setMMapPolicy" +#define FUNCTION_GET_MMAP_POLICY "AAudio_getMMapPolicy" + +#define AAUDIO_ERROR_UNAVAILABLE static_cast(Result::ErrorUnavailable) + +typedef struct AAudioStreamStruct AAudioStream; + +/** + * Call some AAudio test routines that are not part of the normal API. + */ +class AAudioExtensions { +public: + AAudioExtensions() { + int32_t policy = getIntegerProperty("aaudio.mmap_policy", 0); + mMMapSupported = isPolicyEnabled(policy); + + policy = getIntegerProperty("aaudio.mmap_exclusive_policy", 0); + mMMapExclusiveSupported = isPolicyEnabled(policy); + } + + static bool isPolicyEnabled(int32_t policy) { + return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS); + } + + static AAudioExtensions &getInstance() { + static AAudioExtensions instance; + return instance; + } + + bool isMMapUsed(oboe::AudioStream *oboeStream) { + AAudioStream *aaudioStream = (AAudioStream *) oboeStream->getUnderlyingStream(); + return isMMapUsed(aaudioStream); + } + + bool isMMapUsed(AAudioStream *aaudioStream) { + if (loadSymbols()) return false; + if (mAAudioStream_isMMap == nullptr) return false; + return mAAudioStream_isMMap(aaudioStream); + } + + /** + * Controls whether the MMAP data path can be selected when opening a stream. + * It has no effect after the stream has been opened. + * It only affects the application that calls it. Other apps are not affected. + * + * @param enabled + * @return 0 or a negative error code + */ + int32_t setMMapEnabled(bool enabled) { + if (loadSymbols()) return AAUDIO_ERROR_UNAVAILABLE; + if (mAAudio_setMMapPolicy == nullptr) return false; + return mAAudio_setMMapPolicy(enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER); + } + + bool isMMapEnabled() { + if (loadSymbols()) return false; + if (mAAudio_getMMapPolicy == nullptr) return false; + int32_t policy = mAAudio_getMMapPolicy(); + return isPolicyEnabled(policy); + } + + bool isMMapSupported() { + return mMMapSupported; + } + + bool isMMapExclusiveSupported() { + return mMMapExclusiveSupported; + } + +private: + + enum { + AAUDIO_POLICY_NEVER = 1, + AAUDIO_POLICY_AUTO, + AAUDIO_POLICY_ALWAYS + }; + typedef int32_t aaudio_policy_t; + + int getIntegerProperty(const char *name, int defaultValue) { + int result = defaultValue; + char valueText[PROP_VALUE_MAX] = {0}; + if (__system_property_get(name, valueText) != 0) { + result = atoi(valueText); + } + return result; + } + + /** + * Load the function pointers. + * This can be called multiple times. + * It should only be called from one thread. + * + * @return 0 if successful or negative error. + */ + aaudio_result_t loadSymbols() { + if (mAAudio_getMMapPolicy != nullptr) { + return 0; + } + + AAudioLoader *libLoader = AAudioLoader::getInstance(); + int openResult = libLoader->open(); + if (openResult != 0) { + LOGD("%s() could not open " LIB_AAUDIO_NAME, __func__); + return AAUDIO_ERROR_UNAVAILABLE; + } + + void *libHandle = AAudioLoader::getInstance()->getLibHandle(); + if (libHandle == nullptr) { + LOGE("%s() could not find " LIB_AAUDIO_NAME, __func__); + return AAUDIO_ERROR_UNAVAILABLE; + } + + mAAudioStream_isMMap = (bool (*)(AAudioStream *stream)) + dlsym(libHandle, FUNCTION_IS_MMAP); + if (mAAudioStream_isMMap == nullptr) { + LOGI("%s() could not find " FUNCTION_IS_MMAP, __func__); + return AAUDIO_ERROR_UNAVAILABLE; + } + + mAAudio_setMMapPolicy = (int32_t (*)(aaudio_policy_t policy)) + dlsym(libHandle, FUNCTION_SET_MMAP_POLICY); + if (mAAudio_setMMapPolicy == nullptr) { + LOGI("%s() could not find " FUNCTION_SET_MMAP_POLICY, __func__); + return AAUDIO_ERROR_UNAVAILABLE; + } + + mAAudio_getMMapPolicy = (aaudio_policy_t (*)()) + dlsym(libHandle, FUNCTION_GET_MMAP_POLICY); + if (mAAudio_getMMapPolicy == nullptr) { + LOGI("%s() could not find " FUNCTION_GET_MMAP_POLICY, __func__); + return AAUDIO_ERROR_UNAVAILABLE; + } + + return 0; + } + + bool mMMapSupported = false; + bool mMMapExclusiveSupported = false; + + bool (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr; + int32_t (*mAAudio_setMMapPolicy)(aaudio_policy_t policy) = nullptr; + aaudio_policy_t (*mAAudio_getMMapPolicy)() = nullptr; +}; + +} // namespace oboe + +#endif //OBOE_AAUDIO_EXTENSIONS_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioLoader_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioLoader_android.cpp new file mode 100644 index 0000000..ae0f45f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioLoader_android.cpp @@ -0,0 +1,450 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_oboe_Utilities_android.h" +#include "oboe_common_OboeDebug_android.h" +#include "oboe_aaudio_AAudioLoader_android.h" + +#define LIB_AAUDIO_NAME "libaaudio.so" + +namespace oboe { + +AAudioLoader::~AAudioLoader() { + // Issue 360: thread_local variables with non-trivial destructors + // will cause segfaults if the containing library is dlclose()ed on + // devices running M or newer, or devices before M when using a static STL. + // The simple workaround is to not call dlclose. + // https://github.com/android/ndk/wiki/Changelog-r22#known-issues + // + // The libaaudio and libaaudioclient do not use thread_local. + // But, to be safe, we should avoid dlclose() if possible. + // Because AAudioLoader is a static Singleton, we can safely skip + // calling dlclose() without causing a resource leak. + LOGI("%s() dlclose(%s) not called, OK", __func__, LIB_AAUDIO_NAME); +} + +AAudioLoader* AAudioLoader::getInstance() { + static AAudioLoader instance; + return &instance; +} + +int AAudioLoader::open() { + if (mLibHandle != nullptr) { + return 0; + } + + // Use RTLD_NOW to avoid the unpredictable behavior that RTLD_LAZY can cause. + // Also resolving all the links now will prevent a run-time penalty later. + mLibHandle = dlopen(LIB_AAUDIO_NAME, RTLD_NOW); + if (mLibHandle == nullptr) { + LOGI("AAudioLoader::open() could not find " LIB_AAUDIO_NAME); + return -1; // TODO review return code + } else { + LOGD("AAudioLoader(): dlopen(%s) returned %p", LIB_AAUDIO_NAME, mLibHandle); + } + + // Load all the function pointers. + createStreamBuilder = load_I_PPB("AAudio_createStreamBuilder"); + builder_openStream = load_I_PBPPS("AAudioStreamBuilder_openStream"); + + builder_setChannelCount = load_V_PBI("AAudioStreamBuilder_setChannelCount"); + if (builder_setChannelCount == nullptr) { + // Use old deprecated alias if needed. + builder_setChannelCount = load_V_PBI("AAudioStreamBuilder_setSamplesPerFrame"); + } + + builder_setBufferCapacityInFrames = load_V_PBI("AAudioStreamBuilder_setBufferCapacityInFrames"); + builder_setDeviceId = load_V_PBI("AAudioStreamBuilder_setDeviceId"); + builder_setDirection = load_V_PBI("AAudioStreamBuilder_setDirection"); + builder_setFormat = load_V_PBI("AAudioStreamBuilder_setFormat"); + builder_setFramesPerDataCallback = load_V_PBI("AAudioStreamBuilder_setFramesPerDataCallback"); + builder_setSharingMode = load_V_PBI("AAudioStreamBuilder_setSharingMode"); + builder_setPerformanceMode = load_V_PBI("AAudioStreamBuilder_setPerformanceMode"); + builder_setSampleRate = load_V_PBI("AAudioStreamBuilder_setSampleRate"); + + if (getSdkVersion() >= __ANDROID_API_P__){ + builder_setUsage = load_V_PBI("AAudioStreamBuilder_setUsage"); + builder_setContentType = load_V_PBI("AAudioStreamBuilder_setContentType"); + builder_setInputPreset = load_V_PBI("AAudioStreamBuilder_setInputPreset"); + builder_setSessionId = load_V_PBI("AAudioStreamBuilder_setSessionId"); + } + + if (getSdkVersion() >= __ANDROID_API_S__){ + builder_setPackageName = load_V_PBCPH("AAudioStreamBuilder_setPackageName"); + builder_setAttributionTag = load_V_PBCPH("AAudioStreamBuilder_setAttributionTag"); + } + + if (getSdkVersion() >= __ANDROID_API_S_V2__) { + builder_setChannelMask = load_V_PBU("AAudioStreamBuilder_setChannelMask"); + } + + builder_delete = load_I_PB("AAudioStreamBuilder_delete"); + + + builder_setDataCallback = load_V_PBPDPV("AAudioStreamBuilder_setDataCallback"); + builder_setErrorCallback = load_V_PBPEPV("AAudioStreamBuilder_setErrorCallback"); + + stream_read = load_I_PSPVIL("AAudioStream_read"); + + stream_write = load_I_PSCPVIL("AAudioStream_write"); + + stream_waitForStateChange = load_I_PSTPTL("AAudioStream_waitForStateChange"); + + stream_getTimestamp = load_I_PSKPLPL("AAudioStream_getTimestamp"); + + stream_getChannelCount = load_I_PS("AAudioStream_getChannelCount"); + if (stream_getChannelCount == nullptr) { + // Use old alias if needed. + stream_getChannelCount = load_I_PS("AAudioStream_getSamplesPerFrame"); + } + + stream_close = load_I_PS("AAudioStream_close"); + + stream_getBufferSize = load_I_PS("AAudioStream_getBufferSizeInFrames"); + stream_getDeviceId = load_I_PS("AAudioStream_getDeviceId"); + stream_getBufferCapacity = load_I_PS("AAudioStream_getBufferCapacityInFrames"); + stream_getFormat = load_F_PS("AAudioStream_getFormat"); + stream_getFramesPerBurst = load_I_PS("AAudioStream_getFramesPerBurst"); + stream_getFramesRead = load_L_PS("AAudioStream_getFramesRead"); + stream_getFramesWritten = load_L_PS("AAudioStream_getFramesWritten"); + stream_getPerformanceMode = load_I_PS("AAudioStream_getPerformanceMode"); + stream_getSampleRate = load_I_PS("AAudioStream_getSampleRate"); + stream_getSharingMode = load_I_PS("AAudioStream_getSharingMode"); + stream_getState = load_I_PS("AAudioStream_getState"); + stream_getXRunCount = load_I_PS("AAudioStream_getXRunCount"); + + stream_requestStart = load_I_PS("AAudioStream_requestStart"); + stream_requestPause = load_I_PS("AAudioStream_requestPause"); + stream_requestFlush = load_I_PS("AAudioStream_requestFlush"); + stream_requestStop = load_I_PS("AAudioStream_requestStop"); + + stream_setBufferSize = load_I_PSI("AAudioStream_setBufferSizeInFrames"); + + convertResultToText = load_CPH_I("AAudio_convertResultToText"); + + if (getSdkVersion() >= __ANDROID_API_P__){ + stream_getUsage = load_I_PS("AAudioStream_getUsage"); + stream_getContentType = load_I_PS("AAudioStream_getContentType"); + stream_getInputPreset = load_I_PS("AAudioStream_getInputPreset"); + stream_getSessionId = load_I_PS("AAudioStream_getSessionId"); + } + + if (getSdkVersion() >= __ANDROID_API_S_V2__) { + stream_getChannelMask = load_U_PS("AAudioStream_getChannelMask"); + } + return 0; +} + +static void AAudioLoader_check(void *proc, const char *functionName) { + if (proc == nullptr) { + LOGW("AAudioLoader could not find %s", functionName); + } +} + +AAudioLoader::signature_I_PPB AAudioLoader::load_I_PPB(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_CPH_I AAudioLoader::load_CPH_I(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_V_PBI AAudioLoader::load_V_PBI(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_V_PBCPH AAudioLoader::load_V_PBCPH(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_V_PBPDPV AAudioLoader::load_V_PBPDPV(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_V_PBPEPV AAudioLoader::load_V_PBPEPV(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PSI AAudioLoader::load_I_PSI(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PS AAudioLoader::load_I_PS(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_L_PS AAudioLoader::load_L_PS(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_F_PS AAudioLoader::load_F_PS(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_B_PS AAudioLoader::load_B_PS(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PB AAudioLoader::load_I_PB(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PBPPS AAudioLoader::load_I_PBPPS(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PSCPVIL AAudioLoader::load_I_PSCPVIL(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PSPVIL AAudioLoader::load_I_PSPVIL(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PSTPTL AAudioLoader::load_I_PSTPTL(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_I_PSKPLPL AAudioLoader::load_I_PSKPLPL(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_V_PBU AAudioLoader::load_V_PBU(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +AAudioLoader::signature_U_PS AAudioLoader::load_U_PS(const char *functionName) { + void *proc = dlsym(mLibHandle, functionName); + AAudioLoader_check(proc, functionName); + return reinterpret_cast(proc); +} + +// Ensure that all AAudio primitive data types are int32_t +#define ASSERT_INT32(type) static_assert(std::is_same::value, \ +#type" must be int32_t") + +// Ensure that all AAudio primitive data types are uint32_t +#define ASSERT_UINT32(type) static_assert(std::is_same::value, \ +#type" must be uint32_t") + +#define ERRMSG "Oboe constants must match AAudio constants." + +// These asserts help verify that the Oboe definitions match the equivalent AAudio definitions. +// This code is in this .cpp file so it only gets tested once. +#ifdef AAUDIO_AAUDIO_H + + ASSERT_INT32(aaudio_stream_state_t); + ASSERT_INT32(aaudio_direction_t); + ASSERT_INT32(aaudio_format_t); + ASSERT_INT32(aaudio_data_callback_result_t); + ASSERT_INT32(aaudio_result_t); + ASSERT_INT32(aaudio_sharing_mode_t); + ASSERT_INT32(aaudio_performance_mode_t); + + static_assert((int32_t)StreamState::Uninitialized == AAUDIO_STREAM_STATE_UNINITIALIZED, ERRMSG); + static_assert((int32_t)StreamState::Unknown == AAUDIO_STREAM_STATE_UNKNOWN, ERRMSG); + static_assert((int32_t)StreamState::Open == AAUDIO_STREAM_STATE_OPEN, ERRMSG); + static_assert((int32_t)StreamState::Starting == AAUDIO_STREAM_STATE_STARTING, ERRMSG); + static_assert((int32_t)StreamState::Started == AAUDIO_STREAM_STATE_STARTED, ERRMSG); + static_assert((int32_t)StreamState::Pausing == AAUDIO_STREAM_STATE_PAUSING, ERRMSG); + static_assert((int32_t)StreamState::Paused == AAUDIO_STREAM_STATE_PAUSED, ERRMSG); + static_assert((int32_t)StreamState::Flushing == AAUDIO_STREAM_STATE_FLUSHING, ERRMSG); + static_assert((int32_t)StreamState::Flushed == AAUDIO_STREAM_STATE_FLUSHED, ERRMSG); + static_assert((int32_t)StreamState::Stopping == AAUDIO_STREAM_STATE_STOPPING, ERRMSG); + static_assert((int32_t)StreamState::Stopped == AAUDIO_STREAM_STATE_STOPPED, ERRMSG); + static_assert((int32_t)StreamState::Closing == AAUDIO_STREAM_STATE_CLOSING, ERRMSG); + static_assert((int32_t)StreamState::Closed == AAUDIO_STREAM_STATE_CLOSED, ERRMSG); + static_assert((int32_t)StreamState::Disconnected == AAUDIO_STREAM_STATE_DISCONNECTED, ERRMSG); + + static_assert((int32_t)Direction::Output == AAUDIO_DIRECTION_OUTPUT, ERRMSG); + static_assert((int32_t)Direction::Input == AAUDIO_DIRECTION_INPUT, ERRMSG); + + static_assert((int32_t)AudioFormat::Invalid == AAUDIO_FORMAT_INVALID, ERRMSG); + static_assert((int32_t)AudioFormat::Unspecified == AAUDIO_FORMAT_UNSPECIFIED, ERRMSG); + static_assert((int32_t)AudioFormat::I16 == AAUDIO_FORMAT_PCM_I16, ERRMSG); + static_assert((int32_t)AudioFormat::Float == AAUDIO_FORMAT_PCM_FLOAT, ERRMSG); + + static_assert((int32_t)DataCallbackResult::Continue == AAUDIO_CALLBACK_RESULT_CONTINUE, ERRMSG); + static_assert((int32_t)DataCallbackResult::Stop == AAUDIO_CALLBACK_RESULT_STOP, ERRMSG); + + static_assert((int32_t)Result::OK == AAUDIO_OK, ERRMSG); + static_assert((int32_t)Result::ErrorBase == AAUDIO_ERROR_BASE, ERRMSG); + static_assert((int32_t)Result::ErrorDisconnected == AAUDIO_ERROR_DISCONNECTED, ERRMSG); + static_assert((int32_t)Result::ErrorIllegalArgument == AAUDIO_ERROR_ILLEGAL_ARGUMENT, ERRMSG); + static_assert((int32_t)Result::ErrorInternal == AAUDIO_ERROR_INTERNAL, ERRMSG); + static_assert((int32_t)Result::ErrorInvalidState == AAUDIO_ERROR_INVALID_STATE, ERRMSG); + static_assert((int32_t)Result::ErrorInvalidHandle == AAUDIO_ERROR_INVALID_HANDLE, ERRMSG); + static_assert((int32_t)Result::ErrorUnimplemented == AAUDIO_ERROR_UNIMPLEMENTED, ERRMSG); + static_assert((int32_t)Result::ErrorUnavailable == AAUDIO_ERROR_UNAVAILABLE, ERRMSG); + static_assert((int32_t)Result::ErrorNoFreeHandles == AAUDIO_ERROR_NO_FREE_HANDLES, ERRMSG); + static_assert((int32_t)Result::ErrorNoMemory == AAUDIO_ERROR_NO_MEMORY, ERRMSG); + static_assert((int32_t)Result::ErrorNull == AAUDIO_ERROR_NULL, ERRMSG); + static_assert((int32_t)Result::ErrorTimeout == AAUDIO_ERROR_TIMEOUT, ERRMSG); + static_assert((int32_t)Result::ErrorWouldBlock == AAUDIO_ERROR_WOULD_BLOCK, ERRMSG); + static_assert((int32_t)Result::ErrorInvalidFormat == AAUDIO_ERROR_INVALID_FORMAT, ERRMSG); + static_assert((int32_t)Result::ErrorOutOfRange == AAUDIO_ERROR_OUT_OF_RANGE, ERRMSG); + static_assert((int32_t)Result::ErrorNoService == AAUDIO_ERROR_NO_SERVICE, ERRMSG); + static_assert((int32_t)Result::ErrorInvalidRate == AAUDIO_ERROR_INVALID_RATE, ERRMSG); + + static_assert((int32_t)SharingMode::Exclusive == AAUDIO_SHARING_MODE_EXCLUSIVE, ERRMSG); + static_assert((int32_t)SharingMode::Shared == AAUDIO_SHARING_MODE_SHARED, ERRMSG); + + static_assert((int32_t)PerformanceMode::None == AAUDIO_PERFORMANCE_MODE_NONE, ERRMSG); + static_assert((int32_t)PerformanceMode::PowerSaving + == AAUDIO_PERFORMANCE_MODE_POWER_SAVING, ERRMSG); + static_assert((int32_t)PerformanceMode::LowLatency + == AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, ERRMSG); + +// The aaudio_ usage, content and input_preset types were added in NDK 17, +// which is the first version to support Android Pie (API 28). +#if __NDK_MAJOR__ >= 17 + + ASSERT_INT32(aaudio_usage_t); + ASSERT_INT32(aaudio_content_type_t); + ASSERT_INT32(aaudio_input_preset_t); + + static_assert((int32_t)Usage::Media == AAUDIO_USAGE_MEDIA, ERRMSG); + static_assert((int32_t)Usage::VoiceCommunication == AAUDIO_USAGE_VOICE_COMMUNICATION, ERRMSG); + static_assert((int32_t)Usage::VoiceCommunicationSignalling + == AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, ERRMSG); + static_assert((int32_t)Usage::Alarm == AAUDIO_USAGE_ALARM, ERRMSG); + static_assert((int32_t)Usage::Notification == AAUDIO_USAGE_NOTIFICATION, ERRMSG); + static_assert((int32_t)Usage::NotificationRingtone == AAUDIO_USAGE_NOTIFICATION_RINGTONE, ERRMSG); + static_assert((int32_t)Usage::NotificationEvent == AAUDIO_USAGE_NOTIFICATION_EVENT, ERRMSG); + static_assert((int32_t)Usage::AssistanceAccessibility == AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY, ERRMSG); + static_assert((int32_t)Usage::AssistanceNavigationGuidance + == AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, ERRMSG); + static_assert((int32_t)Usage::AssistanceSonification == AAUDIO_USAGE_ASSISTANCE_SONIFICATION, ERRMSG); + static_assert((int32_t)Usage::Game == AAUDIO_USAGE_GAME, ERRMSG); + static_assert((int32_t)Usage::Assistant == AAUDIO_USAGE_ASSISTANT, ERRMSG); + + static_assert((int32_t)ContentType::Speech == AAUDIO_CONTENT_TYPE_SPEECH, ERRMSG); + static_assert((int32_t)ContentType::Music == AAUDIO_CONTENT_TYPE_MUSIC, ERRMSG); + static_assert((int32_t)ContentType::Movie == AAUDIO_CONTENT_TYPE_MOVIE, ERRMSG); + static_assert((int32_t)ContentType::Sonification == AAUDIO_CONTENT_TYPE_SONIFICATION, ERRMSG); + + static_assert((int32_t)InputPreset::Generic == AAUDIO_INPUT_PRESET_GENERIC, ERRMSG); + static_assert((int32_t)InputPreset::Camcorder == AAUDIO_INPUT_PRESET_CAMCORDER, ERRMSG); + static_assert((int32_t)InputPreset::VoiceRecognition == AAUDIO_INPUT_PRESET_VOICE_RECOGNITION, ERRMSG); + static_assert((int32_t)InputPreset::VoiceCommunication + == AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION, ERRMSG); + static_assert((int32_t)InputPreset::Unprocessed == AAUDIO_INPUT_PRESET_UNPROCESSED, ERRMSG); + + static_assert((int32_t)SessionId::None == AAUDIO_SESSION_ID_NONE, ERRMSG); + static_assert((int32_t)SessionId::Allocate == AAUDIO_SESSION_ID_ALLOCATE, ERRMSG); + +#endif // __NDK_MAJOR__ >= 17 + +// The aaudio channel masks were added in NDK 24, +// which is the first version to support Android SC_V2 (API 32). +#if __NDK_MAJOR__ >= 24 + + ASSERT_UINT32(aaudio_channel_mask_t); + + static_assert((uint32_t)ChannelMask::FrontLeft == AAUDIO_CHANNEL_FRONT_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontRight == AAUDIO_CHANNEL_FRONT_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontCenter == AAUDIO_CHANNEL_FRONT_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::LowFrequency == AAUDIO_CHANNEL_LOW_FREQUENCY, ERRMSG); + static_assert((uint32_t)ChannelMask::BackLeft == AAUDIO_CHANNEL_BACK_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::BackRight == AAUDIO_CHANNEL_BACK_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontLeftOfCenter == AAUDIO_CHANNEL_FRONT_LEFT_OF_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontRightOfCenter == AAUDIO_CHANNEL_FRONT_RIGHT_OF_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::BackCenter == AAUDIO_CHANNEL_BACK_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::SideLeft == AAUDIO_CHANNEL_SIDE_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::SideRight == AAUDIO_CHANNEL_SIDE_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::TopCenter == AAUDIO_CHANNEL_TOP_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::TopFrontLeft == AAUDIO_CHANNEL_TOP_FRONT_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::TopFrontCenter == AAUDIO_CHANNEL_TOP_FRONT_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::TopFrontRight == AAUDIO_CHANNEL_TOP_FRONT_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::TopBackLeft == AAUDIO_CHANNEL_TOP_BACK_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::TopBackCenter == AAUDIO_CHANNEL_TOP_BACK_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::TopBackRight == AAUDIO_CHANNEL_TOP_BACK_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::TopSideLeft == AAUDIO_CHANNEL_TOP_SIDE_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::TopSideRight == AAUDIO_CHANNEL_TOP_SIDE_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::BottomFrontLeft == AAUDIO_CHANNEL_BOTTOM_FRONT_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::BottomFrontCenter == AAUDIO_CHANNEL_BOTTOM_FRONT_CENTER, ERRMSG); + static_assert((uint32_t)ChannelMask::BottomFrontRight == AAUDIO_CHANNEL_BOTTOM_FRONT_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::LowFrequency2 == AAUDIO_CHANNEL_LOW_FREQUENCY_2, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontWideLeft == AAUDIO_CHANNEL_FRONT_WIDE_LEFT, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontWideRight == AAUDIO_CHANNEL_FRONT_WIDE_RIGHT, ERRMSG); + static_assert((uint32_t)ChannelMask::Mono == AAUDIO_CHANNEL_MONO, ERRMSG); + static_assert((uint32_t)ChannelMask::Stereo == AAUDIO_CHANNEL_STEREO, ERRMSG); + static_assert((uint32_t)ChannelMask::CM2Point1 == AAUDIO_CHANNEL_2POINT1, ERRMSG); + static_assert((uint32_t)ChannelMask::Tri == AAUDIO_CHANNEL_TRI, ERRMSG); + static_assert((uint32_t)ChannelMask::TriBack == AAUDIO_CHANNEL_TRI_BACK, ERRMSG); + static_assert((uint32_t)ChannelMask::CM3Point1 == AAUDIO_CHANNEL_3POINT1, ERRMSG); + static_assert((uint32_t)ChannelMask::CM2Point0Point2 == AAUDIO_CHANNEL_2POINT0POINT2, ERRMSG); + static_assert((uint32_t)ChannelMask::CM2Point1Point2 == AAUDIO_CHANNEL_2POINT1POINT2, ERRMSG); + static_assert((uint32_t)ChannelMask::CM3Point0Point2 == AAUDIO_CHANNEL_3POINT0POINT2, ERRMSG); + static_assert((uint32_t)ChannelMask::CM3Point1Point2 == AAUDIO_CHANNEL_3POINT1POINT2, ERRMSG); + static_assert((uint32_t)ChannelMask::Quad == AAUDIO_CHANNEL_QUAD, ERRMSG); + static_assert((uint32_t)ChannelMask::QuadSide == AAUDIO_CHANNEL_QUAD_SIDE, ERRMSG); + static_assert((uint32_t)ChannelMask::Surround == AAUDIO_CHANNEL_SURROUND, ERRMSG); + static_assert((uint32_t)ChannelMask::Penta == AAUDIO_CHANNEL_PENTA, ERRMSG); + static_assert((uint32_t)ChannelMask::CM5Point1 == AAUDIO_CHANNEL_5POINT1, ERRMSG); + static_assert((uint32_t)ChannelMask::CM5Point1Side == AAUDIO_CHANNEL_5POINT1_SIDE, ERRMSG); + static_assert((uint32_t)ChannelMask::CM6Point1 == AAUDIO_CHANNEL_6POINT1, ERRMSG); + static_assert((uint32_t)ChannelMask::CM7Point1 == AAUDIO_CHANNEL_7POINT1, ERRMSG); + static_assert((uint32_t)ChannelMask::CM5Point1Point2 == AAUDIO_CHANNEL_5POINT1POINT2, ERRMSG); + static_assert((uint32_t)ChannelMask::CM5Point1Point4 == AAUDIO_CHANNEL_5POINT1POINT4, ERRMSG); + static_assert((uint32_t)ChannelMask::CM7Point1Point2 == AAUDIO_CHANNEL_7POINT1POINT2, ERRMSG); + static_assert((uint32_t)ChannelMask::CM7Point1Point4 == AAUDIO_CHANNEL_7POINT1POINT4, ERRMSG); + static_assert((uint32_t)ChannelMask::CM9Point1Point4 == AAUDIO_CHANNEL_9POINT1POINT4, ERRMSG); + static_assert((uint32_t)ChannelMask::CM9Point1Point6 == AAUDIO_CHANNEL_9POINT1POINT6, ERRMSG); + static_assert((uint32_t)ChannelMask::FrontBack == AAUDIO_CHANNEL_FRONT_BACK, ERRMSG); + +#endif + +#endif // AAUDIO_AAUDIO_H + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioLoader_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioLoader_android.h new file mode 100644 index 0000000..8f23558 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AAudioLoader_android.h @@ -0,0 +1,263 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_AAUDIO_LOADER_H_ +#define OBOE_AAUDIO_LOADER_H_ + +#include +#include "oboe_oboe_Definitions_android.h" + +// If the NDK is before O then define this in your build +// so that AAudio.h will not be included. +#ifdef OBOE_NO_INCLUDE_AAUDIO + +// Define missing types from AAudio.h +typedef int32_t aaudio_stream_state_t; +typedef int32_t aaudio_direction_t; +typedef int32_t aaudio_format_t; +typedef int32_t aaudio_data_callback_result_t; +typedef int32_t aaudio_result_t; +typedef int32_t aaudio_sharing_mode_t; +typedef int32_t aaudio_performance_mode_t; + +typedef struct AAudioStreamStruct AAudioStream; +typedef struct AAudioStreamBuilderStruct AAudioStreamBuilder; + +typedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)( + AAudioStream *stream, + void *userData, + void *audioData, + int32_t numFrames); + +typedef void (*AAudioStream_errorCallback)( + AAudioStream *stream, + void *userData, + aaudio_result_t error); + +// These were defined in P +typedef int32_t aaudio_usage_t; +typedef int32_t aaudio_content_type_t; +typedef int32_t aaudio_input_preset_t; +typedef int32_t aaudio_session_id_t; + +// There are a few definitions used by Oboe. +#define AAUDIO_OK static_cast(Result::OK) +#define AAUDIO_ERROR_TIMEOUT static_cast(Result::ErrorTimeout) +#define AAUDIO_STREAM_STATE_STARTING static_cast(StreamState::Starting) +#define AAUDIO_STREAM_STATE_STARTED static_cast(StreamState::Started) +#else +#include +#endif + +#ifndef __NDK_MAJOR__ +#define __NDK_MAJOR__ 0 +#endif + +#if __NDK_MAJOR__ < 24 +// Defined in SC_V2 +typedef uint32_t aaudio_channel_mask_t; +#endif + +#ifndef __ANDROID_API_S__ +#define __ANDROID_API_S__ 31 +#endif + +#ifndef __ANDROID_API_S_V2__ +#define __ANDROID_API_S_V2__ 32 +#endif + +namespace oboe { + +/** + * The AAudio API was not available in early versions of Android. + * To avoid linker errors, we dynamically link with the functions by name using dlsym(). + * On older versions this linkage will safely fail. + */ +class AAudioLoader { + public: + // Use signatures for common functions. + // Key to letter abbreviations. + // S = Stream + // B = Builder + // I = int32_t + // L = int64_t + // T = sTate + // K = clocKid_t + // P = Pointer to following data type + // C = Const prefix + // H = cHar + // U = uint32_t + typedef int32_t (*signature_I_PPB)(AAudioStreamBuilder **builder); + + typedef const char * (*signature_CPH_I)(int32_t); + + typedef int32_t (*signature_I_PBPPS)(AAudioStreamBuilder *, + AAudioStream **stream); // AAudioStreamBuilder_open() + + typedef int32_t (*signature_I_PB)(AAudioStreamBuilder *); // AAudioStreamBuilder_delete() + // AAudioStreamBuilder_setSampleRate() + typedef void (*signature_V_PBI)(AAudioStreamBuilder *, int32_t); + + // AAudioStreamBuilder_setChannelMask() + typedef void (*signature_V_PBU)(AAudioStreamBuilder *, uint32_t); + + typedef void (*signature_V_PBCPH)(AAudioStreamBuilder *, const char *); + + typedef int32_t (*signature_I_PS)(AAudioStream *); // AAudioStream_getSampleRate() + typedef int64_t (*signature_L_PS)(AAudioStream *); // AAudioStream_getFramesRead() + // AAudioStream_setBufferSizeInFrames() + typedef int32_t (*signature_I_PSI)(AAudioStream *, int32_t); + + typedef void (*signature_V_PBPDPV)(AAudioStreamBuilder *, + AAudioStream_dataCallback, + void *); + + typedef void (*signature_V_PBPEPV)(AAudioStreamBuilder *, + AAudioStream_errorCallback, + void *); + + typedef aaudio_format_t (*signature_F_PS)(AAudioStream *stream); + + typedef int32_t (*signature_I_PSPVIL)(AAudioStream *, void *, int32_t, int64_t); + typedef int32_t (*signature_I_PSCPVIL)(AAudioStream *, const void *, int32_t, int64_t); + + typedef int32_t (*signature_I_PSTPTL)(AAudioStream *, + aaudio_stream_state_t, + aaudio_stream_state_t *, + int64_t); + + typedef int32_t (*signature_I_PSKPLPL)(AAudioStream *, clockid_t, int64_t *, int64_t *); + + typedef bool (*signature_B_PS)(AAudioStream *); + + typedef uint32_t (*signature_U_PS)(AAudioStream *); + + static AAudioLoader* getInstance(); // singleton + + /** + * Open the AAudio shared library and load the function pointers. + * This can be called multiple times. + * It should only be called from one thread. + * + * The destructor will clean up after the open. + * + * @return 0 if successful or negative error. + */ + int open(); + + void *getLibHandle() const { return mLibHandle; } + + // Function pointers into the AAudio shared library. + signature_I_PPB createStreamBuilder = nullptr; + + signature_I_PBPPS builder_openStream = nullptr; + + signature_V_PBI builder_setBufferCapacityInFrames = nullptr; + signature_V_PBI builder_setChannelCount = nullptr; + signature_V_PBI builder_setDeviceId = nullptr; + signature_V_PBI builder_setDirection = nullptr; + signature_V_PBI builder_setFormat = nullptr; + signature_V_PBI builder_setFramesPerDataCallback = nullptr; + signature_V_PBI builder_setPerformanceMode = nullptr; + signature_V_PBI builder_setSampleRate = nullptr; + signature_V_PBI builder_setSharingMode = nullptr; + signature_V_PBU builder_setChannelMask = nullptr; + + signature_V_PBI builder_setUsage = nullptr; + signature_V_PBI builder_setContentType = nullptr; + signature_V_PBI builder_setInputPreset = nullptr; + signature_V_PBI builder_setSessionId = nullptr; + + signature_V_PBCPH builder_setPackageName = nullptr; + signature_V_PBCPH builder_setAttributionTag = nullptr; + + signature_V_PBPDPV builder_setDataCallback = nullptr; + signature_V_PBPEPV builder_setErrorCallback = nullptr; + + signature_I_PB builder_delete = nullptr; + + signature_F_PS stream_getFormat = nullptr; + + signature_I_PSPVIL stream_read = nullptr; + signature_I_PSCPVIL stream_write = nullptr; + + signature_I_PSTPTL stream_waitForStateChange = nullptr; + + signature_I_PSKPLPL stream_getTimestamp = nullptr; + + signature_I_PS stream_close = nullptr; + + signature_I_PS stream_getChannelCount = nullptr; + signature_I_PS stream_getDeviceId = nullptr; + + signature_I_PS stream_getBufferSize = nullptr; + signature_I_PS stream_getBufferCapacity = nullptr; + signature_I_PS stream_getFramesPerBurst = nullptr; + signature_I_PS stream_getState = nullptr; + signature_I_PS stream_getPerformanceMode = nullptr; + signature_I_PS stream_getSampleRate = nullptr; + signature_I_PS stream_getSharingMode = nullptr; + signature_I_PS stream_getXRunCount = nullptr; + + signature_I_PSI stream_setBufferSize = nullptr; + signature_I_PS stream_requestStart = nullptr; + signature_I_PS stream_requestPause = nullptr; + signature_I_PS stream_requestFlush = nullptr; + signature_I_PS stream_requestStop = nullptr; + + signature_L_PS stream_getFramesRead = nullptr; + signature_L_PS stream_getFramesWritten = nullptr; + + signature_CPH_I convertResultToText = nullptr; + + signature_I_PS stream_getUsage = nullptr; + signature_I_PS stream_getContentType = nullptr; + signature_I_PS stream_getInputPreset = nullptr; + signature_I_PS stream_getSessionId = nullptr; + + signature_U_PS stream_getChannelMask = nullptr; + + private: + AAudioLoader() {} + ~AAudioLoader(); + + // Load function pointers for specific signatures. + signature_I_PPB load_I_PPB(const char *name); + signature_CPH_I load_CPH_I(const char *name); + signature_V_PBI load_V_PBI(const char *name); + signature_V_PBCPH load_V_PBCPH(const char *name); + signature_V_PBPDPV load_V_PBPDPV(const char *name); + signature_V_PBPEPV load_V_PBPEPV(const char *name); + signature_I_PB load_I_PB(const char *name); + signature_I_PBPPS load_I_PBPPS(const char *name); + signature_I_PS load_I_PS(const char *name); + signature_L_PS load_L_PS(const char *name); + signature_F_PS load_F_PS(const char *name); + signature_B_PS load_B_PS(const char *name); + signature_I_PSI load_I_PSI(const char *name); + signature_I_PSPVIL load_I_PSPVIL(const char *name); + signature_I_PSCPVIL load_I_PSCPVIL(const char *name); + signature_I_PSTPTL load_I_PSTPTL(const char *name); + signature_I_PSKPLPL load_I_PSKPLPL(const char *name); + signature_V_PBU load_V_PBU(const char *name); + signature_U_PS load_U_PS(const char *name); + + void *mLibHandle = nullptr; +}; + +} // namespace oboe + +#endif //OBOE_AAUDIO_LOADER_H_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AudioStreamAAudio_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AudioStreamAAudio_android.cpp new file mode 100644 index 0000000..2a987ac --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AudioStreamAAudio_android.cpp @@ -0,0 +1,729 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "oboe_aaudio_AAudioLoader_android.h" +#include "oboe_aaudio_AudioStreamAAudio_android.h" +#include "oboe_common_AudioClock_android.h" +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_Utilities_android.h" +#include "oboe_aaudio_AAudioExtensions_android.h" + +#ifdef __ANDROID__ +#include +#include "oboe_common_QuirksManager_android.h" + +#endif + +#ifndef OBOE_FIX_FORCE_STARTING_TO_STARTED +// Workaround state problems in AAudio +// TODO Which versions does this occur in? Verify fixed in Q. +#define OBOE_FIX_FORCE_STARTING_TO_STARTED 1 +#endif // OBOE_FIX_FORCE_STARTING_TO_STARTED + +using namespace oboe; +AAudioLoader *AudioStreamAAudio::mLibLoader = nullptr; + +// 'C' wrapper for the data callback method +static aaudio_data_callback_result_t oboe_aaudio_data_callback_proc( + AAudioStream *stream, + void *userData, + void *audioData, + int32_t numFrames) { + + AudioStreamAAudio *oboeStream = reinterpret_cast(userData); + if (oboeStream != nullptr) { + return static_cast( + oboeStream->callOnAudioReady(stream, audioData, numFrames)); + + } else { + return static_cast(DataCallbackResult::Stop); + } +} + +// This runs in its own thread. +// Only one of these threads will be launched from internalErrorCallback(). +// It calls app error callbacks from a static function in case the stream gets deleted. +static void oboe_aaudio_error_thread_proc(AudioStreamAAudio *oboeStream, + Result error) { + LOGD("%s(,%d) - entering >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", __func__, error); + AudioStreamErrorCallback *errorCallback = oboeStream->getErrorCallback(); + if (errorCallback == nullptr) return; // should be impossible + bool isErrorHandled = errorCallback->onError(oboeStream, error); + + if (!isErrorHandled) { + oboeStream->requestStop(); + errorCallback->onErrorBeforeClose(oboeStream, error); + oboeStream->close(); + // Warning, oboeStream may get deleted by this callback. + errorCallback->onErrorAfterClose(oboeStream, error); + } + LOGD("%s() - exiting <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", __func__); +} + +// This runs in its own thread. +// Only one of these threads will be launched from internalErrorCallback(). +// Prevents deletion of the stream if the app is using AudioStreamBuilder::openSharedStream() +static void oboe_aaudio_error_thread_proc_shared(std::shared_ptr sharedStream, + Result error) { + AudioStreamAAudio *oboeStream = reinterpret_cast(sharedStream.get()); + oboe_aaudio_error_thread_proc(oboeStream, error); +} + +namespace oboe { + +/* + * Create a stream that uses Oboe Audio API. + */ +AudioStreamAAudio::AudioStreamAAudio(const AudioStreamBuilder &builder) + : AudioStream(builder) + , mAAudioStream(nullptr) { + mCallbackThreadEnabled.store(false); + mLibLoader = AAudioLoader::getInstance(); +} + +bool AudioStreamAAudio::isSupported() { + mLibLoader = AAudioLoader::getInstance(); + int openResult = mLibLoader->open(); + return openResult == 0; +} + +// Static method for the error callback. +// We use a method so we can access protected methods on the stream. +// Launch a thread to handle the error. +// That other thread can safely stop, close and delete the stream. +void AudioStreamAAudio::internalErrorCallback( + AAudioStream *stream, + void *userData, + aaudio_result_t error) { + oboe::Result oboeResult = static_cast(error); + AudioStreamAAudio *oboeStream = reinterpret_cast(userData); + + // Coerce the error code if needed to workaround a regression in RQ1A that caused + // the wrong code to be passed when headsets plugged in. See b/173928197. + if (OboeGlobals::areWorkaroundsEnabled() + && getSdkVersion() == __ANDROID_API_R__ + && oboeResult == oboe::Result::ErrorTimeout) { + oboeResult = oboe::Result::ErrorDisconnected; + LOGD("%s() ErrorTimeout changed to ErrorDisconnected to fix b/173928197", __func__); + } + + oboeStream->mErrorCallbackResult = oboeResult; + + // Prevents deletion of the stream if the app is using AudioStreamBuilder::openStream(shared_ptr) + std::shared_ptr sharedStream = oboeStream->lockWeakThis(); + + // These checks should be enough because we assume that the stream close() + // will join() any active callback threads and will not allow new callbacks. + if (oboeStream->wasErrorCallbackCalled()) { // block extra error callbacks + LOGE("%s() multiple error callbacks called!", __func__); + } else if (stream != oboeStream->getUnderlyingStream()) { + LOGW("%s() stream already closed or closing", __func__); // might happen if there are bugs + } else if (sharedStream) { + // Handle error on a separate thread using shared pointer. + std::thread t(oboe_aaudio_error_thread_proc_shared, sharedStream, oboeResult); + t.detach(); + } else { + // Handle error on a separate thread. + std::thread t(oboe_aaudio_error_thread_proc, oboeStream, oboeResult); + t.detach(); + } +} + +void AudioStreamAAudio::logUnsupportedAttributes() { + int sdkVersion = getSdkVersion(); + + // These attributes are not supported pre Android "P" + if (sdkVersion < __ANDROID_API_P__) { + if (mUsage != Usage::Media) { + LOGW("Usage [AudioStreamBuilder::setUsage()] " + "is not supported on AAudio streams running on pre-Android P versions."); + } + + if (mContentType != ContentType::Music) { + LOGW("ContentType [AudioStreamBuilder::setContentType()] " + "is not supported on AAudio streams running on pre-Android P versions."); + } + + if (mSessionId != SessionId::None) { + LOGW("SessionId [AudioStreamBuilder::setSessionId()] " + "is not supported on AAudio streams running on pre-Android P versions."); + } + } +} + +Result AudioStreamAAudio::open() { + Result result = Result::OK; + + if (mAAudioStream != nullptr) { + return Result::ErrorInvalidState; + } + + result = AudioStream::open(); + if (result != Result::OK) { + return result; + } + + AAudioStreamBuilder *aaudioBuilder; + result = static_cast(mLibLoader->createStreamBuilder(&aaudioBuilder)); + if (result != Result::OK) { + return result; + } + + // Do not set INPUT capacity below 4096 because that prevents us from getting a FAST track + // when using the Legacy data path. + // If the app requests > 4096 then we allow it but we are less likely to get LowLatency. + // See internal bug b/80308183 for more details. + // Fixed in Q but let's still clip the capacity because high input capacity + // does not increase latency. + int32_t capacity = mBufferCapacityInFrames; + constexpr int kCapacityRequiredForFastLegacyTrack = 4096; // matches value in AudioFinger + if (OboeGlobals::areWorkaroundsEnabled() + && mDirection == oboe::Direction::Input + && capacity != oboe::Unspecified + && capacity < kCapacityRequiredForFastLegacyTrack + && mPerformanceMode == oboe::PerformanceMode::LowLatency) { + capacity = kCapacityRequiredForFastLegacyTrack; + LOGD("AudioStreamAAudio.open() capacity changed from %d to %d for lower latency", + static_cast(mBufferCapacityInFrames), capacity); + } + mLibLoader->builder_setBufferCapacityInFrames(aaudioBuilder, capacity); + + // Channel mask was added in SC_V2. Given the corresponding channel count of selected channel + // mask may be different from selected channel count, the last set value will be respected. + // If channel count is set after channel mask, the previously set channel mask will be cleared. + // If channel mask is set after channel count, the channel count will be automatically + // calculated from selected channel mask. In that case, only set channel mask when the API + // is available and the channel mask is specified. + if (mLibLoader->builder_setChannelMask != nullptr && mChannelMask != ChannelMask::Unspecified) { + mLibLoader->builder_setChannelMask(aaudioBuilder, + static_cast(mChannelMask)); + } else { + mLibLoader->builder_setChannelCount(aaudioBuilder, mChannelCount); + } + mLibLoader->builder_setDeviceId(aaudioBuilder, mDeviceId); + mLibLoader->builder_setDirection(aaudioBuilder, static_cast(mDirection)); + mLibLoader->builder_setFormat(aaudioBuilder, static_cast(mFormat)); + mLibLoader->builder_setSampleRate(aaudioBuilder, mSampleRate); + mLibLoader->builder_setSharingMode(aaudioBuilder, + static_cast(mSharingMode)); + mLibLoader->builder_setPerformanceMode(aaudioBuilder, + static_cast(mPerformanceMode)); + + // These were added in P so we have to check for the function pointer. + if (mLibLoader->builder_setUsage != nullptr) { + mLibLoader->builder_setUsage(aaudioBuilder, + static_cast(mUsage)); + } + + if (mLibLoader->builder_setContentType != nullptr) { + mLibLoader->builder_setContentType(aaudioBuilder, + static_cast(mContentType)); + } + + if (mLibLoader->builder_setInputPreset != nullptr) { + aaudio_input_preset_t inputPreset = mInputPreset; + if (getSdkVersion() <= __ANDROID_API_P__ && inputPreset == InputPreset::VoicePerformance) { + LOGD("InputPreset::VoicePerformance not supported before Q. Using VoiceRecognition."); + inputPreset = InputPreset::VoiceRecognition; // most similar preset + } + mLibLoader->builder_setInputPreset(aaudioBuilder, + static_cast(inputPreset)); + } + + if (mLibLoader->builder_setSessionId != nullptr) { + mLibLoader->builder_setSessionId(aaudioBuilder, + static_cast(mSessionId)); + } + + // These were added in S so we have to check for the function pointer. + if (mLibLoader->builder_setPackageName != nullptr && !mPackageName.empty()) { + mLibLoader->builder_setPackageName(aaudioBuilder, + mPackageName.c_str()); + } + + if (mLibLoader->builder_setAttributionTag != nullptr && !mAttributionTag.empty()) { + mLibLoader->builder_setAttributionTag(aaudioBuilder, + mAttributionTag.c_str()); + } + + if (isDataCallbackSpecified()) { + mLibLoader->builder_setDataCallback(aaudioBuilder, oboe_aaudio_data_callback_proc, this); + mLibLoader->builder_setFramesPerDataCallback(aaudioBuilder, getFramesPerDataCallback()); + + if (!isErrorCallbackSpecified()) { + // The app did not specify a callback so we should specify + // our own so the stream gets closed and stopped. + mErrorCallback = &mDefaultErrorCallback; + } + mLibLoader->builder_setErrorCallback(aaudioBuilder, internalErrorCallback, this); + } + // Else if the data callback is not being used then the write method will return an error + // and the app can stop and close the stream. + + // ============= OPEN THE STREAM ================ + { + AAudioStream *stream = nullptr; + result = static_cast(mLibLoader->builder_openStream(aaudioBuilder, &stream)); + mAAudioStream.store(stream); + } + if (result != Result::OK) { + // Warn developer because ErrorInternal is not very informative. + if (result == Result::ErrorInternal && mDirection == Direction::Input) { + LOGW("AudioStreamAAudio.open() may have failed due to lack of " + "audio recording permission."); + } + goto error2; + } + + // Query and cache the stream properties + mDeviceId = mLibLoader->stream_getDeviceId(mAAudioStream); + mChannelCount = mLibLoader->stream_getChannelCount(mAAudioStream); + mSampleRate = mLibLoader->stream_getSampleRate(mAAudioStream); + mFormat = static_cast(mLibLoader->stream_getFormat(mAAudioStream)); + mSharingMode = static_cast(mLibLoader->stream_getSharingMode(mAAudioStream)); + mPerformanceMode = static_cast( + mLibLoader->stream_getPerformanceMode(mAAudioStream)); + mBufferCapacityInFrames = mLibLoader->stream_getBufferCapacity(mAAudioStream); + mBufferSizeInFrames = mLibLoader->stream_getBufferSize(mAAudioStream); + mFramesPerBurst = mLibLoader->stream_getFramesPerBurst(mAAudioStream); + + // These were added in P so we have to check for the function pointer. + if (mLibLoader->stream_getUsage != nullptr) { + mUsage = static_cast(mLibLoader->stream_getUsage(mAAudioStream)); + } + if (mLibLoader->stream_getContentType != nullptr) { + mContentType = static_cast(mLibLoader->stream_getContentType(mAAudioStream)); + } + if (mLibLoader->stream_getInputPreset != nullptr) { + mInputPreset = static_cast(mLibLoader->stream_getInputPreset(mAAudioStream)); + } + if (mLibLoader->stream_getSessionId != nullptr) { + mSessionId = static_cast(mLibLoader->stream_getSessionId(mAAudioStream)); + } else { + mSessionId = SessionId::None; + } + + if (mLibLoader->stream_getChannelMask != nullptr) { + mChannelMask = static_cast(mLibLoader->stream_getChannelMask(mAAudioStream)); + } + + LOGD("AudioStreamAAudio.open() format=%d, sampleRate=%d, capacity = %d", + static_cast(mFormat), static_cast(mSampleRate), + static_cast(mBufferCapacityInFrames)); + + calculateDefaultDelayBeforeCloseMillis(); + +error2: + mLibLoader->builder_delete(aaudioBuilder); + LOGD("AudioStreamAAudio.open: AAudioStream_Open() returned %s", + mLibLoader->convertResultToText(static_cast(result))); + return result; +} + +Result AudioStreamAAudio::close() { + // Prevent two threads from closing the stream at the same time and crashing. + // This could occur, for example, if an application called close() at the same + // time that an onError callback was being executed because of a disconnect. + std::lock_guard lock(mLock); + + AudioStream::close(); + + AAudioStream *stream = nullptr; + { + // Wait for any methods using mAAudioStream to finish. + std::unique_lock lock2(mAAudioStreamLock); + // Closing will delete *mAAudioStream so we need to null out the pointer atomically. + stream = mAAudioStream.exchange(nullptr); + } + if (stream != nullptr) { + if (OboeGlobals::areWorkaroundsEnabled()) { + // Make sure we are really stopped. Do it under mLock + // so another thread cannot call requestStart() right before the close. + requestStop_l(stream); + sleepBeforeClose(); + } + return static_cast(mLibLoader->stream_close(stream)); + } else { + return Result::ErrorClosed; + } +} + +static void oboe_stop_thread_proc(AudioStream *oboeStream) { + if (oboeStream != nullptr) { + oboeStream->requestStop(); + } +} + +void AudioStreamAAudio::launchStopThread() { + // Prevent multiple stop threads from being launched. + if (mStopThreadAllowed.exchange(false)) { + // Stop this stream on a separate thread + std::thread t(oboe_stop_thread_proc, this); + t.detach(); + } +} + +DataCallbackResult AudioStreamAAudio::callOnAudioReady(AAudioStream * /*stream*/, + void *audioData, + int32_t numFrames) { + DataCallbackResult result = fireDataCallback(audioData, numFrames); + if (result == DataCallbackResult::Continue) { + return result; + } else { + if (result == DataCallbackResult::Stop) { + LOGD("Oboe callback returned DataCallbackResult::Stop"); + } else { + LOGE("Oboe callback returned unexpected value = %d", result); + } + + // Returning Stop caused various problems before S. See #1230 + if (OboeGlobals::areWorkaroundsEnabled() && getSdkVersion() <= __ANDROID_API_R__) { + launchStopThread(); + return DataCallbackResult::Continue; + } else { + return DataCallbackResult::Stop; // OK >= API_S + } + } +} + +Result AudioStreamAAudio::requestStart() { + std::lock_guard lock(mLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + // Avoid state machine errors in O_MR1. + if (getSdkVersion() <= __ANDROID_API_O_MR1__) { + StreamState state = static_cast(mLibLoader->stream_getState(stream)); + if (state == StreamState::Starting || state == StreamState::Started) { + // WARNING: On P, AAudio is returning ErrorInvalidState for Output and OK for Input. + return Result::OK; + } + } + if (isDataCallbackSpecified()) { + setDataCallbackEnabled(true); + } + mStopThreadAllowed = true; + return static_cast(mLibLoader->stream_requestStart(stream)); + } else { + return Result::ErrorClosed; + } +} + +Result AudioStreamAAudio::requestPause() { + std::lock_guard lock(mLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + // Avoid state machine errors in O_MR1. + if (getSdkVersion() <= __ANDROID_API_O_MR1__) { + StreamState state = static_cast(mLibLoader->stream_getState(stream)); + if (state == StreamState::Pausing || state == StreamState::Paused) { + return Result::OK; + } + } + return static_cast(mLibLoader->stream_requestPause(stream)); + } else { + return Result::ErrorClosed; + } +} + +Result AudioStreamAAudio::requestFlush() { + std::lock_guard lock(mLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + // Avoid state machine errors in O_MR1. + if (getSdkVersion() <= __ANDROID_API_O_MR1__) { + StreamState state = static_cast(mLibLoader->stream_getState(stream)); + if (state == StreamState::Flushing || state == StreamState::Flushed) { + return Result::OK; + } + } + return static_cast(mLibLoader->stream_requestFlush(stream)); + } else { + return Result::ErrorClosed; + } +} + +Result AudioStreamAAudio::requestStop() { + std::lock_guard lock(mLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + return requestStop_l(stream); + } else { + return Result::ErrorClosed; + } +} + +// Call under mLock +Result AudioStreamAAudio::requestStop_l(AAudioStream *stream) { + // Avoid state machine errors in O_MR1. + if (getSdkVersion() <= __ANDROID_API_O_MR1__) { + StreamState state = static_cast(mLibLoader->stream_getState(stream)); + if (state == StreamState::Stopping || state == StreamState::Stopped) { + return Result::OK; + } + } + return static_cast(mLibLoader->stream_requestStop(stream)); +} + +ResultWithValue AudioStreamAAudio::write(const void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + int32_t result = mLibLoader->stream_write(mAAudioStream, buffer, + numFrames, timeoutNanoseconds); + return ResultWithValue::createBasedOnSign(result); + } else { + return ResultWithValue(Result::ErrorClosed); + } +} + +ResultWithValue AudioStreamAAudio::read(void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + int32_t result = mLibLoader->stream_read(mAAudioStream, buffer, + numFrames, timeoutNanoseconds); + return ResultWithValue::createBasedOnSign(result); + } else { + return ResultWithValue(Result::ErrorClosed); + } +} + + +// AAudioStream_waitForStateChange() can crash if it is waiting on a stream and that stream +// is closed from another thread. We do not want to lock the stream for the duration of the call. +// So we call AAudioStream_waitForStateChange() with a timeout of zero so that it will not block. +// Then we can do our own sleep with the lock unlocked. +Result AudioStreamAAudio::waitForStateChange(StreamState currentState, + StreamState *nextState, + int64_t timeoutNanoseconds) { + Result oboeResult = Result::ErrorTimeout; + int64_t sleepTimeNanos = 20 * kNanosPerMillisecond; // arbitrary + aaudio_stream_state_t currentAAudioState = static_cast(currentState); + + aaudio_result_t result = AAUDIO_OK; + int64_t timeLeftNanos = timeoutNanoseconds; + + mLock.lock(); + while (true) { + // Do we still have an AAudio stream? If not then stream must have been closed. + AAudioStream *stream = mAAudioStream.load(); + if (stream == nullptr) { + if (nextState != nullptr) { + *nextState = StreamState::Closed; + } + oboeResult = Result::ErrorClosed; + break; + } + + // Update and query state change with no blocking. + aaudio_stream_state_t aaudioNextState; + result = mLibLoader->stream_waitForStateChange( + mAAudioStream, + currentAAudioState, + &aaudioNextState, + 0); // timeout=0 for non-blocking + // AAudio will return AAUDIO_ERROR_TIMEOUT if timeout=0 and the state does not change. + if (result != AAUDIO_OK && result != AAUDIO_ERROR_TIMEOUT) { + oboeResult = static_cast(result); + break; + } +#if OBOE_FIX_FORCE_STARTING_TO_STARTED + if (OboeGlobals::areWorkaroundsEnabled() + && aaudioNextState == static_cast(StreamState::Starting)) { + aaudioNextState = static_cast(StreamState::Started); + } +#endif // OBOE_FIX_FORCE_STARTING_TO_STARTED + if (nextState != nullptr) { + *nextState = static_cast(aaudioNextState); + } + if (currentAAudioState != aaudioNextState) { // state changed? + oboeResult = Result::OK; + break; + } + + // Did we timeout or did user ask for non-blocking? + if (timeLeftNanos <= 0) { + break; + } + + // No change yet so sleep. + mLock.unlock(); // Don't sleep while locked. + if (sleepTimeNanos > timeLeftNanos) { + sleepTimeNanos = timeLeftNanos; // last little bit + } + AudioClock::sleepForNanos(sleepTimeNanos); + timeLeftNanos -= sleepTimeNanos; + mLock.lock(); + } + + mLock.unlock(); + return oboeResult; +} + +ResultWithValue AudioStreamAAudio::setBufferSizeInFrames(int32_t requestedFrames) { + int32_t adjustedFrames = requestedFrames; + if (adjustedFrames > mBufferCapacityInFrames) { + adjustedFrames = mBufferCapacityInFrames; + } + // This calls getBufferSize() so avoid recursive lock. + adjustedFrames = QuirksManager::getInstance().clipBufferSize(*this, adjustedFrames); + + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + int32_t newBufferSize = mLibLoader->stream_setBufferSize(mAAudioStream, adjustedFrames); + // Cache the result if it's valid + if (newBufferSize > 0) mBufferSizeInFrames = newBufferSize; + return ResultWithValue::createBasedOnSign(newBufferSize); + } else { + return ResultWithValue(Result::ErrorClosed); + } +} + +StreamState AudioStreamAAudio::getState() { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + aaudio_stream_state_t aaudioState = mLibLoader->stream_getState(stream); +#if OBOE_FIX_FORCE_STARTING_TO_STARTED + if (OboeGlobals::areWorkaroundsEnabled() + && aaudioState == AAUDIO_STREAM_STATE_STARTING) { + aaudioState = AAUDIO_STREAM_STATE_STARTED; + } +#endif // OBOE_FIX_FORCE_STARTING_TO_STARTED + return static_cast(aaudioState); + } else { + return StreamState::Closed; + } +} + +int32_t AudioStreamAAudio::getBufferSizeInFrames() { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + mBufferSizeInFrames = mLibLoader->stream_getBufferSize(stream); + } + return mBufferSizeInFrames; +} + +void AudioStreamAAudio::updateFramesRead() { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); +// Set to 1 for debugging race condition #1180 with mAAudioStream. +// See also DEBUG_CLOSE_RACE in OboeTester. +// This was left in the code so that we could test the fix again easily in the future. +// We could not trigger the race condition without adding these get calls and the sleeps. +#define DEBUG_CLOSE_RACE 0 +#if DEBUG_CLOSE_RACE + // This is used when testing race conditions with close(). + // See DEBUG_CLOSE_RACE in OboeTester + AudioClock::sleepForNanos(400 * kNanosPerMillisecond); +#endif // DEBUG_CLOSE_RACE + if (stream != nullptr) { + mFramesRead = mLibLoader->stream_getFramesRead(stream); + } +} + +void AudioStreamAAudio::updateFramesWritten() { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + mFramesWritten = mLibLoader->stream_getFramesWritten(stream); + } +} + +ResultWithValue AudioStreamAAudio::getXRunCount() { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + return ResultWithValue::createBasedOnSign(mLibLoader->stream_getXRunCount(stream)); + } else { + return ResultWithValue(Result::ErrorNull); + } +} + +Result AudioStreamAAudio::getTimestamp(clockid_t clockId, + int64_t *framePosition, + int64_t *timeNanoseconds) { + if (getState() != StreamState::Started) { + return Result::ErrorInvalidState; + } + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + return static_cast(mLibLoader->stream_getTimestamp(stream, clockId, + framePosition, timeNanoseconds)); + } else { + return Result::ErrorNull; + } +} + +ResultWithValue AudioStreamAAudio::calculateLatencyMillis() { + // Get the time that a known audio frame was presented. + int64_t hardwareFrameIndex; + int64_t hardwareFrameHardwareTime; + auto result = getTimestamp(CLOCK_MONOTONIC, + &hardwareFrameIndex, + &hardwareFrameHardwareTime); + if (result != oboe::Result::OK) { + return ResultWithValue(static_cast(result)); + } + + // Get counter closest to the app. + bool isOutput = (getDirection() == oboe::Direction::Output); + int64_t appFrameIndex = isOutput ? getFramesWritten() : getFramesRead(); + + // Assume that the next frame will be processed at the current time + using namespace std::chrono; + int64_t appFrameAppTime = + duration_cast(steady_clock::now().time_since_epoch()).count(); + + // Calculate the number of frames between app and hardware + int64_t frameIndexDelta = appFrameIndex - hardwareFrameIndex; + + // Calculate the time which the next frame will be or was presented + int64_t frameTimeDelta = (frameIndexDelta * oboe::kNanosPerSecond) / getSampleRate(); + int64_t appFrameHardwareTime = hardwareFrameHardwareTime + frameTimeDelta; + + // The current latency is the difference in time between when the current frame is at + // the app and when it is at the hardware. + double latencyNanos = static_cast(isOutput + ? (appFrameHardwareTime - appFrameAppTime) // hardware is later + : (appFrameAppTime - appFrameHardwareTime)); // hardware is earlier + double latencyMillis = latencyNanos / kNanosPerMillisecond; + + return ResultWithValue(latencyMillis); +} + +bool AudioStreamAAudio::isMMapUsed() { + std::shared_lock lock(mAAudioStreamLock); + AAudioStream *stream = mAAudioStream.load(); + if (stream != nullptr) { + return AAudioExtensions::getInstance().isMMapUsed(stream); + } else { + return false; + } +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AudioStreamAAudio_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AudioStreamAAudio_android.h new file mode 100644 index 0000000..9a37eb9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_aaudio_AudioStreamAAudio_android.h @@ -0,0 +1,142 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STREAM_AAUDIO_H_ +#define OBOE_STREAM_AAUDIO_H_ + +#include +#include +#include +#include + +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_oboe_Definitions_android.h" +#include "oboe_aaudio_AAudioLoader_android.h" + +namespace oboe { + +/** + * Implementation of OboeStream that uses AAudio. + * + * Do not create this class directly. + * Use an OboeStreamBuilder to create one. + */ +class AudioStreamAAudio : public AudioStream { +public: + AudioStreamAAudio(); + explicit AudioStreamAAudio(const AudioStreamBuilder &builder); + + virtual ~AudioStreamAAudio() = default; + + /** + * + * @return true if AAudio is supported on this device. + */ + static bool isSupported(); + + // These functions override methods in AudioStream. + // See AudioStream for documentation. + Result open() override; + Result close() override; + + Result requestStart() override; + Result requestPause() override; + Result requestFlush() override; + Result requestStop() override; + + ResultWithValue write(const void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) override; + + ResultWithValue read(void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) override; + + ResultWithValue setBufferSizeInFrames(int32_t requestedFrames) override; + int32_t getBufferSizeInFrames() override; + ResultWithValue getXRunCount() override; + bool isXRunCountSupported() const override { return true; } + + ResultWithValue calculateLatencyMillis() override; + + Result waitForStateChange(StreamState currentState, + StreamState *nextState, + int64_t timeoutNanoseconds) override; + + Result getTimestamp(clockid_t clockId, + int64_t *framePosition, + int64_t *timeNanoseconds) override; + + StreamState getState() override; + + AudioApi getAudioApi() const override { + return AudioApi::AAudio; + } + + DataCallbackResult callOnAudioReady(AAudioStream *stream, + void *audioData, + int32_t numFrames); + + bool isMMapUsed(); + +protected: + static void internalErrorCallback( + AAudioStream *stream, + void *userData, + aaudio_result_t error); + + void *getUnderlyingStream() const override { + return mAAudioStream.load(); + } + + void updateFramesRead() override; + void updateFramesWritten() override; + + void logUnsupportedAttributes(); + +private: + // Must call under mLock. And stream must NOT be nullptr. + Result requestStop_l(AAudioStream *stream); + + /** + * Launch a thread that will stop the stream. + */ + void launchStopThread(); + +public: + int32_t getMDelayBeforeCloseMillis() const; + + void setDelayBeforeCloseMillis(int32_t mDelayBeforeCloseMillis); + +private: + + std::atomic mCallbackThreadEnabled; + std::atomic mStopThreadAllowed{false}; + + // pointer to the underlying 'C' AAudio stream, valid if open, null if closed + std::atomic mAAudioStream{nullptr}; + std::shared_mutex mAAudioStreamLock; // to protect mAAudioStream while closing + + static AAudioLoader *mLibLoader; + + // We may not use this but it is so small that it is not worth allocating dynamically. + AudioStreamErrorCallback mDefaultErrorCallback; +}; + +} // namespace oboe + +#endif // OBOE_STREAM_AAUDIO_H_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioClock_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioClock_android.h new file mode 100644 index 0000000..69ad61b --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioClock_android.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_AUDIO_CLOCK_H +#define OBOE_AUDIO_CLOCK_H + +#include +#include +#include "oboe_oboe_Definitions_android.h" + +namespace oboe { + +// TODO: Move this class into the public headers because it is useful when calculating stream latency +class AudioClock { +public: + static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) { + struct timespec time; + int result = clock_gettime(clockId, &time); + if (result < 0) { + return result; + } + return (time.tv_sec * kNanosPerSecond) + time.tv_nsec; + } + + /** + * Sleep until the specified time. + * + * @param nanoTime time to wake up + * @param clockId CLOCK_MONOTONIC is default + * @return 0 or a negative error, eg. -EINTR + */ + + static int sleepUntilNanoTime(int64_t nanoTime, clockid_t clockId = CLOCK_MONOTONIC) { + struct timespec time; + time.tv_sec = nanoTime / kNanosPerSecond; + time.tv_nsec = nanoTime - (time.tv_sec * kNanosPerSecond); + return 0 - clock_nanosleep(clockId, TIMER_ABSTIME, &time, NULL); + } + + /** + * Sleep for the specified number of nanoseconds in real-time. + * Return immediately with 0 if a negative nanoseconds is specified. + * + * @param nanoseconds time to sleep + * @param clockId CLOCK_REALTIME is default + * @return 0 or a negative error, eg. -EINTR + */ + + static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_REALTIME) { + if (nanoseconds > 0) { + struct timespec time; + time.tv_sec = nanoseconds / kNanosPerSecond; + time.tv_nsec = nanoseconds - (time.tv_sec * kNanosPerSecond); + return 0 - clock_nanosleep(clockId, 0, &time, NULL); + } + return 0; + } +}; + +} // namespace oboe + +#endif //OBOE_AUDIO_CLOCK_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioSourceCaller_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioSourceCaller_android.cpp new file mode 100644 index 0000000..d1a9ac1 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioSourceCaller_android.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_common_AudioSourceCaller_android.h" + +using namespace oboe; +using namespace flowgraph; + +int32_t AudioSourceCaller::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) { + AudioStreamDataCallback *callback = mStream->getDataCallback(); + int32_t result = 0; + int32_t numFrames = numBytes / mStream->getBytesPerFrame(); + if (callback != nullptr) { + DataCallbackResult callbackResult = callback->onAudioReady(mStream, buffer, numFrames); + // onAudioReady() does not return the number of bytes processed so we have to assume all. + result = (callbackResult == DataCallbackResult::Continue) + ? numBytes + : -1; + } else { + auto readResult = mStream->read(buffer, numFrames, mTimeoutNanos); + if (!readResult) return (int32_t) readResult.error(); + result = readResult.value() * mStream->getBytesPerFrame(); + } + return result; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioSourceCaller_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioSourceCaller_android.h new file mode 100644 index 0000000..5ac784e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioSourceCaller_android.h @@ -0,0 +1,83 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_AUDIO_SOURCE_CALLER_H +#define OBOE_AUDIO_SOURCE_CALLER_H + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_Oboe_android.h" + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_FixedBlockReader_android.h" + +namespace oboe { + +class AudioStreamCallback; +class AudioStream; + +/** + * For output streams that use a callback, call the application for more data. + * For input streams that do not use a callback, read from the stream. + */ +class AudioSourceCaller : public flowgraph::FlowGraphSource, public FixedBlockProcessor { +public: + AudioSourceCaller(int32_t channelCount, int32_t framesPerCallback, int32_t bytesPerSample) + : FlowGraphSource(channelCount) + , mBlockReader(*this) { + mBlockReader.open(channelCount * framesPerCallback * bytesPerSample); + } + + /** + * Set the stream to use as a source of data. + * @param stream + */ + void setStream(oboe::AudioStream *stream) { + mStream = stream; + } + + oboe::AudioStream *getStream() { + return mStream; + } + + /** + * Timeout value to use when calling audioStream->read(). + * @param timeoutNanos Zero for no timeout or time in nanoseconds. + */ + void setTimeoutNanos(int64_t timeoutNanos) { + mTimeoutNanos = timeoutNanos; + } + + int64_t getTimeoutNanos() const { + return mTimeoutNanos; + } + + /** + * Called internally for block size adaptation. + * @param buffer + * @param numBytes + * @return + */ + int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) override; + +protected: + oboe::AudioStream *mStream = nullptr; + int64_t mTimeoutNanos = 0; + + FixedBlockReader mBlockReader; +}; + +} +#endif //OBOE_AUDIO_SOURCE_CALLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioStreamBuilder_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioStreamBuilder_android.cpp new file mode 100644 index 0000000..1fd5b3a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioStreamBuilder_android.cpp @@ -0,0 +1,224 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + + +#include "oboe_aaudio_AAudioExtensions_android.h" +#include "oboe_aaudio_AudioStreamAAudio_android.h" +#include "oboe_common_FilterAudioStream_android.h" +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_Oboe_android.h" +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_opensles_AudioInputStreamOpenSLES_android.h" +#include "oboe_opensles_AudioOutputStreamOpenSLES_android.h" +#include "oboe_opensles_AudioStreamOpenSLES_android.h" +#include "oboe_common_QuirksManager_android.h" + +bool oboe::OboeGlobals::mWorkaroundsEnabled = true; + +namespace oboe { + +/** + * The following default values are used when oboe does not have any better way of determining the optimal values + * for an audio stream. This can happen when: + * + * - Client is creating a stream on API < 26 (OpenSLES) but has not supplied the optimal sample + * rate and/or frames per burst + * - Client is creating a stream on API 16 (OpenSLES) where AudioManager.PROPERTY_OUTPUT_* values + * are not available + */ +int32_t DefaultStreamValues::SampleRate = 48000; // Common rate for mobile audio and video +int32_t DefaultStreamValues::FramesPerBurst = 192; // 4 msec at 48000 Hz +int32_t DefaultStreamValues::ChannelCount = 2; // Stereo + +constexpr int kBufferSizeInBurstsForLowLatencyStreams = 2; + +#ifndef OBOE_ENABLE_AAUDIO +// Set OBOE_ENABLE_AAUDIO to 0 if you want to disable the AAudio API. +// This might be useful if you want to force all the unit tests to use OpenSL ES. +#define OBOE_ENABLE_AAUDIO 1 +#endif + +bool AudioStreamBuilder::isAAudioSupported() { + return AudioStreamAAudio::isSupported() && OBOE_ENABLE_AAUDIO; +} + +bool AudioStreamBuilder::isAAudioRecommended() { + // See https://github.com/google/oboe/issues/40, + // AAudio may not be stable on Android O, depending on how it is used. + // To be safe, use AAudio only on O_MR1 and above. + return (getSdkVersion() >= __ANDROID_API_O_MR1__) && isAAudioSupported(); +} + +AudioStream *AudioStreamBuilder::build() { + AudioStream *stream = nullptr; + if (isAAudioRecommended() && mAudioApi != AudioApi::OpenSLES) { + stream = new AudioStreamAAudio(*this); + } else if (isAAudioSupported() && mAudioApi == AudioApi::AAudio) { + stream = new AudioStreamAAudio(*this); + LOGE("Creating AAudio stream on 8.0 because it was specified. This is error prone."); + } else { + if (getDirection() == oboe::Direction::Output) { + stream = new AudioOutputStreamOpenSLES(*this); + } else if (getDirection() == oboe::Direction::Input) { + stream = new AudioInputStreamOpenSLES(*this); + } + } + return stream; +} + +bool AudioStreamBuilder::isCompatible(AudioStreamBase &other) { + return (getSampleRate() == oboe::Unspecified || getSampleRate() == other.getSampleRate()) + && (getFormat() == (AudioFormat)oboe::Unspecified || getFormat() == other.getFormat()) + && (getFramesPerDataCallback() == oboe::Unspecified || getFramesPerDataCallback() == other.getFramesPerDataCallback()) + && (getChannelCount() == oboe::Unspecified || getChannelCount() == other.getChannelCount()); +} + +Result AudioStreamBuilder::openStream(AudioStream **streamPP) { + auto result = isValidConfig(); + if (result != Result::OK) { + LOGW("%s() invalid config %d", __func__, result); + return result; + } + + LOGI("%s() %s -------- %s --------", + __func__, getDirection() == Direction::Input ? "INPUT" : "OUTPUT", getVersionText()); + + if (streamPP == nullptr) { + return Result::ErrorNull; + } + *streamPP = nullptr; + + AudioStream *streamP = nullptr; + + // Maybe make a FilterInputStream. + AudioStreamBuilder childBuilder(*this); + // Check need for conversion and modify childBuilder for optimal stream. + bool conversionNeeded = QuirksManager::getInstance().isConversionNeeded(*this, childBuilder); + // Do we need to make a child stream and convert. + if (conversionNeeded) { + AudioStream *tempStream; + result = childBuilder.openStream(&tempStream); + if (result != Result::OK) { + return result; + } + + if (isCompatible(*tempStream)) { + // The child stream would work as the requested stream so we can just use it directly. + *streamPP = tempStream; + return result; + } else { + AudioStreamBuilder parentBuilder = *this; + // Build a stream that is as close as possible to the childStream. + if (getFormat() == oboe::AudioFormat::Unspecified) { + parentBuilder.setFormat(tempStream->getFormat()); + } + if (getChannelCount() == oboe::Unspecified) { + parentBuilder.setChannelCount(tempStream->getChannelCount()); + } + if (getSampleRate() == oboe::Unspecified) { + parentBuilder.setSampleRate(tempStream->getSampleRate()); + } + if (getFramesPerDataCallback() == oboe::Unspecified) { + parentBuilder.setFramesPerCallback(tempStream->getFramesPerDataCallback()); + } + + // Use childStream in a FilterAudioStream. + LOGI("%s() create a FilterAudioStream for data conversion.", __func__); + FilterAudioStream *filterStream = new FilterAudioStream(parentBuilder, tempStream); + result = filterStream->configureFlowGraph(); + if (result != Result::OK) { + filterStream->close(); + delete filterStream; + // Just open streamP the old way. + } else { + streamP = static_cast(filterStream); + } + } + } + + if (streamP == nullptr) { + streamP = build(); + if (streamP == nullptr) { + return Result::ErrorNull; + } + } + + // If MMAP has a problem in this case then disable it temporarily. + bool wasMMapOriginallyEnabled = AAudioExtensions::getInstance().isMMapEnabled(); + bool wasMMapTemporarilyDisabled = false; + if (wasMMapOriginallyEnabled) { + bool isMMapSafe = QuirksManager::getInstance().isMMapSafe(childBuilder); + if (!isMMapSafe) { + AAudioExtensions::getInstance().setMMapEnabled(false); + wasMMapTemporarilyDisabled = true; + } + } + result = streamP->open(); + if (wasMMapTemporarilyDisabled) { + AAudioExtensions::getInstance().setMMapEnabled(wasMMapOriginallyEnabled); // restore original + } + if (result == Result::OK) { + + int32_t optimalBufferSize = -1; + // Use a reasonable default buffer size. + if (streamP->getDirection() == Direction::Input) { + // For input, small size does not improve latency because the stream is usually + // run close to empty. And a low size can result in XRuns so always use the maximum. + optimalBufferSize = streamP->getBufferCapacityInFrames(); + } else if (streamP->getPerformanceMode() == PerformanceMode::LowLatency + && streamP->getDirection() == Direction::Output) { // Output check is redundant. + optimalBufferSize = streamP->getFramesPerBurst() * + kBufferSizeInBurstsForLowLatencyStreams; + } + if (optimalBufferSize >= 0) { + auto setBufferResult = streamP->setBufferSizeInFrames(optimalBufferSize); + if (!setBufferResult) { + LOGW("Failed to setBufferSizeInFrames(%d). Error was %s", + optimalBufferSize, + convertToText(setBufferResult.error())); + } + } + + *streamPP = streamP; + } else { + delete streamP; + } + return result; +} + +Result AudioStreamBuilder::openManagedStream(oboe::ManagedStream &stream) { + stream.reset(); + AudioStream *streamptr; + auto result = openStream(&streamptr); + stream.reset(streamptr); + return result; +} + +Result AudioStreamBuilder::openStream(std::shared_ptr &sharedStream) { + sharedStream.reset(); + AudioStream *streamptr; + auto result = openStream(&streamptr); + if (result == Result::OK) { + sharedStream.reset(streamptr); + // Save a weak_ptr in the stream for use with callbacks. + streamptr->setWeakThis(sharedStream); + } + return result; +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioStream_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioStream_android.cpp new file mode 100644 index 0000000..bb7e894 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_AudioStream_android.cpp @@ -0,0 +1,208 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_common_OboeDebug_android.h" +#include "oboe_common_AudioClock_android.h" +#include "oboe_oboe_Utilities_android.h" + +namespace oboe { + +/* + * AudioStream + */ +AudioStream::AudioStream(const AudioStreamBuilder &builder) + : AudioStreamBase(builder) { +} + +Result AudioStream::close() { + // Update local counters so they can be read after the close. + updateFramesWritten(); + updateFramesRead(); + return Result::OK; +} + +// Call this from fireDataCallback() if you want to monitor CPU scheduler. +void AudioStream::checkScheduler() { + int scheduler = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK; // for current thread + if (scheduler != mPreviousScheduler) { + LOGD("AudioStream::%s() scheduler = %s", __func__, + ((scheduler == SCHED_FIFO) ? "SCHED_FIFO" : + ((scheduler == SCHED_OTHER) ? "SCHED_OTHER" : + ((scheduler == SCHED_RR) ? "SCHED_RR" : "UNKNOWN"))) + ); + mPreviousScheduler = scheduler; + } +} + +DataCallbackResult AudioStream::fireDataCallback(void *audioData, int32_t numFrames) { + if (!isDataCallbackEnabled()) { + LOGW("AudioStream::%s() called with data callback disabled!", __func__); + return DataCallbackResult::Stop; // Should not be getting called + } + + DataCallbackResult result; + if (mDataCallback) { + result = mDataCallback->onAudioReady(this, audioData, numFrames); + } else { + result = onDefaultCallback(audioData, numFrames); + } + // On Oreo, we might get called after returning stop. + // So block that here. + setDataCallbackEnabled(result == DataCallbackResult::Continue); + + return result; +} + +Result AudioStream::waitForStateTransition(StreamState startingState, + StreamState endingState, + int64_t timeoutNanoseconds) +{ + StreamState state; + { + std::lock_guard lock(mLock); + state = getState(); + if (state == StreamState::Closed) { + return Result::ErrorClosed; + } else if (state == StreamState::Disconnected) { + return Result::ErrorDisconnected; + } + } + + StreamState nextState = state; + // TODO Should this be a while()?! + if (state == startingState && state != endingState) { + Result result = waitForStateChange(state, &nextState, timeoutNanoseconds); + if (result != Result::OK) { + return result; + } + } + + if (nextState != endingState) { + return Result::ErrorInvalidState; + } else { + return Result::OK; + } +} + +Result AudioStream::start(int64_t timeoutNanoseconds) +{ + Result result = requestStart(); + if (result != Result::OK) return result; + if (timeoutNanoseconds <= 0) return result; + return waitForStateTransition(StreamState::Starting, + StreamState::Started, timeoutNanoseconds); +} + +Result AudioStream::pause(int64_t timeoutNanoseconds) +{ + Result result = requestPause(); + if (result != Result::OK) return result; + if (timeoutNanoseconds <= 0) return result; + return waitForStateTransition(StreamState::Pausing, + StreamState::Paused, timeoutNanoseconds); +} + +Result AudioStream::flush(int64_t timeoutNanoseconds) +{ + Result result = requestFlush(); + if (result != Result::OK) return result; + if (timeoutNanoseconds <= 0) return result; + return waitForStateTransition(StreamState::Flushing, + StreamState::Flushed, timeoutNanoseconds); +} + +Result AudioStream::stop(int64_t timeoutNanoseconds) +{ + Result result = requestStop(); + if (result != Result::OK) return result; + if (timeoutNanoseconds <= 0) return result; + return waitForStateTransition(StreamState::Stopping, + StreamState::Stopped, timeoutNanoseconds); +} + +int32_t AudioStream::getBytesPerSample() const { + return convertFormatToSizeInBytes(mFormat); +} + +int64_t AudioStream::getFramesRead() { + updateFramesRead(); + return mFramesRead; +} + +int64_t AudioStream::getFramesWritten() { + updateFramesWritten(); + return mFramesWritten; +} + +ResultWithValue AudioStream::getAvailableFrames() { + int64_t readCounter = getFramesRead(); + if (readCounter < 0) return ResultWithValue::createBasedOnSign(readCounter); + int64_t writeCounter = getFramesWritten(); + if (writeCounter < 0) return ResultWithValue::createBasedOnSign(writeCounter); + int32_t framesAvailable = writeCounter - readCounter; + return ResultWithValue(framesAvailable); +} + +ResultWithValue AudioStream::waitForAvailableFrames(int32_t numFrames, + int64_t timeoutNanoseconds) { + if (numFrames == 0) return Result::OK; + if (numFrames < 0) return Result::ErrorOutOfRange; + + int64_t framesAvailable = 0; + int64_t burstInNanos = getFramesPerBurst() * kNanosPerSecond / getSampleRate(); + bool ready = false; + int64_t deadline = AudioClock::getNanoseconds() + timeoutNanoseconds; + do { + ResultWithValue result = getAvailableFrames(); + if (!result) return result; + framesAvailable = result.value(); + ready = (framesAvailable >= numFrames); + if (!ready) { + int64_t now = AudioClock::getNanoseconds(); + if (now > deadline) break; + AudioClock::sleepForNanos(burstInNanos); + } + } while (!ready); + return (!ready) + ? ResultWithValue(Result::ErrorTimeout) + : ResultWithValue(framesAvailable); +} + +ResultWithValue AudioStream::getTimestamp(clockid_t clockId) { + FrameTimestamp frame; + Result result = getTimestamp(clockId, &frame.position, &frame.timestamp); + if (result == Result::OK){ + return ResultWithValue(frame); + } else { + return ResultWithValue(static_cast(result)); + } +} + +void AudioStream::calculateDefaultDelayBeforeCloseMillis() { + // Calculate delay time before close based on burst duration. + // Start with a burst duration then add 1 msec as a safety margin. + mDelayBeforeCloseMillis = std::max(kMinDelayBeforeCloseMillis, + 1 + ((mFramesPerBurst * 1000) / getSampleRate())); + LOGD("calculateDefaultDelayBeforeCloseMillis() default = %d", + static_cast(mDelayBeforeCloseMillis)); +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_DataConversionFlowGraph_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_DataConversionFlowGraph_android.cpp new file mode 100644 index 0000000..66d12ad --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_DataConversionFlowGraph_android.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_common_DataConversionFlowGraph_android.h" +#include "oboe_common_SourceFloatCaller_android.h" +#include "oboe_common_SourceI16Caller_android.h" +#include "oboe_common_SourceI24Caller_android.h" +#include "oboe_common_SourceI32Caller_android.h" + +#include "oboe_flowgraph_ClipToRange_android.h" +#include "oboe_flowgraph_MonoToMultiConverter_android.h" +#include "oboe_flowgraph_MultiToMonoConverter_android.h" +#include "oboe_flowgraph_RampLinear_android.h" +#include "oboe_flowgraph_SinkFloat_android.h" +#include "oboe_flowgraph_SinkI16_android.h" +#include "oboe_flowgraph_SinkI24_android.h" +#include "oboe_flowgraph_SinkI32_android.h" +#include "oboe_flowgraph_SourceFloat_android.h" +#include "oboe_flowgraph_SourceI16_android.h" +#include "oboe_flowgraph_SourceI24_android.h" +#include "oboe_flowgraph_SourceI32_android.h" +#include "oboe_flowgraph_SampleRateConverter_android.h" + +using namespace oboe; +using namespace flowgraph; +using namespace resampler; + +void DataConversionFlowGraph::setSource(const void *buffer, int32_t numFrames) { + mSource->setData(buffer, numFrames); +} + +static MultiChannelResampler::Quality convertOboeSRQualityToMCR(SampleRateConversionQuality quality) { + switch (quality) { + case SampleRateConversionQuality::Fastest: + return MultiChannelResampler::Quality::Fastest; + case SampleRateConversionQuality::Low: + return MultiChannelResampler::Quality::Low; + default: + case SampleRateConversionQuality::Medium: + return MultiChannelResampler::Quality::Medium; + case SampleRateConversionQuality::High: + return MultiChannelResampler::Quality::High; + case SampleRateConversionQuality::Best: + return MultiChannelResampler::Quality::Best; + } +} + +// Chain together multiple processors. +// Callback Output +// Use SourceCaller that calls original app callback from the flowgraph. +// The child callback from FilteredAudioStream read()s from the flowgraph. +// Callback Input +// Child callback from FilteredAudioStream writes()s to the flowgraph. +// The output of the flowgraph goes through a BlockWriter to the app callback. +// Blocking Write +// Write buffer is set on an AudioSource. +// Data is pulled through the graph and written to the child stream. +// Blocking Read +// Reads in a loop from the flowgraph Sink to fill the read buffer. +// A SourceCaller then does a blocking read from the child Stream. +// +Result DataConversionFlowGraph::configure(AudioStream *sourceStream, AudioStream *sinkStream) { + + FlowGraphPortFloatOutput *lastOutput = nullptr; + + bool isOutput = sourceStream->getDirection() == Direction::Output; + bool isInput = !isOutput; + mFilterStream = isOutput ? sourceStream : sinkStream; + + AudioFormat sourceFormat = sourceStream->getFormat(); + int32_t sourceChannelCount = sourceStream->getChannelCount(); + int32_t sourceSampleRate = sourceStream->getSampleRate(); + int32_t sourceFramesPerCallback = sourceStream->getFramesPerDataCallback(); + + AudioFormat sinkFormat = sinkStream->getFormat(); + int32_t sinkChannelCount = sinkStream->getChannelCount(); + int32_t sinkSampleRate = sinkStream->getSampleRate(); + int32_t sinkFramesPerCallback = sinkStream->getFramesPerDataCallback(); + + LOGI("%s() flowgraph converts channels: %d to %d, format: %d to %d" + ", rate: %d to %d, cbsize: %d to %d, qual = %d", + __func__, + sourceChannelCount, sinkChannelCount, + sourceFormat, sinkFormat, + sourceSampleRate, sinkSampleRate, + sourceFramesPerCallback, sinkFramesPerCallback, + sourceStream->getSampleRateConversionQuality()); + + // Source + // IF OUTPUT and using a callback then call back to the app using a SourceCaller. + // OR IF INPUT and NOT using a callback then read from the child stream using a SourceCaller. + bool isDataCallbackSpecified = sourceStream->isDataCallbackSpecified(); + if ((isDataCallbackSpecified && isOutput) + || (!isDataCallbackSpecified && isInput)) { + int32_t actualSourceFramesPerCallback = (sourceFramesPerCallback == kUnspecified) + ? sourceStream->getFramesPerBurst() + : sourceFramesPerCallback; + switch (sourceFormat) { + case AudioFormat::Float: + mSourceCaller = std::make_unique(sourceChannelCount, + actualSourceFramesPerCallback); + break; + case AudioFormat::I16: + mSourceCaller = std::make_unique(sourceChannelCount, + actualSourceFramesPerCallback); + break; + case AudioFormat::I24: + mSourceCaller = std::make_unique(sourceChannelCount, + actualSourceFramesPerCallback); + break; + case AudioFormat::I32: + mSourceCaller = std::make_unique(sourceChannelCount, + actualSourceFramesPerCallback); + break; + default: + LOGE("%s() Unsupported source caller format = %d", __func__, sourceFormat); + return Result::ErrorIllegalArgument; + } + mSourceCaller->setStream(sourceStream); + lastOutput = &mSourceCaller->output; + } else { + // IF OUTPUT and NOT using a callback then write to the child stream using a BlockWriter. + // OR IF INPUT and using a callback then write to the app using a BlockWriter. + switch (sourceFormat) { + case AudioFormat::Float: + mSource = std::make_unique(sourceChannelCount); + break; + case AudioFormat::I16: + mSource = std::make_unique(sourceChannelCount); + break; + case AudioFormat::I24: + mSource = std::make_unique(sourceChannelCount); + break; + case AudioFormat::I32: + mSource = std::make_unique(sourceChannelCount); + break; + default: + LOGE("%s() Unsupported source format = %d", __func__, sourceFormat); + return Result::ErrorIllegalArgument; + } + if (isInput) { + int32_t actualSinkFramesPerCallback = (sinkFramesPerCallback == kUnspecified) + ? sinkStream->getFramesPerBurst() + : sinkFramesPerCallback; + // The BlockWriter is after the Sink so use the SinkStream size. + mBlockWriter.open(actualSinkFramesPerCallback * sinkStream->getBytesPerFrame()); + mAppBuffer = std::make_unique( + kDefaultBufferSize * sinkStream->getBytesPerFrame()); + } + lastOutput = &mSource->output; + } + + // If we are going to reduce the number of channels then do it before the + // sample rate converter. + if (sourceChannelCount > sinkChannelCount) { + if (sinkChannelCount == 1) { + mMultiToMonoConverter = std::make_unique(sourceChannelCount); + lastOutput->connect(&mMultiToMonoConverter->input); + lastOutput = &mMultiToMonoConverter->output; + } else { + mChannelCountConverter = std::make_unique( + sourceChannelCount, + sinkChannelCount); + lastOutput->connect(&mChannelCountConverter->input); + lastOutput = &mChannelCountConverter->output; + } + } + + // Sample Rate conversion + if (sourceSampleRate != sinkSampleRate) { + // Create a resampler to do the math. + mResampler.reset(MultiChannelResampler::make(lastOutput->getSamplesPerFrame(), + sourceSampleRate, + sinkSampleRate, + convertOboeSRQualityToMCR( + sourceStream->getSampleRateConversionQuality()))); + // Make a flowgraph node that uses the resampler. + mRateConverter = std::make_unique(lastOutput->getSamplesPerFrame(), + *mResampler.get()); + lastOutput->connect(&mRateConverter->input); + lastOutput = &mRateConverter->output; + } + + // Expand the number of channels if required. + if (sourceChannelCount < sinkChannelCount) { + if (sourceChannelCount == 1) { + mMonoToMultiConverter = std::make_unique(sinkChannelCount); + lastOutput->connect(&mMonoToMultiConverter->input); + lastOutput = &mMonoToMultiConverter->output; + } else { + mChannelCountConverter = std::make_unique( + sourceChannelCount, + sinkChannelCount); + lastOutput->connect(&mChannelCountConverter->input); + lastOutput = &mChannelCountConverter->output; + } + } + + // Sink + switch (sinkFormat) { + case AudioFormat::Float: + mSink = std::make_unique(sinkChannelCount); + break; + case AudioFormat::I16: + mSink = std::make_unique(sinkChannelCount); + break; + case AudioFormat::I24: + mSink = std::make_unique(sinkChannelCount); + break; + case AudioFormat::I32: + mSink = std::make_unique(sinkChannelCount); + break; + default: + LOGE("%s() Unsupported sink format = %d", __func__, sinkFormat); + return Result::ErrorIllegalArgument;; + } + lastOutput->connect(&mSink->input); + + return Result::OK; +} + +int32_t DataConversionFlowGraph::read(void *buffer, int32_t numFrames, int64_t timeoutNanos) { + if (mSourceCaller) { + mSourceCaller->setTimeoutNanos(timeoutNanos); + } + int32_t numRead = mSink->read(buffer, numFrames); + return numRead; +} + +// This is similar to pushing data through the flowgraph. +int32_t DataConversionFlowGraph::write(void *inputBuffer, int32_t numFrames) { + // Put the data from the input at the head of the flowgraph. + mSource->setData(inputBuffer, numFrames); + while (true) { + // Pull and read some data in app format into a small buffer. + int32_t framesRead = mSink->read(mAppBuffer.get(), flowgraph::kDefaultBufferSize); + if (framesRead <= 0) break; + // Write to a block adapter, which will call the destination whenever it has enough data. + int32_t bytesRead = mBlockWriter.write(mAppBuffer.get(), + framesRead * mFilterStream->getBytesPerFrame()); + if (bytesRead < 0) return bytesRead; // TODO review + } + return numFrames; +} + +int32_t DataConversionFlowGraph::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) { + int32_t numFrames = numBytes / mFilterStream->getBytesPerFrame(); + mCallbackResult = mFilterStream->getDataCallback()->onAudioReady(mFilterStream, buffer, numFrames); + // TODO handle STOP from callback, process data remaining in the block adapter + return numBytes; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_DataConversionFlowGraph_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_DataConversionFlowGraph_android.h new file mode 100644 index 0000000..53baee9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_DataConversionFlowGraph_android.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_OBOE_FLOW_GRAPH_H +#define OBOE_OBOE_FLOW_GRAPH_H + +#include +#include +#include + +#include "oboe_flowgraph_ChannelCountConverter_android.h" +#include "oboe_flowgraph_MonoToMultiConverter_android.h" +#include "oboe_flowgraph_MultiToMonoConverter_android.h" +#include "oboe_flowgraph_SampleRateConverter_android.h" +#include "oboe_oboe_Definitions_android.h" +#include "oboe_common_AudioSourceCaller_android.h" +#include "oboe_common_FixedBlockWriter_android.h" + +namespace oboe { + +class AudioStream; +class AudioSourceCaller; + +/** + * Convert PCM channels, format and sample rate for optimal latency. + */ +class DataConversionFlowGraph : public FixedBlockProcessor { +public: + + DataConversionFlowGraph() + : mBlockWriter(*this) {} + + void setSource(const void *buffer, int32_t numFrames); + + /** Connect several modules together to convert from source to sink. + * This should only be called once for each instance. + * + * @param sourceFormat + * @param sourceChannelCount + * @param sinkFormat + * @param sinkChannelCount + * @return + */ + oboe::Result configure(oboe::AudioStream *sourceStream, oboe::AudioStream *sinkStream); + + int32_t read(void *buffer, int32_t numFrames, int64_t timeoutNanos); + + int32_t write(void *buffer, int32_t numFrames); + + int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) override; + + DataCallbackResult getDataCallbackResult() { + return mCallbackResult; + } + +private: + std::unique_ptr mSource; + std::unique_ptr mSourceCaller; + std::unique_ptr mMonoToMultiConverter; + std::unique_ptr mMultiToMonoConverter; + std::unique_ptr mChannelCountConverter; + std::unique_ptr mResampler; + std::unique_ptr mRateConverter; + std::unique_ptr mSink; + + FixedBlockWriter mBlockWriter; + DataCallbackResult mCallbackResult = DataCallbackResult::Continue; + AudioStream *mFilterStream = nullptr; + std::unique_ptr mAppBuffer; +}; + +} +#endif //OBOE_OBOE_FLOW_GRAPH_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FilterAudioStream_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FilterAudioStream_android.cpp new file mode 100644 index 0000000..768263f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FilterAudioStream_android.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_common_FilterAudioStream_android.h" + +using namespace oboe; +using namespace flowgraph; + +// Output callback uses FixedBlockReader::read() +// <= SourceFloatCaller::onProcess() +// <=== DataConversionFlowGraph::read() +// <== FilterAudioStream::onAudioReady() +// +// Output blocking uses no block adapter because AAudio can accept +// writes of any size. It uses DataConversionFlowGraph::read() <== FilterAudioStream::write() <= app +// +// Input callback uses FixedBlockWriter::write() +// <= DataConversionFlowGraph::write() +// <= FilterAudioStream::onAudioReady() +// +// Input blocking uses FixedBlockReader::read() // TODO may not need block adapter +// <= SourceFloatCaller::onProcess() +// <=== SinkFloat::read() +// <= DataConversionFlowGraph::read() +// <== FilterAudioStream::read() +// <= app + +Result FilterAudioStream::configureFlowGraph() { + mFlowGraph = std::make_unique(); + bool isOutput = getDirection() == Direction::Output; + + AudioStream *sourceStream = isOutput ? this : mChildStream.get(); + AudioStream *sinkStream = isOutput ? mChildStream.get() : this; + + mRateScaler = ((double) getSampleRate()) / mChildStream->getSampleRate(); + + return mFlowGraph->configure(sourceStream, sinkStream); +} + +// Put the data to be written at the source end of the flowgraph. +// Then read (pull) the data from the flowgraph and write it to the +// child stream. +ResultWithValue FilterAudioStream::write(const void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + int32_t framesWritten = 0; + mFlowGraph->setSource(buffer, numFrames); + while (true) { + int32_t numRead = mFlowGraph->read(mBlockingBuffer.get(), + getFramesPerBurst(), + timeoutNanoseconds); + if (numRead < 0) { + return ResultWithValue::createBasedOnSign(numRead); + } + if (numRead == 0) { + break; // finished processing the source buffer + } + auto writeResult = mChildStream->write(mBlockingBuffer.get(), + numRead, + timeoutNanoseconds); + if (!writeResult) { + return writeResult; + } + framesWritten += writeResult.value(); + } + return ResultWithValue::createBasedOnSign(framesWritten); +} + +// Read (pull) the data we want from the sink end of the flowgraph. +// The necessary data will be read from the child stream using a flowgraph callback. +ResultWithValue FilterAudioStream::read(void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + int32_t framesRead = mFlowGraph->read(buffer, numFrames, timeoutNanoseconds); + return ResultWithValue::createBasedOnSign(framesRead); +} + +DataCallbackResult FilterAudioStream::onAudioReady(AudioStream *oboeStream, + void *audioData, + int32_t numFrames) { + int32_t framesProcessed; + if (oboeStream->getDirection() == Direction::Output) { + framesProcessed = mFlowGraph->read(audioData, numFrames, 0 /* timeout */); + } else { + framesProcessed = mFlowGraph->write(audioData, numFrames); + } + return (framesProcessed < numFrames) + ? DataCallbackResult::Stop + : mFlowGraph->getDataCallbackResult(); +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FilterAudioStream_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FilterAudioStream_android.h new file mode 100644 index 0000000..6cc6108 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FilterAudioStream_android.h @@ -0,0 +1,223 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_FILTER_AUDIO_STREAM_H +#define OBOE_FILTER_AUDIO_STREAM_H + +#include +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_common_DataConversionFlowGraph_android.h" + +namespace oboe { + +/** + * An AudioStream that wraps another AudioStream and provides audio data conversion. + * Operations may include channel conversion, data format conversion and/or sample rate conversion. + */ +class FilterAudioStream : public AudioStream, AudioStreamCallback { +public: + + /** + * Construct an `AudioStream` using the given `AudioStreamBuilder` and a child AudioStream. + * + * This should only be called internally by AudioStreamBuilder. + * Ownership of childStream will be passed to this object. + * + * @param builder containing all the stream's attributes + */ + FilterAudioStream(const AudioStreamBuilder &builder, AudioStream *childStream) + : AudioStream(builder) + , mChildStream(childStream) { + // Intercept the callback if used. + if (builder.isErrorCallbackSpecified()) { + mErrorCallback = mChildStream->swapErrorCallback(this); + } + if (builder.isDataCallbackSpecified()) { + mDataCallback = mChildStream->swapDataCallback(this); + } else { + const int size = childStream->getFramesPerBurst() * childStream->getBytesPerFrame(); + mBlockingBuffer = std::make_unique(size); + } + + // Copy parameters that may not match builder. + mBufferCapacityInFrames = mChildStream->getBufferCapacityInFrames(); + mPerformanceMode = mChildStream->getPerformanceMode(); + mInputPreset = mChildStream->getInputPreset(); + mFramesPerBurst = mChildStream->getFramesPerBurst(); + mDeviceId = mChildStream->getDeviceId(); + } + + virtual ~FilterAudioStream() = default; + + AudioStream *getChildStream() const { + return mChildStream.get(); + } + + Result configureFlowGraph(); + + // Close child and parent. + Result close() override { + const Result result1 = mChildStream->close(); + const Result result2 = AudioStream::close(); + return (result1 != Result::OK ? result1 : result2); + } + + /** + * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `start(0)`. + */ + Result requestStart() override { + return mChildStream->requestStart(); + } + + /** + * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `pause(0)`. + */ + Result requestPause() override { + return mChildStream->requestPause(); + } + + /** + * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `flush(0)`. + */ + Result requestFlush() override { + return mChildStream->requestFlush(); + } + + /** + * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `stop(0)`. + */ + Result requestStop() override { + return mChildStream->requestStop(); + } + + ResultWithValue read(void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) override; + + ResultWithValue write(const void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) override; + + StreamState getState() override { + return mChildStream->getState(); + } + + Result waitForStateChange( + StreamState inputState, + StreamState *nextState, + int64_t timeoutNanoseconds) override { + return mChildStream->waitForStateChange(inputState, nextState, timeoutNanoseconds); + } + + bool isXRunCountSupported() const override { + return mChildStream->isXRunCountSupported(); + } + + AudioApi getAudioApi() const override { + return mChildStream->getAudioApi(); + } + + void updateFramesWritten() override { + // TODO for output, just count local writes? + mFramesWritten = static_cast(mChildStream->getFramesWritten() * mRateScaler); + } + + void updateFramesRead() override { + // TODO for input, just count local reads? + mFramesRead = static_cast(mChildStream->getFramesRead() * mRateScaler); + } + + void *getUnderlyingStream() const override { + return mChildStream->getUnderlyingStream(); + } + + ResultWithValue setBufferSizeInFrames(int32_t requestedFrames) override { + return mChildStream->setBufferSizeInFrames(requestedFrames); + } + + int32_t getBufferSizeInFrames() override { + mBufferSizeInFrames = mChildStream->getBufferSizeInFrames(); + return mBufferSizeInFrames; + } + + ResultWithValue getXRunCount() override { + return mChildStream->getXRunCount(); + } + + ResultWithValue calculateLatencyMillis() override { + // This will automatically include the latency of the flowgraph? + return mChildStream->calculateLatencyMillis(); + } + + Result getTimestamp(clockid_t clockId, + int64_t *framePosition, + int64_t *timeNanoseconds) override { + int64_t childPosition = 0; + Result result = mChildStream->getTimestamp(clockId, &childPosition, timeNanoseconds); + // It is OK if framePosition is null. + if (framePosition) { + *framePosition = childPosition * mRateScaler; + } + return result; + } + + DataCallbackResult onAudioReady(AudioStream *oboeStream, + void *audioData, + int32_t numFrames) override; + + bool onError(AudioStream * /*audioStream*/, Result error) override { + if (mErrorCallback != nullptr) { + return mErrorCallback->onError(this, error); + } + return false; + } + + void onErrorBeforeClose(AudioStream * /*oboeStream*/, Result error) override { + if (mErrorCallback != nullptr) { + mErrorCallback->onErrorBeforeClose(this, error); + } + } + + void onErrorAfterClose(AudioStream * /*oboeStream*/, Result error) override { + // Close this parent stream because the callback will only close the child. + AudioStream::close(); + if (mErrorCallback != nullptr) { + mErrorCallback->onErrorAfterClose(this, error); + } + } + + /** + * @return last result passed from an error callback + */ + oboe::Result getLastErrorCallbackResult() const override { + return mChildStream->getLastErrorCallbackResult(); + } + +private: + + std::unique_ptr mChildStream; // this stream wraps the child stream + std::unique_ptr mFlowGraph; // for converting data + std::unique_ptr mBlockingBuffer; // temp buffer for write() + double mRateScaler = 1.0; // ratio parent/child sample rates +}; + +} // oboe + +#endif //OBOE_FILTER_AUDIO_STREAM_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockAdapter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockAdapter_android.cpp new file mode 100644 index 0000000..048af8e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockAdapter_android.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_common_FixedBlockAdapter_android.h" + +FixedBlockAdapter::~FixedBlockAdapter() { +} + +int32_t FixedBlockAdapter::open(int32_t bytesPerFixedBlock) +{ + mSize = bytesPerFixedBlock; + mStorage = std::make_unique(bytesPerFixedBlock); + mPosition = 0; + return 0; +} + +int32_t FixedBlockAdapter::close() +{ + mStorage.reset(nullptr); + mSize = 0; + mPosition = 0; + return 0; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockAdapter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockAdapter_android.h new file mode 100644 index 0000000..76e961c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockAdapter_android.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAUDIO_FIXED_BLOCK_ADAPTER_H +#define AAUDIO_FIXED_BLOCK_ADAPTER_H + +#include +#include +#include + +/** + * Interface for a class that needs fixed-size blocks. + */ +class FixedBlockProcessor { +public: + virtual ~FixedBlockProcessor() = default; + /** + * + * @param buffer Pointer to first byte of data. + * @param numBytes This will be a fixed size specified in FixedBlockAdapter::open(). + * @return Number of bytes processed or a negative error code. + */ + virtual int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) = 0; +}; + +/** + * Base class for a variable-to-fixed-size block adapter. + */ +class FixedBlockAdapter +{ +public: + FixedBlockAdapter(FixedBlockProcessor &fixedBlockProcessor) + : mFixedBlockProcessor(fixedBlockProcessor) {} + + virtual ~FixedBlockAdapter(); + + /** + * Allocate internal resources needed for buffering data. + */ + virtual int32_t open(int32_t bytesPerFixedBlock); + + /** + * Free internal resources. + */ + int32_t close(); + +protected: + FixedBlockProcessor &mFixedBlockProcessor; + std::unique_ptr mStorage; // Store data here while assembling buffers. + int32_t mSize = 0; // Size in bytes of the fixed size buffer. + int32_t mPosition = 0; // Offset of the last byte read or written. +}; + +#endif /* AAUDIO_FIXED_BLOCK_ADAPTER_H */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockReader_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockReader_android.cpp new file mode 100644 index 0000000..6a94a9a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockReader_android.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_common_FixedBlockAdapter_android.h" + +#include "oboe_common_FixedBlockReader_android.h" + + +FixedBlockReader::FixedBlockReader(FixedBlockProcessor &fixedBlockProcessor) + : FixedBlockAdapter(fixedBlockProcessor) { + mPosition = mSize; +} + +int32_t FixedBlockReader::open(int32_t bytesPerFixedBlock) { + int32_t result = FixedBlockAdapter::open(bytesPerFixedBlock); + mPosition = 0; + mValid = 0; + return result; +} + +int32_t FixedBlockReader::readFromStorage(uint8_t *buffer, int32_t numBytes) { + int32_t bytesToRead = numBytes; + int32_t dataAvailable = mValid - mPosition; + if (bytesToRead > dataAvailable) { + bytesToRead = dataAvailable; + } + memcpy(buffer, mStorage.get() + mPosition, bytesToRead); + mPosition += bytesToRead; + return bytesToRead; +} + +int32_t FixedBlockReader::read(uint8_t *buffer, int32_t numBytes) { + int32_t bytesRead; + int32_t bytesLeft = numBytes; + while(bytesLeft > 0) { + if (mPosition < mValid) { + // Use up bytes currently in storage. + bytesRead = readFromStorage(buffer, bytesLeft); + buffer += bytesRead; + bytesLeft -= bytesRead; + } else if (bytesLeft >= mSize) { + // Nothing in storage. Read through if enough for a complete block. + bytesRead = mFixedBlockProcessor.onProcessFixedBlock(buffer, mSize); + if (bytesRead < 0) return bytesRead; + buffer += bytesRead; + bytesLeft -= bytesRead; + } else { + // Just need a partial block so we have to reload storage. + bytesRead = mFixedBlockProcessor.onProcessFixedBlock(mStorage.get(), mSize); + if (bytesRead < 0) return bytesRead; + mPosition = 0; + mValid = bytesRead; + if (bytesRead == 0) break; + } + } + return numBytes - bytesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockReader_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockReader_android.h new file mode 100644 index 0000000..ffa1eca --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockReader_android.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAUDIO_FIXED_BLOCK_READER_H +#define AAUDIO_FIXED_BLOCK_READER_H + +#include + +#include "oboe_common_FixedBlockAdapter_android.h" + +/** + * Read from a fixed-size block to a variable sized block. + * + * This can be used to convert a pull data flow from fixed sized buffers to variable sized buffers. + * An example would be an audio output callback that reads from the app. + */ +class FixedBlockReader : public FixedBlockAdapter +{ +public: + FixedBlockReader(FixedBlockProcessor &fixedBlockProcessor); + + virtual ~FixedBlockReader() = default; + + int32_t open(int32_t bytesPerFixedBlock) override; + + /** + * Read into a variable sized block. + * + * Note that if the fixed-sized blocks must be aligned, then the variable-sized blocks + * must have the same alignment. + * For example, if the fixed-size blocks must be a multiple of 8, then the variable-sized + * blocks must also be a multiple of 8. + * + * @param buffer + * @param numBytes + * @return Number of bytes read or a negative error code. + */ + int32_t read(uint8_t *buffer, int32_t numBytes); + +private: + int32_t readFromStorage(uint8_t *buffer, int32_t numBytes); + + int32_t mValid = 0; // Number of valid bytes in mStorage. +}; + + +#endif /* AAUDIO_FIXED_BLOCK_READER_H */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockWriter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockWriter_android.cpp new file mode 100644 index 0000000..1ef2a6e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockWriter_android.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_common_FixedBlockAdapter_android.h" +#include "oboe_common_FixedBlockWriter_android.h" + +FixedBlockWriter::FixedBlockWriter(FixedBlockProcessor &fixedBlockProcessor) + : FixedBlockAdapter(fixedBlockProcessor) {} + + +int32_t FixedBlockWriter::writeToStorage(uint8_t *buffer, int32_t numBytes) { + int32_t bytesToStore = numBytes; + int32_t roomAvailable = mSize - mPosition; + if (bytesToStore > roomAvailable) { + bytesToStore = roomAvailable; + } + memcpy(mStorage.get() + mPosition, buffer, bytesToStore); + mPosition += bytesToStore; + return bytesToStore; +} + +int32_t FixedBlockWriter::write(uint8_t *buffer, int32_t numBytes) { + int32_t bytesLeft = numBytes; + + // If we already have data in storage then add to it. + if (mPosition > 0) { + int32_t bytesWritten = writeToStorage(buffer, bytesLeft); + buffer += bytesWritten; + bytesLeft -= bytesWritten; + // If storage full then flush it out + if (mPosition == mSize) { + bytesWritten = mFixedBlockProcessor.onProcessFixedBlock(mStorage.get(), mSize); + if (bytesWritten < 0) return bytesWritten; + mPosition = 0; + if (bytesWritten < mSize) { + // Only some of the data was written! This should not happen. + return -1; + } + } + } + + // Write through if enough for a complete block. + while(bytesLeft > mSize) { + int32_t bytesWritten = mFixedBlockProcessor.onProcessFixedBlock(buffer, mSize); + if (bytesWritten < 0) return bytesWritten; + buffer += bytesWritten; + bytesLeft -= bytesWritten; + } + + // Save any remaining partial blocks for next time. + if (bytesLeft > 0) { + int32_t bytesWritten = writeToStorage(buffer, bytesLeft); + bytesLeft -= bytesWritten; + } + + return numBytes - bytesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockWriter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockWriter_android.h new file mode 100644 index 0000000..b36ab21 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_FixedBlockWriter_android.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAUDIO_FIXED_BLOCK_WRITER_H +#define AAUDIO_FIXED_BLOCK_WRITER_H + +#include + +#include "oboe_common_FixedBlockAdapter_android.h" + +/** + * This can be used to convert a push data flow from variable sized buffers to fixed sized buffers. + * An example would be an audio input callback. + */ +class FixedBlockWriter : public FixedBlockAdapter +{ +public: + FixedBlockWriter(FixedBlockProcessor &fixedBlockProcessor); + + virtual ~FixedBlockWriter() = default; + + /** + * Write from a variable sized block. + * + * Note that if the fixed-sized blocks must be aligned, then the variable-sized blocks + * must have the same alignment. + * For example, if the fixed-size blocks must be a multiple of 8, then the variable-sized + * blocks must also be a multiple of 8. + * + * @param buffer + * @param numBytes + * @return Number of bytes written or a negative error code. + */ + int32_t write(uint8_t *buffer, int32_t numBytes); + +private: + + int32_t writeToStorage(uint8_t *buffer, int32_t numBytes); +}; + +#endif /* AAUDIO_FIXED_BLOCK_WRITER_H */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_LatencyTuner_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_LatencyTuner_android.cpp new file mode 100644 index 0000000..8aca447 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_LatencyTuner_android.cpp @@ -0,0 +1,108 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_oboe_LatencyTuner_android.h" + +using namespace oboe; + +LatencyTuner::LatencyTuner(AudioStream &stream) + : LatencyTuner(stream, stream.getBufferCapacityInFrames()) { +} + +LatencyTuner::LatencyTuner(oboe::AudioStream &stream, int32_t maximumBufferSize) + : mStream(stream) + , mMaxBufferSize(maximumBufferSize) { + int32_t burstSize = stream.getFramesPerBurst(); + setMinimumBufferSize(kDefaultNumBursts * burstSize); + setBufferSizeIncrement(burstSize); + reset(); +} + +Result LatencyTuner::tune() { + if (mState == State::Unsupported) { + return Result::ErrorUnimplemented; + } + + Result result = Result::OK; + + // Process reset requests. + int32_t numRequests = mLatencyTriggerRequests.load(); + if (numRequests != mLatencyTriggerResponses.load()) { + mLatencyTriggerResponses.store(numRequests); + reset(); + } + + // Set state to Active if the idle countdown has reached zero. + if (mState == State::Idle && --mIdleCountDown <= 0) { + mState = State::Active; + } + + // When state is Active attempt to change the buffer size if the number of xRuns has increased. + if (mState == State::Active) { + + auto xRunCountResult = mStream.getXRunCount(); + if (xRunCountResult == Result::OK) { + if ((xRunCountResult.value() - mPreviousXRuns) > 0) { + mPreviousXRuns = xRunCountResult.value(); + int32_t oldBufferSize = mStream.getBufferSizeInFrames(); + int32_t requestedBufferSize = oldBufferSize + getBufferSizeIncrement(); + + // Do not request more than the maximum buffer size (which was either user-specified + // or was from stream->getBufferCapacityInFrames()) + if (requestedBufferSize > mMaxBufferSize) requestedBufferSize = mMaxBufferSize; + + // Note that this will not allocate more memory. It simply determines + // how much of the existing buffer capacity will be used. The size will be + // clipped to the bufferCapacity by AAudio. + auto setBufferResult = mStream.setBufferSizeInFrames(requestedBufferSize); + if (setBufferResult != Result::OK) { + result = setBufferResult; + mState = State::Unsupported; + } else if (setBufferResult.value() == oldBufferSize) { + mState = State::AtMax; + } + } + } else { + mState = State::Unsupported; + } + } + + if (mState == State::Unsupported) { + result = Result::ErrorUnimplemented; + } + + if (mState == State::AtMax) { + result = Result::OK; + } + return result; +} + +void LatencyTuner::requestReset() { + if (mState != State::Unsupported) { + mLatencyTriggerRequests++; + } +} + +void LatencyTuner::reset() { + mState = State::Idle; + mIdleCountDown = kIdleCount; + // Set to minimal latency + mStream.setBufferSizeInFrames(getMinimumBufferSize()); +} + +bool LatencyTuner::isAtMaximumBufferSize() { + return mState == State::AtMax; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_MonotonicCounter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_MonotonicCounter_android.h new file mode 100644 index 0000000..00c979c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_MonotonicCounter_android.h @@ -0,0 +1,112 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COMMON_MONOTONIC_COUNTER_H +#define COMMON_MONOTONIC_COUNTER_H + +#include + +/** + * Maintain a 64-bit monotonic counter. + * Can be used to track a 32-bit counter that wraps or gets reset. + * + * Note that this is not atomic and has no interior locks. + * A caller will need to provide their own exterior locking + * if they need to use it from multiple threads. + */ +class MonotonicCounter { + +public: + MonotonicCounter() {} + virtual ~MonotonicCounter() {} + + /** + * @return current value of the counter + */ + int64_t get() const { + return mCounter64; + } + + /** + * set the current value of the counter + */ + void set(int64_t counter) { + mCounter64 = counter; + } + + /** + * Advance the counter if delta is positive. + * @return current value of the counter + */ + int64_t increment(int64_t delta) { + if (delta > 0) { + mCounter64 += delta; + } + return mCounter64; + } + + /** + * Advance the 64-bit counter if (current32 - previousCurrent32) > 0. + * This can be used to convert a 32-bit counter that may be wrapping into + * a monotonic 64-bit counter. + * + * This counter32 should NOT be allowed to advance by more than 0x7FFFFFFF between calls. + * Think of the wrapping counter like a sine wave. If the frequency of the signal + * is more than half the sampling rate (Nyquist rate) then you cannot measure it properly. + * If the counter wraps around every 24 hours then we should measure it with a period + * of less than 12 hours. + * + * @return current value of the 64-bit counter + */ + int64_t update32(int32_t counter32) { + int32_t delta = counter32 - mCounter32; + // protect against the mCounter64 going backwards + if (delta > 0) { + mCounter64 += delta; + mCounter32 = counter32; + } + return mCounter64; + } + + /** + * Reset the stored value of the 32-bit counter. + * This is used if your counter32 has been reset to zero. + */ + void reset32() { + mCounter32 = 0; + } + + /** + * Round 64-bit counter up to a multiple of the period. + * + * The period must be positive. + * + * @param period might be, for example, a buffer capacity + */ + void roundUp64(int32_t period) { + if (period > 0) { + int64_t numPeriods = (mCounter64 + period - 1) / period; + mCounter64 = numPeriods * period; + } + } + +private: + int64_t mCounter64 = 0; + int32_t mCounter32 = 0; +}; + + +#endif //COMMON_MONOTONIC_COUNTER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_OboeDebug_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_OboeDebug_android.h new file mode 100644 index 0000000..dc7434c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_OboeDebug_android.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef OBOE_DEBUG_H +#define OBOE_DEBUG_H + +#include + +#ifndef MODULE_NAME +#define MODULE_NAME "OboeAudio" +#endif + +// Always log INFO and errors. +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__) +#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, MODULE_NAME, __VA_ARGS__) +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, __VA_ARGS__) +#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, MODULE_NAME, __VA_ARGS__) + +#if OBOE_ENABLE_LOGGING +#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__) +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__) +#else +#define LOGV(...) +#define LOGD(...) +#endif + +#endif //OBOE_DEBUG_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_OboeExtensions_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_OboeExtensions_android.cpp new file mode 100644 index 0000000..5ef1eb3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_OboeExtensions_android.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_oboe_OboeExtensions_android.h" +#include "oboe_aaudio_AAudioExtensions_android.h" + +using namespace oboe; + +bool OboeExtensions::isMMapSupported(){ + return AAudioExtensions::getInstance().isMMapSupported(); +} + +bool OboeExtensions::isMMapEnabled(){ + return AAudioExtensions::getInstance().isMMapEnabled(); +} + +int32_t OboeExtensions::setMMapEnabled(bool enabled){ + return AAudioExtensions::getInstance().setMMapEnabled(enabled); +} + +bool OboeExtensions::isMMapUsed(oboe::AudioStream *oboeStream){ + return AAudioExtensions::getInstance().isMMapUsed(oboeStream); +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_QuirksManager_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_QuirksManager_android.cpp new file mode 100644 index 0000000..ba25d1a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_QuirksManager_android.cpp @@ -0,0 +1,304 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_oboe_Oboe_android.h" + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_common_QuirksManager_android.h" + +using namespace oboe; + +int32_t QuirksManager::DeviceQuirks::clipBufferSize(AudioStream &stream, + int32_t requestedSize) { + if (!OboeGlobals::areWorkaroundsEnabled()) { + return requestedSize; + } + int bottomMargin = kDefaultBottomMarginInBursts; + int topMargin = kDefaultTopMarginInBursts; + if (isMMapUsed(stream)) { + if (stream.getSharingMode() == SharingMode::Exclusive) { + bottomMargin = getExclusiveBottomMarginInBursts(); + topMargin = getExclusiveTopMarginInBursts(); + } + } else { + bottomMargin = kLegacyBottomMarginInBursts; + } + + int32_t burst = stream.getFramesPerBurst(); + int32_t minSize = bottomMargin * burst; + int32_t adjustedSize = requestedSize; + if (adjustedSize < minSize ) { + adjustedSize = minSize; + } else { + int32_t maxSize = stream.getBufferCapacityInFrames() - (topMargin * burst); + if (adjustedSize > maxSize ) { + adjustedSize = maxSize; + } + } + return adjustedSize; +} + +bool QuirksManager::DeviceQuirks::isAAudioMMapPossible(const AudioStreamBuilder &builder) const { + bool isSampleRateCompatible = + builder.getSampleRate() == oboe::Unspecified + || builder.getSampleRate() == kCommonNativeRate + || builder.getSampleRateConversionQuality() != SampleRateConversionQuality::None; + return builder.getPerformanceMode() == PerformanceMode::LowLatency + && isSampleRateCompatible + && builder.getChannelCount() <= kChannelCountStereo; +} + +bool QuirksManager::DeviceQuirks::shouldConvertFloatToI16ForOutputStreams() { + std::string productManufacturer = getPropertyString("ro.product.manufacturer"); + if (getSdkVersion() < __ANDROID_API_L__) { + return true; + } else if ((productManufacturer == "vivo") && (getSdkVersion() < __ANDROID_API_M__)) { + return true; + } + return false; +} + +/** + * This is for Samsung Exynos quirks. Samsung Mobile uses Qualcomm chips so + * the QualcommDeviceQuirks would apply. + */ +class SamsungExynosDeviceQuirks : public QuirksManager::DeviceQuirks { +public: + SamsungExynosDeviceQuirks() { + std::string chipname = getPropertyString("ro.hardware.chipname"); + isExynos9810 = (chipname == "exynos9810"); + isExynos990 = (chipname == "exynos990"); + isExynos850 = (chipname == "exynos850"); + + mBuildChangelist = getPropertyInteger("ro.build.changelist", 0); + } + + virtual ~SamsungExynosDeviceQuirks() = default; + + int32_t getExclusiveBottomMarginInBursts() const override { + return kBottomMargin; + } + + int32_t getExclusiveTopMarginInBursts() const override { + return kTopMargin; + } + + // See Oboe issues #824 and #1247 for more information. + bool isMonoMMapActuallyStereo() const override { + return isExynos9810 || isExynos850; // TODO We can make this version specific if it gets fixed. + } + + bool isAAudioMMapPossible(const AudioStreamBuilder &builder) const override { + return DeviceQuirks::isAAudioMMapPossible(builder) + // Samsung says they use Legacy for Camcorder + && builder.getInputPreset() != oboe::InputPreset::Camcorder; + } + + bool isMMapSafe(const AudioStreamBuilder &builder) override { + const bool isInput = builder.getDirection() == Direction::Input; + // This detects b/159066712 , S20 LSI has corrupt low latency audio recording + // and turns off MMAP. + // See also https://github.com/google/oboe/issues/892 + bool isRecordingCorrupted = isInput + && isExynos990 + && mBuildChangelist < 19350896; + + // Certain S9+ builds record silence when using MMAP and not using the VoiceCommunication + // preset. + // See https://github.com/google/oboe/issues/1110 + bool wouldRecordSilence = isInput + && isExynos9810 + && mBuildChangelist <= 18847185 + && (builder.getInputPreset() != InputPreset::VoiceCommunication); + + if (wouldRecordSilence){ + LOGI("QuirksManager::%s() Requested stream configuration would result in silence on " + "this device. Switching off MMAP.", __func__); + } + + return !isRecordingCorrupted && !wouldRecordSilence; + } + +private: + // Stay farther away from DSP position on Exynos devices. + static constexpr int32_t kBottomMargin = 2; + static constexpr int32_t kTopMargin = 1; + bool isExynos9810 = false; + bool isExynos990 = false; + bool isExynos850 = false; + int mBuildChangelist = 0; +}; + +class QualcommDeviceQuirks : public QuirksManager::DeviceQuirks { +public: + QualcommDeviceQuirks() { + std::string modelName = getPropertyString("ro.soc.model"); + isSM8150 = (modelName == "SDM8150"); + } + + virtual ~QualcommDeviceQuirks() = default; + + int32_t getExclusiveBottomMarginInBursts() const override { + return kBottomMargin; + } + + bool isMMapSafe(const AudioStreamBuilder &builder) override { + // See https://github.com/google/oboe/issues/1121#issuecomment-897957749 + bool isMMapBroken = false; + if (isSM8150 && (getSdkVersion() <= __ANDROID_API_P__)) { + LOGI("QuirksManager::%s() MMAP not actually supported on this chip." + " Switching off MMAP.", __func__); + isMMapBroken = true; + } + + return !isMMapBroken; + } + +private: + bool isSM8150 = false; + static constexpr int32_t kBottomMargin = 1; +}; + +QuirksManager::QuirksManager() { + std::string productManufacturer = getPropertyString("ro.product.manufacturer"); + if (productManufacturer == "samsung") { + std::string arch = getPropertyString("ro.arch"); + bool isExynos = (arch.rfind("exynos", 0) == 0); // starts with? + if (isExynos) { + mDeviceQuirks = std::make_unique(); + } + } + if (!mDeviceQuirks) { + std::string socManufacturer = getPropertyString("ro.soc.manufacturer"); + if (socManufacturer == "Qualcomm") { + // This may include Samsung Mobile devices. + mDeviceQuirks = std::make_unique(); + } else { + mDeviceQuirks = std::make_unique(); + } + } +} + +bool QuirksManager::isConversionNeeded( + const AudioStreamBuilder &builder, + AudioStreamBuilder &childBuilder) { + bool conversionNeeded = false; + const bool isLowLatency = builder.getPerformanceMode() == PerformanceMode::LowLatency; + const bool isInput = builder.getDirection() == Direction::Input; + const bool isFloat = builder.getFormat() == AudioFormat::Float; + + // There are multiple bugs involving using callback with a specified callback size. + // Issue #778: O to Q had a problem with Legacy INPUT streams for FLOAT streams + // and a specified callback size. It would assert because of a bad buffer size. + // + // Issue #973: O to R had a problem with Legacy output streams using callback and a specified callback size. + // An AudioTrack stream could still be running when the AAudio FixedBlockReader was closed. + // Internally b/161914201#comment25 + // + // Issue #983: O to R would glitch if the framesPerCallback was too small. + // + // Most of these problems were related to Legacy stream. MMAP was OK. But we don't + // know if we will get an MMAP stream. So, to be safe, just do the conversion in Oboe. + if (OboeGlobals::areWorkaroundsEnabled() + && builder.willUseAAudio() + && builder.isDataCallbackSpecified() + && builder.getFramesPerDataCallback() != 0 + && getSdkVersion() <= __ANDROID_API_R__) { + LOGI("QuirksManager::%s() avoid setFramesPerCallback(n>0)", __func__); + childBuilder.setFramesPerCallback(oboe::Unspecified); + conversionNeeded = true; + } + + // If a SAMPLE RATE is specified for low latency, let the native code choose an optimal rate. + // This isn't really a workaround. It is an Oboe feature that is convenient to place here. + // TODO There may be a problem if the devices supports low latency + // at a higher rate than the default. + if (builder.getSampleRate() != oboe::Unspecified + && builder.getSampleRateConversionQuality() != SampleRateConversionQuality::None + && isLowLatency + ) { + childBuilder.setSampleRate(oboe::Unspecified); // native API decides the best sample rate + conversionNeeded = true; + } + + // Data Format + // OpenSL ES and AAudio before P do not support FAST path for FLOAT capture. + if (OboeGlobals::areWorkaroundsEnabled() + && isFloat + && isInput + && builder.isFormatConversionAllowed() + && isLowLatency + && (!builder.willUseAAudio() || (getSdkVersion() < __ANDROID_API_P__)) + ) { + childBuilder.setFormat(AudioFormat::I16); // needed for FAST track + conversionNeeded = true; + LOGI("QuirksManager::%s() forcing internal format to I16 for low latency", __func__); + } + + // Add quirk for float output when needed. + if (OboeGlobals::areWorkaroundsEnabled() + && isFloat + && !isInput + && builder.isFormatConversionAllowed() + && mDeviceQuirks->shouldConvertFloatToI16ForOutputStreams() + ) { + childBuilder.setFormat(AudioFormat::I16); + conversionNeeded = true; + LOGI("QuirksManager::%s() float was requested but not supported on pre-L devices " + "and some devices like Vivo devices may have issues on L devices, " + "creating an underlying I16 stream and using format conversion to provide a float " + "stream", __func__); + } + + // Channel Count conversions + if (OboeGlobals::areWorkaroundsEnabled() + && builder.isChannelConversionAllowed() + && builder.getChannelCount() == kChannelCountStereo + && isInput + && isLowLatency + && (!builder.willUseAAudio() && (getSdkVersion() == __ANDROID_API_O__)) + ) { + // Workaround for heap size regression in O. + // b/66967812 AudioRecord does not allow FAST track for stereo capture in O + childBuilder.setChannelCount(kChannelCountMono); + conversionNeeded = true; + LOGI("QuirksManager::%s() using mono internally for low latency on O", __func__); + } else if (OboeGlobals::areWorkaroundsEnabled() + && builder.getChannelCount() == kChannelCountMono + && isInput + && mDeviceQuirks->isMonoMMapActuallyStereo() + && builder.willUseAAudio() + // Note: we might use this workaround on a device that supports + // MMAP but will use Legacy for this stream. But this will only happen + // on devices that have the broken mono. + && mDeviceQuirks->isAAudioMMapPossible(builder) + ) { + // Workaround for mono actually running in stereo mode. + childBuilder.setChannelCount(kChannelCountStereo); // Use stereo and extract first channel. + conversionNeeded = true; + LOGI("QuirksManager::%s() using stereo internally to avoid broken mono", __func__); + } + // Note that MMAP does not support mono in 8.1. But that would only matter on Pixel 1 + // phones and they have almost all been updated to 9.0. + + return conversionNeeded; +} + +bool QuirksManager::isMMapSafe(AudioStreamBuilder &builder) { + if (!OboeGlobals::areWorkaroundsEnabled()) return true; + return mDeviceQuirks->isMMapSafe(builder); +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_QuirksManager_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_QuirksManager_android.h new file mode 100644 index 0000000..c1ead82 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_QuirksManager_android.h @@ -0,0 +1,134 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_QUIRKS_MANAGER_H +#define OBOE_QUIRKS_MANAGER_H + +#include +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_aaudio_AudioStreamAAudio_android.h" + +#ifndef __ANDROID_API_R__ +#define __ANDROID_API_R__ 30 +#endif + +namespace oboe { + +/** + * INTERNAL USE ONLY. + * + * Based on manufacturer, model and Android version number + * decide whether data conversion needs to occur. + * + * This also manages device and version specific workarounds. + */ + +class QuirksManager { +public: + + static QuirksManager &getInstance() { + static QuirksManager instance; // singleton + return instance; + } + + QuirksManager(); + virtual ~QuirksManager() = default; + + /** + * Do we need to do channel, format or rate conversion to provide a low latency + * stream for this builder? If so then provide a builder for the native child stream + * that will be used to get low latency. + * + * @param builder builder provided by application + * @param childBuilder modified builder appropriate for the underlying device + * @return true if conversion is needed + */ + bool isConversionNeeded(const AudioStreamBuilder &builder, AudioStreamBuilder &childBuilder); + + static bool isMMapUsed(AudioStream &stream) { + bool answer = false; + if (stream.getAudioApi() == AudioApi::AAudio) { + AudioStreamAAudio *streamAAudio = + reinterpret_cast(&stream); + answer = streamAAudio->isMMapUsed(); + } + return answer; + } + + virtual int32_t clipBufferSize(AudioStream &stream, int32_t bufferSize) { + return mDeviceQuirks->clipBufferSize(stream, bufferSize); + } + + class DeviceQuirks { + public: + virtual ~DeviceQuirks() = default; + + /** + * Restrict buffer size. This is mainly to avoid glitches caused by MMAP + * timestamp inaccuracies. + * @param stream + * @param requestedSize + * @return + */ + int32_t clipBufferSize(AudioStream &stream, int32_t requestedSize); + + // Exclusive MMAP streams can have glitches because they are using a timing + // model of the DSP to control IO instead of direct synchronization. + virtual int32_t getExclusiveBottomMarginInBursts() const { + return kDefaultBottomMarginInBursts; + } + + virtual int32_t getExclusiveTopMarginInBursts() const { + return kDefaultTopMarginInBursts; + } + + // On some devices, you can open a mono stream but it is actually running in stereo! + virtual bool isMonoMMapActuallyStereo() const { + return false; + } + + virtual bool isAAudioMMapPossible(const AudioStreamBuilder &builder) const; + + virtual bool isMMapSafe(const AudioStreamBuilder & /* builder */ ) { + return true; + } + + // On some devices, Float does not work so it should be converted to I16. + static bool shouldConvertFloatToI16ForOutputStreams(); + + static constexpr int32_t kDefaultBottomMarginInBursts = 0; + static constexpr int32_t kDefaultTopMarginInBursts = 0; + + // For Legacy streams, do not let the buffer go below one burst. + // b/129545119 | AAudio Legacy allows setBufferSizeInFrames too low + // Fixed in Q + static constexpr int32_t kLegacyBottomMarginInBursts = 1; + static constexpr int32_t kCommonNativeRate = 48000; // very typical native sample rate + }; + + bool isMMapSafe(AudioStreamBuilder &builder); + +private: + + static constexpr int32_t kChannelCountMono = 1; + static constexpr int32_t kChannelCountStereo = 2; + + std::unique_ptr mDeviceQuirks{}; + +}; + +} +#endif //OBOE_QUIRKS_MANAGER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceFloatCaller_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceFloatCaller_android.cpp new file mode 100644 index 0000000..bcba239 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceFloatCaller_android.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_SourceFloatCaller_android.h" + +using namespace oboe; +using namespace flowgraph; + +int32_t SourceFloatCaller::onProcess(int32_t numFrames) { + int32_t numBytes = mStream->getBytesPerFrame() * numFrames; + int32_t bytesRead = mBlockReader.read((uint8_t *) output.getBuffer(), numBytes); + int32_t framesRead = bytesRead / mStream->getBytesPerFrame(); + return framesRead; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceFloatCaller_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceFloatCaller_android.h new file mode 100644 index 0000000..52924f1 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceFloatCaller_android.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_SOURCE_FLOAT_CALLER_H +#define OBOE_SOURCE_FLOAT_CALLER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_AudioSourceCaller_android.h" +#include "oboe_common_FixedBlockReader_android.h" + +namespace oboe { +/** + * AudioSource that uses callback to get more float data. + */ +class SourceFloatCaller : public AudioSourceCaller { +public: + SourceFloatCaller(int32_t channelCount, int32_t framesPerCallback) + : AudioSourceCaller(channelCount, framesPerCallback, (int32_t)sizeof(float)) {} + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceFloatCaller"; + } +}; + +} +#endif //OBOE_SOURCE_FLOAT_CALLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI16Caller_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI16Caller_android.cpp new file mode 100644 index 0000000..716469d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI16Caller_android.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_SourceI16Caller_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace oboe; +using namespace flowgraph; + +int32_t SourceI16Caller::onProcess(int32_t numFrames) { + int32_t numBytes = mStream->getBytesPerFrame() * numFrames; + int32_t bytesRead = mBlockReader.read((uint8_t *) mConversionBuffer.get(), numBytes); + int32_t framesRead = bytesRead / mStream->getBytesPerFrame(); + + float *floatData = output.getBuffer(); + const int16_t *shortData = mConversionBuffer.get(); + int32_t numSamples = framesRead * output.getSamplesPerFrame(); + +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_float_from_i16(floatData, shortData, numSamples); +#else + for (int i = 0; i < numSamples; i++) { + *floatData++ = *shortData++ * (1.0f / 32768); + } +#endif + + return framesRead; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI16Caller_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI16Caller_android.h new file mode 100644 index 0000000..ee6f477 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI16Caller_android.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_SOURCE_I16_CALLER_H +#define OBOE_SOURCE_I16_CALLER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_AudioSourceCaller_android.h" +#include "oboe_common_FixedBlockReader_android.h" + +namespace oboe { +/** + * AudioSource that uses callback to get more data. + */ +class SourceI16Caller : public AudioSourceCaller { +public: + SourceI16Caller(int32_t channelCount, int32_t framesPerCallback) + : AudioSourceCaller(channelCount, framesPerCallback, sizeof(int16_t)) { + mConversionBuffer = std::make_unique(static_cast(channelCount) + * static_cast(output.getFramesPerBuffer())); + } + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceI16Caller"; + } +private: + std::unique_ptr mConversionBuffer; +}; + +} +#endif //OBOE_SOURCE_I16_CALLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI24Caller_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI24Caller_android.cpp new file mode 100644 index 0000000..ee40b8f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI24Caller_android.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_SourceI24Caller_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace oboe; +using namespace flowgraph; + +int32_t SourceI24Caller::onProcess(int32_t numFrames) { + int32_t numBytes = mStream->getBytesPerFrame() * numFrames; + int32_t bytesRead = mBlockReader.read((uint8_t *) mConversionBuffer.get(), numBytes); + int32_t framesRead = bytesRead / mStream->getBytesPerFrame(); + + float *floatData = output.getBuffer(); + const uint8_t *byteData = mConversionBuffer.get(); + int32_t numSamples = framesRead * output.getSamplesPerFrame(); + +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_float_from_p24(floatData, byteData, numSamples); +#else + static const float scale = 1. / (float)(1UL << 31); + for (int i = 0; i < numSamples; i++) { + // Assemble the data assuming Little Endian format. + int32_t pad = byteData[2]; + pad <<= 8; + pad |= byteData[1]; + pad <<= 8; + pad |= byteData[0]; + pad <<= 8; // Shift to 32 bit data so the sign is correct. + byteData += kBytesPerI24Packed; + *floatData++ = pad * scale; // scale to range -1.0 to 1.0 + } +#endif + + return framesRead; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI24Caller_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI24Caller_android.h new file mode 100644 index 0000000..2cc8952 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI24Caller_android.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_SOURCE_I24_CALLER_H +#define OBOE_SOURCE_I24_CALLER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_AudioSourceCaller_android.h" +#include "oboe_common_FixedBlockReader_android.h" + +namespace oboe { + +/** + * AudioSource that uses callback to get more data. + */ +class SourceI24Caller : public AudioSourceCaller { +public: + SourceI24Caller(int32_t channelCount, int32_t framesPerCallback) + : AudioSourceCaller(channelCount, framesPerCallback, kBytesPerI24Packed) { + mConversionBuffer = std::make_unique(static_cast(kBytesPerI24Packed) + * static_cast(channelCount) + * static_cast(output.getFramesPerBuffer())); + } + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceI24Caller"; + } + +private: + std::unique_ptr mConversionBuffer; + static constexpr int kBytesPerI24Packed = 3; +}; + +} +#endif //OBOE_SOURCE_I16_CALLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI32Caller_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI32Caller_android.cpp new file mode 100644 index 0000000..7b33227 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI32Caller_android.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_SourceI32Caller_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace oboe; +using namespace flowgraph; + +int32_t SourceI32Caller::onProcess(int32_t numFrames) { + int32_t numBytes = mStream->getBytesPerFrame() * numFrames; + int32_t bytesRead = mBlockReader.read((uint8_t *) mConversionBuffer.get(), numBytes); + int32_t framesRead = bytesRead / mStream->getBytesPerFrame(); + + float *floatData = output.getBuffer(); + const int32_t *intData = mConversionBuffer.get(); + int32_t numSamples = framesRead * output.getSamplesPerFrame(); + +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_float_from_i32(floatData, shortData, numSamples); +#else + for (int i = 0; i < numSamples; i++) { + *floatData++ = *intData++ * kScale; + } +#endif + + return framesRead; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI32Caller_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI32Caller_android.h new file mode 100644 index 0000000..2e2b163 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_SourceI32Caller_android.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_SOURCE_I32_CALLER_H +#define OBOE_SOURCE_I32_CALLER_H + +#include +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_common_AudioSourceCaller_android.h" +#include "oboe_common_FixedBlockReader_android.h" + +namespace oboe { + +/** + * AudioSource that uses callback to get more data. + */ +class SourceI32Caller : public AudioSourceCaller { +public: + SourceI32Caller(int32_t channelCount, int32_t framesPerCallback) + : AudioSourceCaller(channelCount, framesPerCallback, sizeof(int32_t)) { + mConversionBuffer = std::make_unique(static_cast(channelCount) + * static_cast(output.getFramesPerBuffer())); + } + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceI32Caller"; + } + +private: + std::unique_ptr mConversionBuffer; + static constexpr float kScale = 1.0 / (1UL << 31); +}; + +} +#endif //OBOE_SOURCE_I32_CALLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_StabilizedCallback_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_StabilizedCallback_android.cpp new file mode 100644 index 0000000..ffca64e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_StabilizedCallback_android.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_oboe_StabilizedCallback_android.h" +#include "oboe_common_AudioClock_android.h" +#include "oboe_common_Trace_android.h" + +constexpr int32_t kLoadGenerationStepSizeNanos = 20000; +constexpr float kPercentageOfCallbackToUse = 0.8; + +using namespace oboe; + +StabilizedCallback::StabilizedCallback(AudioStreamCallback *callback) : mCallback(callback){ + Trace::initialize(); +} + +/** + * An audio callback which attempts to do work for a fixed amount of time. + * + * @param oboeStream + * @param audioData + * @param numFrames + * @return + */ +DataCallbackResult +StabilizedCallback::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) { + + int64_t startTimeNanos = AudioClock::getNanoseconds(); + + if (mFrameCount == 0){ + mEpochTimeNanos = startTimeNanos; + } + + int64_t durationSinceEpochNanos = startTimeNanos - mEpochTimeNanos; + + // In an ideal world the callback start time will be exactly the same as the duration of the + // frames already read/written into the stream. In reality the callback can start early + // or late. By finding the delta we can calculate the target duration for our stabilized + // callback. + int64_t idealStartTimeNanos = (mFrameCount * kNanosPerSecond) / oboeStream->getSampleRate(); + int64_t lateStartNanos = durationSinceEpochNanos - idealStartTimeNanos; + + if (lateStartNanos < 0){ + // This was an early start which indicates that our previous epoch was a late callback. + // Update our epoch to this more accurate time. + mEpochTimeNanos = startTimeNanos; + mFrameCount = 0; + } + + int64_t numFramesAsNanos = (numFrames * kNanosPerSecond) / oboeStream->getSampleRate(); + int64_t targetDurationNanos = static_cast( + (numFramesAsNanos * kPercentageOfCallbackToUse) - lateStartNanos); + + Trace::beginSection("Actual load"); + DataCallbackResult result = mCallback->onAudioReady(oboeStream, audioData, numFrames); + Trace::endSection(); + + int64_t executionDurationNanos = AudioClock::getNanoseconds() - startTimeNanos; + int64_t stabilizingLoadDurationNanos = targetDurationNanos - executionDurationNanos; + + Trace::beginSection("Stabilized load for %lldns", stabilizingLoadDurationNanos); + generateLoad(stabilizingLoadDurationNanos); + Trace::endSection(); + + // Wraparound: At 48000 frames per second mFrameCount wraparound will occur after 6m years, + // significantly longer than the average lifetime of an Android phone. + mFrameCount += numFrames; + return result; +} + +void StabilizedCallback::generateLoad(int64_t durationNanos) { + + int64_t currentTimeNanos = AudioClock::getNanoseconds(); + int64_t deadlineTimeNanos = currentTimeNanos + durationNanos; + + // opsPerStep gives us an estimated number of operations which need to be run to fully utilize + // the CPU for a fixed amount of time (specified by kLoadGenerationStepSizeNanos). + // After each step the opsPerStep value is re-calculated based on the actual time taken to + // execute those operations. + auto opsPerStep = (int)(mOpsPerNano * kLoadGenerationStepSizeNanos); + int64_t stepDurationNanos = 0; + int64_t previousTimeNanos = 0; + + while (currentTimeNanos <= deadlineTimeNanos){ + + for (int i = 0; i < opsPerStep; i++) cpu_relax(); + + previousTimeNanos = currentTimeNanos; + currentTimeNanos = AudioClock::getNanoseconds(); + stepDurationNanos = currentTimeNanos - previousTimeNanos; + + // Calculate exponential moving average to smooth out values, this acts as a low pass filter. + // @see https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + static const float kFilterCoefficient = 0.1; + auto measuredOpsPerNano = (double) opsPerStep / stepDurationNanos; + mOpsPerNano = kFilterCoefficient * measuredOpsPerNano + (1.0 - kFilterCoefficient) * mOpsPerNano; + opsPerStep = (int) (mOpsPerNano * kLoadGenerationStepSizeNanos); + } +} \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Trace_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Trace_android.cpp new file mode 100644 index 0000000..e10c78d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Trace_android.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_common_Trace_android.h" +#include "oboe_common_OboeDebug_android.h" + +static char buffer[256]; + +// Tracing functions +static void *(*ATrace_beginSection)(const char *sectionName); + +static void *(*ATrace_endSection)(); + +typedef void *(*fp_ATrace_beginSection)(const char *sectionName); + +typedef void *(*fp_ATrace_endSection)(); + +bool Trace::mIsTracingSupported = false; + +void Trace::beginSection(const char *format, ...){ + + if (mIsTracingSupported) { + va_list va; + va_start(va, format); + vsprintf(buffer, format, va); + ATrace_beginSection(buffer); + va_end(va); + } else { + LOGE("Tracing is either not initialized (call Trace::initialize()) " + "or not supported on this device"); + } +} + +void Trace::endSection() { + + if (mIsTracingSupported) { + ATrace_endSection(); + } +} + +void Trace::initialize() { + + // Using dlsym allows us to use tracing on API 21+ without needing android/trace.h which wasn't + // published until API 23 + void *lib = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL); + if (lib == nullptr) { + LOGE("Could not open libandroid.so to dynamically load tracing symbols"); + } else { + ATrace_beginSection = + reinterpret_cast( + dlsym(lib, "ATrace_beginSection")); + ATrace_endSection = + reinterpret_cast( + dlsym(lib, "ATrace_endSection")); + + if (ATrace_beginSection != nullptr && ATrace_endSection != nullptr){ + mIsTracingSupported = true; + } + } +} \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Trace_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Trace_android.h new file mode 100644 index 0000000..c7965f9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Trace_android.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_TRACE_H +#define OBOE_TRACE_H + +class Trace { + +public: + static void beginSection(const char *format, ...); + static void endSection(); + static void initialize(); + +private: + static bool mIsTracingSupported; +}; + +#endif //OBOE_TRACE_H \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Utilities_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Utilities_android.cpp new file mode 100644 index 0000000..e3fbe97 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Utilities_android.cpp @@ -0,0 +1,317 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include + +#ifdef __ANDROID__ +#include +#endif + +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_oboe_Definitions_android.h" +#include "oboe_oboe_Utilities_android.h" + +namespace oboe { + +constexpr float kScaleI16ToFloat = (1.0f / 32768.0f); + +void convertFloatToPcm16(const float *source, int16_t *destination, int32_t numSamples) { + for (int i = 0; i < numSamples; i++) { + float fval = source[i]; + fval += 1.0; // to avoid discontinuity at 0.0 caused by truncation + fval *= 32768.0f; + auto sample = static_cast(fval); + // clip to 16-bit range + if (sample < 0) sample = 0; + else if (sample > 0x0FFFF) sample = 0x0FFFF; + sample -= 32768; // center at zero + destination[i] = static_cast(sample); + } +} + +void convertPcm16ToFloat(const int16_t *source, float *destination, int32_t numSamples) { + for (int i = 0; i < numSamples; i++) { + destination[i] = source[i] * kScaleI16ToFloat; + } +} + +int32_t convertFormatToSizeInBytes(AudioFormat format) { + int32_t size = 0; + switch (format) { + case AudioFormat::I16: + size = sizeof(int16_t); + break; + case AudioFormat::Float: + size = sizeof(float); + break; + case AudioFormat::I24: + size = 3; // packed 24-bit data + break; + case AudioFormat::I32: + size = sizeof(int32_t); + break; + default: + break; + } + return size; +} + +template<> +const char *convertToText(Result returnCode) { + switch (returnCode) { + case Result::OK: return "OK"; + case Result::ErrorDisconnected: return "ErrorDisconnected"; + case Result::ErrorIllegalArgument: return "ErrorIllegalArgument"; + case Result::ErrorInternal: return "ErrorInternal"; + case Result::ErrorInvalidState: return "ErrorInvalidState"; + case Result::ErrorInvalidHandle: return "ErrorInvalidHandle"; + case Result::ErrorUnimplemented: return "ErrorUnimplemented"; + case Result::ErrorUnavailable: return "ErrorUnavailable"; + case Result::ErrorNoFreeHandles: return "ErrorNoFreeHandles"; + case Result::ErrorNoMemory: return "ErrorNoMemory"; + case Result::ErrorNull: return "ErrorNull"; + case Result::ErrorTimeout: return "ErrorTimeout"; + case Result::ErrorWouldBlock: return "ErrorWouldBlock"; + case Result::ErrorInvalidFormat: return "ErrorInvalidFormat"; + case Result::ErrorOutOfRange: return "ErrorOutOfRange"; + case Result::ErrorNoService: return "ErrorNoService"; + case Result::ErrorInvalidRate: return "ErrorInvalidRate"; + case Result::ErrorClosed: return "ErrorClosed"; + default: return "Unrecognized result"; + } +} + +template<> +const char *convertToText(AudioFormat format) { + switch (format) { + case AudioFormat::Invalid: return "Invalid"; + case AudioFormat::Unspecified: return "Unspecified"; + case AudioFormat::I16: return "I16"; + case AudioFormat::Float: return "Float"; + case AudioFormat::I24: return "I24"; + case AudioFormat::I32: return "I32"; + default: return "Unrecognized format"; + } +} + +template<> +const char *convertToText(PerformanceMode mode) { + switch (mode) { + case PerformanceMode::LowLatency: return "LowLatency"; + case PerformanceMode::None: return "None"; + case PerformanceMode::PowerSaving: return "PowerSaving"; + default: return "Unrecognized performance mode"; + } +} + +template<> +const char *convertToText(SharingMode mode) { + switch (mode) { + case SharingMode::Exclusive: return "Exclusive"; + case SharingMode::Shared: return "Shared"; + default: return "Unrecognized sharing mode"; + } +} + +template<> +const char *convertToText(DataCallbackResult result) { + switch (result) { + case DataCallbackResult::Continue: return "Continue"; + case DataCallbackResult::Stop: return "Stop"; + default: return "Unrecognized data callback result"; + } +} + +template<> +const char *convertToText(Direction direction) { + switch (direction) { + case Direction::Input: return "Input"; + case Direction::Output: return "Output"; + default: return "Unrecognized direction"; + } +} + +template<> +const char *convertToText(StreamState state) { + switch (state) { + case StreamState::Closed: return "Closed"; + case StreamState::Closing: return "Closing"; + case StreamState::Disconnected: return "Disconnected"; + case StreamState::Flushed: return "Flushed"; + case StreamState::Flushing: return "Flushing"; + case StreamState::Open: return "Open"; + case StreamState::Paused: return "Paused"; + case StreamState::Pausing: return "Pausing"; + case StreamState::Started: return "Started"; + case StreamState::Starting: return "Starting"; + case StreamState::Stopped: return "Stopped"; + case StreamState::Stopping: return "Stopping"; + case StreamState::Uninitialized: return "Uninitialized"; + case StreamState::Unknown: return "Unknown"; + default: return "Unrecognized stream state"; + } +} + +template<> +const char *convertToText(AudioApi audioApi) { + + switch (audioApi) { + case AudioApi::Unspecified: return "Unspecified"; + case AudioApi::OpenSLES: return "OpenSLES"; + case AudioApi::AAudio: return "AAudio"; + default: return "Unrecognized audio API"; + } +} + +template<> +const char *convertToText(AudioStream* stream) { + static std::string streamText; + std::stringstream s; + + s<<"StreamID: "<< static_cast(stream)<getDeviceId()<getDirection())<getAudioApi())<getBufferCapacityInFrames()<getBufferSizeInFrames()<getFramesPerBurst()<getFramesPerDataCallback()<getSampleRate()<getChannelCount()<getFormat())<getSharingMode())<getPerformanceMode()) + <getState())<getXRunCount()<getFramesRead()<getFramesWritten()< +const char *convertToText(Usage usage) { + + switch (usage) { + case Usage::Media: return "Media"; + case Usage::VoiceCommunication: return "VoiceCommunication"; + case Usage::VoiceCommunicationSignalling: return "VoiceCommunicationSignalling"; + case Usage::Alarm: return "Alarm"; + case Usage::Notification: return "Notification"; + case Usage::NotificationRingtone: return "NotificationRingtone"; + case Usage::NotificationEvent: return "NotificationEvent"; + case Usage::AssistanceAccessibility: return "AssistanceAccessibility"; + case Usage::AssistanceNavigationGuidance: return "AssistanceNavigationGuidance"; + case Usage::AssistanceSonification: return "AssistanceSonification"; + case Usage::Game: return "Game"; + case Usage::Assistant: return "Assistant"; + default: return "Unrecognized usage"; + } +} + +template<> +const char *convertToText(ContentType contentType) { + + switch (contentType) { + case ContentType::Speech: return "Speech"; + case ContentType::Music: return "Music"; + case ContentType::Movie: return "Movie"; + case ContentType::Sonification: return "Sonification"; + default: return "Unrecognized content type"; + } +} + +template<> +const char *convertToText(InputPreset inputPreset) { + + switch (inputPreset) { + case InputPreset::Generic: return "Generic"; + case InputPreset::Camcorder: return "Camcorder"; + case InputPreset::VoiceRecognition: return "VoiceRecognition"; + case InputPreset::VoiceCommunication: return "VoiceCommunication"; + case InputPreset::Unprocessed: return "Unprocessed"; + case InputPreset::VoicePerformance: return "VoicePerformance"; + default: return "Unrecognized input preset"; + } +} + +template<> +const char *convertToText(SessionId sessionId) { + + switch (sessionId) { + case SessionId::None: return "None"; + case SessionId::Allocate: return "Allocate"; + default: return "Unrecognized session id"; + } +} + +template<> +const char *convertToText(ChannelCount channelCount) { + + switch (channelCount) { + case ChannelCount::Unspecified: return "Unspecified"; + case ChannelCount::Mono: return "Mono"; + case ChannelCount::Stereo: return "Stereo"; + default: return "Unrecognized channel count"; + } +} + +std::string getPropertyString(const char * name) { + std::string result; +#ifdef __ANDROID__ + char valueText[PROP_VALUE_MAX] = {0}; + if (__system_property_get(name, valueText) != 0) { + result = valueText; + } +#else + (void) name; +#endif + return result; +} + +int getPropertyInteger(const char * name, int defaultValue) { + int result = defaultValue; +#ifdef __ANDROID__ + char valueText[PROP_VALUE_MAX] = {0}; + if (__system_property_get(name, valueText) != 0) { + result = atoi(valueText); + } +#else + (void) name; +#endif + return result; +} + +int getSdkVersion() { + static int sCachedSdkVersion = -1; +#ifdef __ANDROID__ + if (sCachedSdkVersion == -1) { + sCachedSdkVersion = getPropertyInteger("ro.build.version.sdk", -1); + } +#endif + return sCachedSdkVersion; +} + +int getChannelCountFromChannelMask(ChannelMask channelMask) { + return __builtin_popcount(static_cast(channelMask)); +} + +}// namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Version_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Version_android.cpp new file mode 100644 index 0000000..a9b2ff3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_common_Version_android.cpp @@ -0,0 +1,28 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "oboe_oboe_Version_android.h" + +namespace oboe { + + // This variable enables the version information to be read from the resulting binary e.g. + // by running `objdump -s --section=.data ` + // Please do not optimize or change in any way. + char kVersionText[] = "OboeVersion" OBOE_VERSION_TEXT; + + const char * getVersionText(){ + return kVersionText; + } +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoBuffer_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoBuffer_android.cpp new file mode 100644 index 0000000..f1917e8 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoBuffer_android.cpp @@ -0,0 +1,178 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "oboe_oboe_FifoControllerBase_android.h" +#include "oboe_fifo_FifoController_android.h" +#include "oboe_fifo_FifoControllerIndirect_android.h" +#include "oboe_oboe_FifoBuffer_android.h" + +namespace oboe { + +FifoBuffer::FifoBuffer(uint32_t bytesPerFrame, uint32_t capacityInFrames) + : mBytesPerFrame(bytesPerFrame) + , mStorage(nullptr) + , mFramesReadCount(0) + , mFramesUnderrunCount(0) +{ + mFifo = std::make_unique(capacityInFrames); + // allocate buffer + int32_t bytesPerBuffer = bytesPerFrame * capacityInFrames; + mStorage = new uint8_t[bytesPerBuffer]; + mStorageOwned = true; +} + +FifoBuffer::FifoBuffer( uint32_t bytesPerFrame, + uint32_t capacityInFrames, + std::atomic *readCounterAddress, + std::atomic *writeCounterAddress, + uint8_t *dataStorageAddress + ) + : mBytesPerFrame(bytesPerFrame) + , mStorage(dataStorageAddress) + , mFramesReadCount(0) + , mFramesUnderrunCount(0) +{ + mFifo = std::make_unique(capacityInFrames, + readCounterAddress, + writeCounterAddress); + mStorage = dataStorageAddress; + mStorageOwned = false; +} + +FifoBuffer::~FifoBuffer() { + if (mStorageOwned) { + delete[] mStorage; + } +} + +int32_t FifoBuffer::convertFramesToBytes(int32_t frames) { + return frames * mBytesPerFrame; +} + +int32_t FifoBuffer::read(void *buffer, int32_t numFrames) { + if (numFrames <= 0) { + return 0; + } + // safe because numFrames is guaranteed positive + uint32_t framesToRead = static_cast(numFrames); + uint32_t framesAvailable = mFifo->getFullFramesAvailable(); + framesToRead = std::min(framesToRead, framesAvailable); + + uint32_t readIndex = mFifo->getReadIndex(); // ranges 0 to capacity + uint8_t *destination = reinterpret_cast(buffer); + uint8_t *source = &mStorage[convertFramesToBytes(readIndex)]; + if ((readIndex + framesToRead) > mFifo->getFrameCapacity()) { + // read in two parts, first part here is at the end of the mStorage buffer + int32_t frames1 = static_cast(mFifo->getFrameCapacity() - readIndex); + int32_t numBytes = convertFramesToBytes(frames1); + if (numBytes < 0) { + return static_cast(Result::ErrorOutOfRange); + } + memcpy(destination, source, static_cast(numBytes)); + destination += numBytes; + // read second part, which is at the beginning of mStorage + source = &mStorage[0]; + int32_t frames2 = static_cast(framesToRead - frames1); + numBytes = convertFramesToBytes(frames2); + if (numBytes < 0) { + return static_cast(Result::ErrorOutOfRange); + } + memcpy(destination, source, static_cast(numBytes)); + } else { + // just read in one shot + int32_t numBytes = convertFramesToBytes(framesToRead); + if (numBytes < 0) { + return static_cast(Result::ErrorOutOfRange); + } + memcpy(destination, source, static_cast(numBytes)); + } + mFifo->advanceReadIndex(framesToRead); + + return framesToRead; +} + +int32_t FifoBuffer::write(const void *buffer, int32_t numFrames) { + if (numFrames <= 0) { + return 0; + } + // Guaranteed positive. + uint32_t framesToWrite = static_cast(numFrames); + uint32_t framesAvailable = mFifo->getEmptyFramesAvailable(); + framesToWrite = std::min(framesToWrite, framesAvailable); + + uint32_t writeIndex = mFifo->getWriteIndex(); + int byteIndex = convertFramesToBytes(writeIndex); + const uint8_t *source = reinterpret_cast(buffer); + uint8_t *destination = &mStorage[byteIndex]; + if ((writeIndex + framesToWrite) > mFifo->getFrameCapacity()) { + // write in two parts, first part here + int32_t frames1 = static_cast(mFifo->getFrameCapacity() - writeIndex); + int32_t numBytes = convertFramesToBytes(frames1); + if (numBytes < 0) { + return static_cast(Result::ErrorOutOfRange); + } + memcpy(destination, source, static_cast(numBytes)); + // read second part + source += convertFramesToBytes(frames1); + destination = &mStorage[0]; + int frames2 = static_cast(framesToWrite - frames1); + numBytes = convertFramesToBytes(frames2); + if (numBytes < 0) { + return static_cast(Result::ErrorOutOfRange); + } + memcpy(destination, source, static_cast(numBytes)); + } else { + // just write in one shot + int32_t numBytes = convertFramesToBytes(framesToWrite); + if (numBytes < 0) { + return static_cast(Result::ErrorOutOfRange); + } + memcpy(destination, source, static_cast(numBytes)); + } + mFifo->advanceWriteIndex(framesToWrite); + + return framesToWrite; +} + +int32_t FifoBuffer::readNow(void *buffer, int32_t numFrames) { + int32_t framesRead = read(buffer, numFrames); + if (framesRead < 0) { + return framesRead; + } + int32_t framesLeft = numFrames - framesRead; + mFramesReadCount += framesRead; + mFramesUnderrunCount += framesLeft; + // Zero out any samples we could not set. + if (framesLeft > 0) { + uint8_t *destination = reinterpret_cast(buffer); + destination += convertFramesToBytes(framesRead); // point to first byte not set + int32_t bytesToZero = convertFramesToBytes(framesLeft); + memset(destination, 0, static_cast(bytesToZero)); + } + + return framesRead; +} + + +uint32_t FifoBuffer::getBufferCapacityInFrames() const { + return mFifo->getFrameCapacity(); +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerBase_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerBase_android.cpp new file mode 100644 index 0000000..b6a4601 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerBase_android.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "oboe_oboe_FifoControllerBase_android.h" + +namespace oboe { + +FifoControllerBase::FifoControllerBase(uint32_t capacityInFrames) + : mTotalFrames(capacityInFrames) +{ + // Avoid ridiculously large buffers and the arithmetic wraparound issues that can follow. + assert(capacityInFrames <= (UINT32_MAX / 4)); +} + +uint32_t FifoControllerBase::getFullFramesAvailable() const { + uint64_t writeCounter = getWriteCounter(); + uint64_t readCounter = getReadCounter(); + if (readCounter > writeCounter) { + return 0; + } + uint64_t delta = writeCounter - readCounter; + if (delta >= mTotalFrames) { + return mTotalFrames; + } + // delta is now guaranteed to fit within the range of a uint32_t + return static_cast(delta); +} + +uint32_t FifoControllerBase::getReadIndex() const { + // % works with non-power of two sizes + return static_cast(getReadCounter() % mTotalFrames); +} + +void FifoControllerBase::advanceReadIndex(uint32_t numFrames) { + incrementReadCounter(numFrames); +} + +uint32_t FifoControllerBase::getEmptyFramesAvailable() const { + return static_cast(mTotalFrames - getFullFramesAvailable()); +} + +uint32_t FifoControllerBase::getWriteIndex() const { + // % works with non-power of two sizes + return static_cast(getWriteCounter() % mTotalFrames); +} + +void FifoControllerBase::advanceWriteIndex(uint32_t numFrames) { + incrementWriteCounter(numFrames); +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerIndirect_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerIndirect_android.cpp new file mode 100644 index 0000000..42a4057 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerIndirect_android.cpp @@ -0,0 +1,32 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_fifo_FifoControllerIndirect_android.h" + +namespace oboe { + +FifoControllerIndirect::FifoControllerIndirect(uint32_t numFrames, + std::atomic *readCounterAddress, + std::atomic *writeCounterAddress) + : FifoControllerBase(numFrames) + , mReadCounterAddress(readCounterAddress) + , mWriteCounterAddress(writeCounterAddress) +{ +} + +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerIndirect_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerIndirect_android.h new file mode 100644 index 0000000..449989e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoControllerIndirect_android.h @@ -0,0 +1,66 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVEOBOE_FIFOCONTROLLERINDIRECT_H +#define NATIVEOBOE_FIFOCONTROLLERINDIRECT_H + +#include +#include + +#include "oboe_oboe_FifoControllerBase_android.h" + +namespace oboe { + +/** + * A FifoControllerBase with counters external to the class. + */ +class FifoControllerIndirect : public FifoControllerBase { + +public: + FifoControllerIndirect(uint32_t bufferSize, + std::atomic *readCounterAddress, + std::atomic *writeCounterAddress); + virtual ~FifoControllerIndirect() = default; + + virtual uint64_t getReadCounter() const override { + return mReadCounterAddress->load(std::memory_order_acquire); + } + virtual void setReadCounter(uint64_t n) override { + mReadCounterAddress->store(n, std::memory_order_release); + } + virtual void incrementReadCounter(uint64_t n) override { + mReadCounterAddress->fetch_add(n, std::memory_order_acq_rel); + } + virtual uint64_t getWriteCounter() const override { + return mWriteCounterAddress->load(std::memory_order_acquire); + } + virtual void setWriteCounter(uint64_t n) override { + mWriteCounterAddress->store(n, std::memory_order_release); + } + virtual void incrementWriteCounter(uint64_t n) override { + mWriteCounterAddress->fetch_add(n, std::memory_order_acq_rel); + } + +private: + + std::atomic *mReadCounterAddress; + std::atomic *mWriteCounterAddress; + +}; + +} // namespace oboe + +#endif //NATIVEOBOE_FIFOCONTROLLERINDIRECT_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoController_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoController_android.cpp new file mode 100644 index 0000000..ae46b53 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoController_android.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_fifo_FifoController_android.h" + +namespace oboe { + +FifoController::FifoController(uint32_t numFrames) + : FifoControllerBase(numFrames) +{ + setReadCounter(0); + setWriteCounter(0); +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoController_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoController_android.h new file mode 100644 index 0000000..a040ab4 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_fifo_FifoController_android.h @@ -0,0 +1,62 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVEOBOE_FIFOCONTROLLER_H +#define NATIVEOBOE_FIFOCONTROLLER_H + +#include +#include + +#include "oboe_oboe_FifoControllerBase_android.h" + +namespace oboe { + +/** + * A FifoControllerBase with counters contained in the class. + */ +class FifoController : public FifoControllerBase +{ +public: + FifoController(uint32_t bufferSize); + virtual ~FifoController() = default; + + virtual uint64_t getReadCounter() const override { + return mReadCounter.load(std::memory_order_acquire); + } + virtual void setReadCounter(uint64_t n) override { + mReadCounter.store(n, std::memory_order_release); + } + virtual void incrementReadCounter(uint64_t n) override { + mReadCounter.fetch_add(n, std::memory_order_acq_rel); + } + virtual uint64_t getWriteCounter() const override { + return mWriteCounter.load(std::memory_order_acquire); + } + virtual void setWriteCounter(uint64_t n) override { + mWriteCounter.store(n, std::memory_order_release); + } + virtual void incrementWriteCounter(uint64_t n) override { + mWriteCounter.fetch_add(n, std::memory_order_acq_rel); + } + +private: + std::atomic mReadCounter{}; + std::atomic mWriteCounter{}; +}; + +} // namespace oboe + +#endif //NATIVEOBOE_FIFOCONTROLLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ChannelCountConverter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ChannelCountConverter_android.cpp new file mode 100644 index 0000000..91eae22 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ChannelCountConverter_android.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_ChannelCountConverter_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +ChannelCountConverter::ChannelCountConverter( + int32_t inputChannelCount, + int32_t outputChannelCount) + : input(*this, inputChannelCount) + , output(*this, outputChannelCount) { +} + +ChannelCountConverter::~ChannelCountConverter() = default; + +int32_t ChannelCountConverter::onProcess(int32_t numFrames) { + const float *inputBuffer = input.getBuffer(); + float *outputBuffer = output.getBuffer(); + int32_t inputChannelCount = input.getSamplesPerFrame(); + int32_t outputChannelCount = output.getSamplesPerFrame(); + for (int i = 0; i < numFrames; i++) { + int inputChannel = 0; + for (int outputChannel = 0; outputChannel < outputChannelCount; outputChannel++) { + // Copy input channels to output channels. + // Wrap if we run out of inputs. + // Discard if we run out of outputs. + outputBuffer[outputChannel] = inputBuffer[inputChannel]; + inputChannel = (inputChannel == inputChannelCount) + ? 0 : inputChannel + 1; + } + inputBuffer += inputChannelCount; + outputBuffer += outputChannelCount; + } + return numFrames; +} + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ChannelCountConverter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ChannelCountConverter_android.h new file mode 100644 index 0000000..dec8cf1 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ChannelCountConverter_android.h @@ -0,0 +1,52 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_CHANNEL_COUNT_CONVERTER_H +#define FLOWGRAPH_CHANNEL_COUNT_CONVERTER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * Change the number of number of channels without mixing. + * When increasing the channel count, duplicate input channels. + * When decreasing the channel count, drop input channels. + */ + class ChannelCountConverter : public FlowGraphNode { + public: + explicit ChannelCountConverter( + int32_t inputChannelCount, + int32_t outputChannelCount); + + virtual ~ChannelCountConverter(); + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "ChannelCountConverter"; + } + + FlowGraphPortFloatInput input; + FlowGraphPortFloatOutput output; + }; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_CHANNEL_COUNT_CONVERTER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ClipToRange_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ClipToRange_android.cpp new file mode 100644 index 0000000..d4a0731 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ClipToRange_android.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_ClipToRange_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +ClipToRange::ClipToRange(int32_t channelCount) + : FlowGraphFilter(channelCount) { +} + +int32_t ClipToRange::onProcess(int32_t numFrames) { + const float *inputBuffer = input.getBuffer(); + float *outputBuffer = output.getBuffer(); + + int32_t numSamples = numFrames * output.getSamplesPerFrame(); + for (int32_t i = 0; i < numSamples; i++) { + *outputBuffer++ = std::min(mMaximum, std::max(mMinimum, *inputBuffer++)); + } + + return numFrames; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ClipToRange_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ClipToRange_android.h new file mode 100644 index 0000000..eeadd49 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ClipToRange_android.h @@ -0,0 +1,68 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_CLIP_TO_RANGE_H +#define FLOWGRAPH_CLIP_TO_RANGE_H + +#include +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +// This is 3 dB, (10^(3/20)), to match the maximum headroom in AudioTrack for float data. +// It is designed to allow occasional transient peaks. +constexpr float kDefaultMaxHeadroom = 1.41253754f; +constexpr float kDefaultMinHeadroom = -kDefaultMaxHeadroom; + +class ClipToRange : public FlowGraphFilter { +public: + explicit ClipToRange(int32_t channelCount); + + virtual ~ClipToRange() = default; + + int32_t onProcess(int32_t numFrames) override; + + void setMinimum(float min) { + mMinimum = min; + } + + float getMinimum() const { + return mMinimum; + } + + void setMaximum(float min) { + mMaximum = min; + } + + float getMaximum() const { + return mMaximum; + } + + const char *getName() override { + return "ClipToRange"; + } + +private: + float mMinimum = kDefaultMinHeadroom; + float mMaximum = kDefaultMaxHeadroom; +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_CLIP_TO_RANGE_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowGraphNode_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowGraphNode_android.cpp new file mode 100644 index 0000000..48b739e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowGraphNode_android.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdio.h" +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +/***************************************************************************/ +int32_t FlowGraphNode::pullData(int32_t numFrames, int64_t callCount) { + int32_t frameCount = numFrames; + // Prevent recursion and multiple execution of nodes. + if (callCount > mLastCallCount) { + mLastCallCount = callCount; + if (mDataPulledAutomatically) { + // Pull from all the upstream nodes. + for (auto &port : mInputPorts) { + // TODO fix bug of leaving unused data in some ports if using multiple AudioSource + frameCount = port.get().pullData(callCount, frameCount); + } + } + if (frameCount > 0) { + frameCount = onProcess(frameCount); + } + mLastFrameCount = frameCount; + } else { + frameCount = mLastFrameCount; + } + return frameCount; +} + +void FlowGraphNode::pullReset() { + if (!mBlockRecursion) { + mBlockRecursion = true; // for cyclic graphs + // Pull reset from all the upstream nodes. + for (auto &port : mInputPorts) { + port.get().pullReset(); + } + mBlockRecursion = false; + reset(); + } +} + +void FlowGraphNode::reset() { + mLastFrameCount = 0; + mLastCallCount = kInitialCallCount; +} + +/***************************************************************************/ +FlowGraphPortFloat::FlowGraphPortFloat(FlowGraphNode &parent, + int32_t samplesPerFrame, + int32_t framesPerBuffer) + : FlowGraphPort(parent, samplesPerFrame) + , mFramesPerBuffer(framesPerBuffer) + , mBuffer(nullptr) { + size_t numFloats = static_cast(framesPerBuffer) * getSamplesPerFrame(); + mBuffer = std::make_unique(numFloats); +} + +/***************************************************************************/ +int32_t FlowGraphPortFloatOutput::pullData(int64_t callCount, int32_t numFrames) { + numFrames = std::min(getFramesPerBuffer(), numFrames); + return mContainingNode.pullData(numFrames, callCount); +} + +void FlowGraphPortFloatOutput::pullReset() { + mContainingNode.pullReset(); +} + +// These need to be in the .cpp file because of forward cross references. +void FlowGraphPortFloatOutput::connect(FlowGraphPortFloatInput *port) { + port->connect(this); +} + +void FlowGraphPortFloatOutput::disconnect(FlowGraphPortFloatInput *port) { + port->disconnect(this); +} + +/***************************************************************************/ +int32_t FlowGraphPortFloatInput::pullData(int64_t callCount, int32_t numFrames) { + return (mConnected == nullptr) + ? std::min(getFramesPerBuffer(), numFrames) + : mConnected->pullData(callCount, numFrames); +} +void FlowGraphPortFloatInput::pullReset() { + if (mConnected != nullptr) mConnected->pullReset(); +} + +float *FlowGraphPortFloatInput::getBuffer() { + if (mConnected == nullptr) { + return FlowGraphPortFloat::getBuffer(); // loaded using setValue() + } else { + return mConnected->getBuffer(); + } +} + +int32_t FlowGraphSink::pullData(int32_t numFrames) { + return FlowGraphNode::pullData(numFrames, getLastCallCount() + 1); +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowGraphNode_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowGraphNode_android.h new file mode 100644 index 0000000..2884c08 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowGraphNode_android.h @@ -0,0 +1,450 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * FlowGraph.h + * + * Processing node and ports that can be used in a simple data flow graph. + * This was designed to work with audio but could be used for other + * types of data. + */ + +#ifndef FLOWGRAPH_FLOW_GRAPH_NODE_H +#define FLOWGRAPH_FLOW_GRAPH_NODE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO Move these classes into separate files. +// TODO Review use of raw pointers for connect(). Maybe use smart pointers but need to avoid +// run-time deallocation in audio thread. + +// Set flags FLOWGRAPH_ANDROID_INTERNAL and FLOWGRAPH_OUTER_NAMESPACE based on whether compiler +// flag __ANDROID_NDK__ is defined. __ANDROID_NDK__ should be defined in oboe and not aaudio. + +#ifndef FLOWGRAPH_ANDROID_INTERNAL +#ifdef __ANDROID_NDK__ +#define FLOWGRAPH_ANDROID_INTERNAL 0 +#else +#define FLOWGRAPH_ANDROID_INTERNAL 1 +#endif // __ANDROID_NDK__ +#endif // FLOWGRAPH_ANDROID_INTERNAL + +#ifndef FLOWGRAPH_OUTER_NAMESPACE +#ifdef __ANDROID_NDK__ +#define FLOWGRAPH_OUTER_NAMESPACE oboe +#else +#define FLOWGRAPH_OUTER_NAMESPACE aaudio +#endif // __ANDROID_NDK__ +#endif // FLOWGRAPH_OUTER_NAMESPACE + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +// Default block size that can be overridden when the FlowGraphPortFloat is created. +// If it is too small then we will have too much overhead from switching between nodes. +// If it is too high then we will thrash the caches. +constexpr int kDefaultBufferSize = 8; // arbitrary + +class FlowGraphPort; +class FlowGraphPortFloatInput; + +/***************************************************************************/ +/** + * Base class for all nodes in the flowgraph. + */ +class FlowGraphNode { +public: + FlowGraphNode() = default; + virtual ~FlowGraphNode() = default; + + /** + * Read from the input ports, + * generate multiple frames of data then write the results to the output ports. + * + * @param numFrames maximum number of frames requested for processing + * @return number of frames actually processed + */ + virtual int32_t onProcess(int32_t numFrames) = 0; + + /** + * If the callCount is at or after the previous callCount then call + * pullData on all of the upstreamNodes. + * Then call onProcess(). + * This prevents infinite recursion in case of cyclic graphs. + * It also prevents nodes upstream from a branch from being executed twice. + * + * @param callCount + * @param numFrames + * @return number of frames valid + */ + int32_t pullData(int32_t numFrames, int64_t callCount); + + /** + * Recursively reset all the nodes in the graph, starting from a Sink. + * + * This must not be called at the same time as pullData! + */ + void pullReset(); + + /** + * Reset framePosition counters. + */ + virtual void reset(); + + void addInputPort(FlowGraphPort &port) { + mInputPorts.emplace_back(port); + } + + bool isDataPulledAutomatically() const { + return mDataPulledAutomatically; + } + + /** + * Set true if you want the data pulled through the graph automatically. + * This is the default. + * + * Set false if you want to pull the data from the input ports in the onProcess() method. + * You might do this, for example, in a sample rate converting node. + * + * @param automatic + */ + void setDataPulledAutomatically(bool automatic) { + mDataPulledAutomatically = automatic; + } + + virtual const char *getName() { + return "FlowGraph"; + } + + int64_t getLastCallCount() { + return mLastCallCount; + } + +protected: + + static constexpr int64_t kInitialCallCount = -1; + int64_t mLastCallCount = kInitialCallCount; + + std::vector> mInputPorts; + +private: + bool mDataPulledAutomatically = true; + bool mBlockRecursion = false; + int32_t mLastFrameCount = 0; + +}; + +/***************************************************************************/ +/** + * This is a connector that allows data to flow between modules. + * + * The ports are the primary means of interacting with a module. + * So they are generally declared as public. + * + */ +class FlowGraphPort { +public: + FlowGraphPort(FlowGraphNode &parent, int32_t samplesPerFrame) + : mContainingNode(parent) + , mSamplesPerFrame(samplesPerFrame) { + } + + virtual ~FlowGraphPort() = default; + + // Ports are often declared public. So let's make them non-copyable. + FlowGraphPort(const FlowGraphPort&) = delete; + FlowGraphPort& operator=(const FlowGraphPort&) = delete; + + int32_t getSamplesPerFrame() const { + return mSamplesPerFrame; + } + + virtual int32_t pullData(int64_t framePosition, int32_t numFrames) = 0; + + virtual void pullReset() {} + +protected: + FlowGraphNode &mContainingNode; + +private: + const int32_t mSamplesPerFrame = 1; +}; + +/***************************************************************************/ +/** + * This port contains a 32-bit float buffer that can contain several frames of data. + * Processing the data in a block improves performance. + * + * The size is framesPerBuffer * samplesPerFrame). + */ +class FlowGraphPortFloat : public FlowGraphPort { +public: + FlowGraphPortFloat(FlowGraphNode &parent, + int32_t samplesPerFrame, + int32_t framesPerBuffer = kDefaultBufferSize + ); + + virtual ~FlowGraphPortFloat() = default; + + int32_t getFramesPerBuffer() const { + return mFramesPerBuffer; + } + +protected: + + /** + * @return buffer internal to the port or from a connected port + */ + virtual float *getBuffer() { + return mBuffer.get(); + } + +private: + const int32_t mFramesPerBuffer = 1; + std::unique_ptr mBuffer; // allocated in constructor +}; + +/***************************************************************************/ +/** + * The results of a node's processing are stored in the buffers of the output ports. + */ +class FlowGraphPortFloatOutput : public FlowGraphPortFloat { +public: + FlowGraphPortFloatOutput(FlowGraphNode &parent, int32_t samplesPerFrame) + : FlowGraphPortFloat(parent, samplesPerFrame) { + } + + virtual ~FlowGraphPortFloatOutput() = default; + + using FlowGraphPortFloat::getBuffer; + + /** + * Connect to the input of another module. + * An input port can only have one connection. + * An output port can have multiple connections. + * If you connect a second output port to an input port + * then it overwrites the previous connection. + * + * This not thread safe. Do not modify the graph topology from another thread while running. + * Also do not delete a module while it is connected to another port if the graph is running. + */ + void connect(FlowGraphPortFloatInput *port); + + /** + * Disconnect from the input of another module. + * This not thread safe. + */ + void disconnect(FlowGraphPortFloatInput *port); + + /** + * Call the parent module's onProcess() method. + * That may pull data from its inputs and recursively + * process the entire graph. + * @return number of frames actually pulled + */ + int32_t pullData(int64_t framePosition, int32_t numFrames) override; + + + void pullReset() override; + +}; + +/***************************************************************************/ + +/** + * An input port for streaming audio data. + * You can set a value that will be used for processing. + * If you connect an output port to this port then its value will be used instead. + */ +class FlowGraphPortFloatInput : public FlowGraphPortFloat { +public: + FlowGraphPortFloatInput(FlowGraphNode &parent, int32_t samplesPerFrame) + : FlowGraphPortFloat(parent, samplesPerFrame) { + // Add to parent so it can pull data from each input. + parent.addInputPort(*this); + } + + virtual ~FlowGraphPortFloatInput() = default; + + /** + * If connected to an output port then this will return + * that output ports buffers. + * If not connected then it returns the input ports own buffer + * which can be loaded using setValue(). + */ + float *getBuffer() override; + + /** + * Write every value of the float buffer. + * This value will be ignored if an output port is connected + * to this port. + */ + void setValue(float value) { + int numFloats = kDefaultBufferSize * getSamplesPerFrame(); + float *buffer = getBuffer(); + for (int i = 0; i < numFloats; i++) { + *buffer++ = value; + } + } + + /** + * Connect to the output of another module. + * An input port can only have one connection. + * An output port can have multiple connections. + * This not thread safe. + */ + void connect(FlowGraphPortFloatOutput *port) { + assert(getSamplesPerFrame() == port->getSamplesPerFrame()); + mConnected = port; + } + + void disconnect(FlowGraphPortFloatOutput *port) { + assert(mConnected == port); + (void) port; + mConnected = nullptr; + } + + void disconnect() { + mConnected = nullptr; + } + + /** + * Pull data from any output port that is connected. + */ + int32_t pullData(int64_t framePosition, int32_t numFrames) override; + + void pullReset() override; + +private: + FlowGraphPortFloatOutput *mConnected = nullptr; +}; + +/***************************************************************************/ + +/** + * Base class for an edge node in a graph that has no upstream nodes. + * It outputs data but does not consume data. + * By default, it will read its data from an external buffer. + */ +class FlowGraphSource : public FlowGraphNode { +public: + explicit FlowGraphSource(int32_t channelCount) + : output(*this, channelCount) { + } + + virtual ~FlowGraphSource() = default; + + FlowGraphPortFloatOutput output; +}; + +/***************************************************************************/ + +/** + * Base class for an edge node in a graph that has no upstream nodes. + * It outputs data but does not consume data. + * By default, it will read its data from an external buffer. + */ +class FlowGraphSourceBuffered : public FlowGraphSource { +public: + explicit FlowGraphSourceBuffered(int32_t channelCount) + : FlowGraphSource(channelCount) {} + + virtual ~FlowGraphSourceBuffered() = default; + + /** + * Specify buffer that the node will read from. + * + * @param data TODO Consider using std::shared_ptr. + * @param numFrames + */ + void setData(const void *data, int32_t numFrames) { + mData = data; + mSizeInFrames = numFrames; + mFrameIndex = 0; + } + +protected: + const void *mData = nullptr; + int32_t mSizeInFrames = 0; // number of frames in mData + int32_t mFrameIndex = 0; // index of next frame to be processed +}; + +/***************************************************************************/ +/** + * Base class for an edge node in a graph that has no downstream nodes. + * It consumes data but does not output data. + * This graph will be executed when data is read() from this node + * by pulling data from upstream nodes. + */ +class FlowGraphSink : public FlowGraphNode { +public: + explicit FlowGraphSink(int32_t channelCount) + : input(*this, channelCount) { + } + + virtual ~FlowGraphSink() = default; + + FlowGraphPortFloatInput input; + + /** + * Do nothing. The work happens in the read() method. + * + * @param numFrames + * @return number of frames actually processed + */ + int32_t onProcess(int32_t numFrames) override { + return numFrames; + } + + virtual int32_t read(void *data, int32_t numFrames) = 0; + +protected: + /** + * Pull data through the graph using this nodes last callCount. + * @param numFrames + * @return + */ + int32_t pullData(int32_t numFrames); +}; + +/***************************************************************************/ +/** + * Base class for a node that has an input and an output with the same number of channels. + * This may include traditional filters, eg. FIR, but also include + * any processing node that converts input to output. + */ +class FlowGraphFilter : public FlowGraphNode { +public: + explicit FlowGraphFilter(int32_t channelCount) + : input(*this, channelCount) + , output(*this, channelCount) { + } + + virtual ~FlowGraphFilter() = default; + + FlowGraphPortFloatInput input; + FlowGraphPortFloatOutput output; +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif /* FLOWGRAPH_FLOW_GRAPH_NODE_H */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowgraphUtilities_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowgraphUtilities_android.h new file mode 100644 index 0000000..5e90588 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_FlowgraphUtilities_android.h @@ -0,0 +1,55 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_UTILITIES_H +#define FLOWGRAPH_UTILITIES_H + +#include + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +class FlowgraphUtilities { +public: +// This was copied from audio_utils/primitives.h +/** + * Convert a single-precision floating point value to a Q0.31 integer value. + * Rounds to nearest, ties away from 0. + * + * Values outside the range [-1.0, 1.0) are properly clamped to -2147483648 and 2147483647, + * including -Inf and +Inf. NaN values are considered undefined, and behavior may change + * depending on hardware and future implementation of this function. + */ +static int32_t clamp32FromFloat(float f) +{ + static const float scale = (float)(1UL << 31); + static const float limpos = 1.; + static const float limneg = -1.; + + if (f <= limneg) { + return INT32_MIN; + } else if (f >= limpos) { + return INT32_MAX; + } + f *= scale; + /* integer conversion is through truncation (though int to float is not). + * ensure that we round to nearest, ties away from 0. + */ + return f > 0 ? f + 0.5 : f - 0.5; +} + +}; + +#endif // FLOWGRAPH_UTILITIES_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ManyToMultiConverter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ManyToMultiConverter_android.cpp new file mode 100644 index 0000000..23dcd4f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ManyToMultiConverter_android.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_flowgraph_ManyToMultiConverter_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +ManyToMultiConverter::ManyToMultiConverter(int32_t channelCount) + : inputs(channelCount) + , output(*this, channelCount) { + for (int i = 0; i < channelCount; i++) { + inputs[i] = std::make_unique(*this, 1); + } +} + +int32_t ManyToMultiConverter::onProcess(int32_t numFrames) { + int32_t channelCount = output.getSamplesPerFrame(); + + for (int ch = 0; ch < channelCount; ch++) { + const float *inputBuffer = inputs[ch]->getBuffer(); + float *outputBuffer = output.getBuffer() + ch; + + for (int i = 0; i < numFrames; i++) { + // read one, write into the proper interleaved output channel + float sample = *inputBuffer++; + *outputBuffer = sample; + outputBuffer += channelCount; // advance to next multichannel frame + } + } + return numFrames; +} + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ManyToMultiConverter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ManyToMultiConverter_android.h new file mode 100644 index 0000000..9199ee7 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_ManyToMultiConverter_android.h @@ -0,0 +1,53 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_MANY_TO_MULTI_CONVERTER_H +#define FLOWGRAPH_MANY_TO_MULTI_CONVERTER_H + +#include +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * Combine multiple mono inputs into one interleaved multi-channel output. + */ +class ManyToMultiConverter : public flowgraph::FlowGraphNode { +public: + explicit ManyToMultiConverter(int32_t channelCount); + + virtual ~ManyToMultiConverter() = default; + + int32_t onProcess(int numFrames) override; + + void setEnabled(bool /*enabled*/) {} + + std::vector> inputs; + flowgraph::FlowGraphPortFloatOutput output; + + const char *getName() override { + return "ManyToMultiConverter"; + } + +private: +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_MANY_TO_MULTI_CONVERTER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoBlend_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoBlend_android.cpp new file mode 100644 index 0000000..da4bbd0 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoBlend_android.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_flowgraph_MonoBlend_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +MonoBlend::MonoBlend(int32_t channelCount) + : FlowGraphFilter(channelCount) + , mInvChannelCount(1. / channelCount) +{ +} + +int32_t MonoBlend::onProcess(int32_t numFrames) { + int32_t channelCount = output.getSamplesPerFrame(); + const float *inputBuffer = input.getBuffer(); + float *outputBuffer = output.getBuffer(); + + for (size_t i = 0; i < numFrames; ++i) { + float accum = 0; + for (size_t j = 0; j < channelCount; ++j) { + accum += *inputBuffer++; + } + accum *= mInvChannelCount; + for (size_t j = 0; j < channelCount; ++j) { + *outputBuffer++ = accum; + } + } + + return numFrames; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoBlend_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoBlend_android.h new file mode 100644 index 0000000..223275e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoBlend_android.h @@ -0,0 +1,48 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_MONO_BLEND_H +#define FLOWGRAPH_MONO_BLEND_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * Combine data between multiple channels so each channel is an average + * of all channels. + */ +class MonoBlend : public FlowGraphFilter { +public: + explicit MonoBlend(int32_t channelCount); + + virtual ~MonoBlend() = default; + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "MonoBlend"; + } +private: + const float mInvChannelCount; +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_MONO_BLEND diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoToMultiConverter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoToMultiConverter_android.cpp new file mode 100644 index 0000000..b70c780 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoToMultiConverter_android.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_MonoToMultiConverter_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +MonoToMultiConverter::MonoToMultiConverter(int32_t outputChannelCount) + : input(*this, 1) + , output(*this, outputChannelCount) { +} + +int32_t MonoToMultiConverter::onProcess(int32_t numFrames) { + const float *inputBuffer = input.getBuffer(); + float *outputBuffer = output.getBuffer(); + int32_t channelCount = output.getSamplesPerFrame(); + for (int i = 0; i < numFrames; i++) { + // read one, write many + float sample = *inputBuffer++; + for (int channel = 0; channel < channelCount; channel++) { + *outputBuffer++ = sample; + } + } + return numFrames; +} + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoToMultiConverter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoToMultiConverter_android.h new file mode 100644 index 0000000..a7a1453 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MonoToMultiConverter_android.h @@ -0,0 +1,49 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_MONO_TO_MULTI_CONVERTER_H +#define FLOWGRAPH_MONO_TO_MULTI_CONVERTER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * Convert a monophonic stream to a multi-channel interleaved stream + * with the same signal on each channel. + */ +class MonoToMultiConverter : public FlowGraphNode { +public: + explicit MonoToMultiConverter(int32_t outputChannelCount); + + virtual ~MonoToMultiConverter() = default; + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "MonoToMultiConverter"; + } + + FlowGraphPortFloatInput input; + FlowGraphPortFloatOutput output; +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_MONO_TO_MULTI_CONVERTER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToManyConverter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToManyConverter_android.cpp new file mode 100644 index 0000000..ab61645 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToManyConverter_android.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_MultiToManyConverter_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +MultiToManyConverter::MultiToManyConverter(int32_t channelCount) + : outputs(channelCount) + , input(*this, channelCount) { + for (int i = 0; i < channelCount; i++) { + outputs[i] = std::make_unique(*this, 1); + } +} + +MultiToManyConverter::~MultiToManyConverter() = default; + +int32_t MultiToManyConverter::onProcess(int32_t numFrames) { + int32_t channelCount = input.getSamplesPerFrame(); + + for (int ch = 0; ch < channelCount; ch++) { + const float *inputBuffer = input.getBuffer() + ch; + float *outputBuffer = outputs[ch]->getBuffer(); + + for (int i = 0; i < numFrames; i++) { + *outputBuffer++ = *inputBuffer; + inputBuffer += channelCount; + } + } + + return numFrames; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToManyConverter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToManyConverter_android.h new file mode 100644 index 0000000..47b6426 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToManyConverter_android.h @@ -0,0 +1,49 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_MULTI_TO_MANY_CONVERTER_H +#define FLOWGRAPH_MULTI_TO_MANY_CONVERTER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * Convert a multi-channel interleaved stream to multiple mono-channel + * outputs + */ + class MultiToManyConverter : public FlowGraphNode { + public: + explicit MultiToManyConverter(int32_t channelCount); + + virtual ~MultiToManyConverter(); + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "MultiToManyConverter"; + } + + std::vector> outputs; + flowgraph::FlowGraphPortFloatInput input; + }; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_MULTI_TO_MANY_CONVERTER_H \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToMonoConverter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToMonoConverter_android.cpp new file mode 100644 index 0000000..3b7888d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToMonoConverter_android.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_MultiToMonoConverter_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +MultiToMonoConverter::MultiToMonoConverter(int32_t inputChannelCount) + : input(*this, inputChannelCount) + , output(*this, 1) { +} + +MultiToMonoConverter::~MultiToMonoConverter() = default; + +int32_t MultiToMonoConverter::onProcess(int32_t numFrames) { + const float *inputBuffer = input.getBuffer(); + float *outputBuffer = output.getBuffer(); + int32_t channelCount = input.getSamplesPerFrame(); + for (int i = 0; i < numFrames; i++) { + // read first channel of multi stream, write many + *outputBuffer++ = *inputBuffer; + inputBuffer += channelCount; + } + return numFrames; +} + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToMonoConverter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToMonoConverter_android.h new file mode 100644 index 0000000..1d14de7 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_MultiToMonoConverter_android.h @@ -0,0 +1,49 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_MULTI_TO_MONO_CONVERTER_H +#define FLOWGRAPH_MULTI_TO_MONO_CONVERTER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * Convert a multi-channel interleaved stream to a monophonic stream + * by extracting channel[0]. + */ + class MultiToMonoConverter : public FlowGraphNode { + public: + explicit MultiToMonoConverter(int32_t inputChannelCount); + + virtual ~MultiToMonoConverter(); + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "MultiToMonoConverter"; + } + + FlowGraphPortFloatInput input; + FlowGraphPortFloatOutput output; + }; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_MULTI_TO_MONO_CONVERTER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_RampLinear_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_RampLinear_android.cpp new file mode 100644 index 0000000..1bb72bf --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_RampLinear_android.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_RampLinear_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +RampLinear::RampLinear(int32_t channelCount) + : FlowGraphFilter(channelCount) { + mTarget.store(1.0f); +} + +void RampLinear::setLengthInFrames(int32_t frames) { + mLengthInFrames = frames; +} + +void RampLinear::setTarget(float target) { + mTarget.store(target); + // If the ramp has not been used then start immediately at this level. + if (mLastCallCount == kInitialCallCount) { + forceCurrent(target); + } +} + +float RampLinear::interpolateCurrent() { + return mLevelTo - (mRemaining * mScaler); +} + +int32_t RampLinear::onProcess(int32_t numFrames) { + const float *inputBuffer = input.getBuffer(); + float *outputBuffer = output.getBuffer(); + int32_t channelCount = output.getSamplesPerFrame(); + + float target = getTarget(); + if (target != mLevelTo) { + // Start new ramp. Continue from previous level. + mLevelFrom = interpolateCurrent(); + mLevelTo = target; + mRemaining = mLengthInFrames; + mScaler = (mLevelTo - mLevelFrom) / mLengthInFrames; // for interpolation + } + + int32_t framesLeft = numFrames; + + if (mRemaining > 0) { // Ramping? This doesn't happen very often. + int32_t framesToRamp = std::min(framesLeft, mRemaining); + framesLeft -= framesToRamp; + while (framesToRamp > 0) { + float currentLevel = interpolateCurrent(); + for (int ch = 0; ch < channelCount; ch++) { + *outputBuffer++ = *inputBuffer++ * currentLevel; + } + mRemaining--; + framesToRamp--; + } + } + + // Process any frames after the ramp. + int32_t samplesLeft = framesLeft * channelCount; + for (int i = 0; i < samplesLeft; i++) { + *outputBuffer++ = *inputBuffer++ * mLevelTo; + } + + return numFrames; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_RampLinear_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_RampLinear_android.h new file mode 100644 index 0000000..2a67199 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_RampLinear_android.h @@ -0,0 +1,96 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_RAMP_LINEAR_H +#define FLOWGRAPH_RAMP_LINEAR_H + +#include +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * When the target is modified then the output will ramp smoothly + * between the original and the new target value. + * This can be used to smooth out control values and reduce pops. + * + * The target may be updated while a ramp is in progress, which will trigger + * a new ramp from the current value. + */ +class RampLinear : public FlowGraphFilter { +public: + explicit RampLinear(int32_t channelCount); + + virtual ~RampLinear() = default; + + int32_t onProcess(int32_t numFrames) override; + + /** + * This is used for the next ramp. + * Calling this does not affect a ramp that is in progress. + */ + void setLengthInFrames(int32_t frames); + + int32_t getLengthInFrames() const { + return mLengthInFrames; + } + + /** + * This may be safely called by another thread. + * @param target + */ + void setTarget(float target); + + float getTarget() const { + return mTarget.load(); + } + + /** + * Force the nextSegment to start from this level. + * + * WARNING: this can cause a discontinuity if called while the ramp is being used. + * Only call this when setting the initial ramp. + * + * @param level + */ + void forceCurrent(float level) { + mLevelFrom = level; + mLevelTo = level; + } + + const char *getName() override { + return "RampLinear"; + } + +private: + + float interpolateCurrent(); + + std::atomic mTarget; + + int32_t mLengthInFrames = 48000.0f / 100.0f ; // 10 msec at 48000 Hz; + int32_t mRemaining = 0; + float mScaler = 0.0f; + float mLevelFrom = 0.0f; + float mLevelTo = 0.0f; +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_RAMP_LINEAR_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SampleRateConverter_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SampleRateConverter_android.cpp new file mode 100644 index 0000000..f86eca7 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SampleRateConverter_android.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_flowgraph_SampleRateConverter_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +SampleRateConverter::SampleRateConverter(int32_t channelCount, + MultiChannelResampler &resampler) + : FlowGraphFilter(channelCount) + , mResampler(resampler) { + setDataPulledAutomatically(false); +} + +void SampleRateConverter::reset() { + FlowGraphNode::reset(); + mInputCursor = kInitialCallCount; +} + +// Return true if there is a sample available. +bool SampleRateConverter::isInputAvailable() { + // If we have consumed all of the input data then go out and get some more. + if (mInputCursor >= mNumValidInputFrames) { + mInputCallCount++; + mNumValidInputFrames = input.pullData(mInputCallCount, input.getFramesPerBuffer()); + mInputCursor = 0; + } + return (mInputCursor < mNumValidInputFrames); +} + +const float *SampleRateConverter::getNextInputFrame() { + const float *inputBuffer = input.getBuffer(); + return &inputBuffer[mInputCursor++ * input.getSamplesPerFrame()]; +} + +int32_t SampleRateConverter::onProcess(int32_t numFrames) { + float *outputBuffer = output.getBuffer(); + int32_t channelCount = output.getSamplesPerFrame(); + int framesLeft = numFrames; + while (framesLeft > 0) { + // Gather input samples as needed. + if(mResampler.isWriteNeeded()) { + if (isInputAvailable()) { + const float *frame = getNextInputFrame(); + mResampler.writeNextFrame(frame); + } else { + break; + } + } else { + // Output frame is interpolated from input samples. + mResampler.readNextFrame(outputBuffer); + outputBuffer += channelCount; + framesLeft--; + } + } + return numFrames - framesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SampleRateConverter_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SampleRateConverter_android.h new file mode 100644 index 0000000..6ec8ae3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SampleRateConverter_android.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SAMPLE_RATE_CONVERTER_H +#define FLOWGRAPH_SAMPLE_RATE_CONVERTER_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_resampler_MultiChannelResampler_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +class SampleRateConverter : public FlowGraphFilter { +public: + explicit SampleRateConverter(int32_t channelCount, + resampler::MultiChannelResampler &mResampler); + + virtual ~SampleRateConverter() = default; + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SampleRateConverter"; + } + + void reset() override; + +private: + + // Return true if there is a sample available. + bool isInputAvailable(); + + // This assumes data is available. Only call after calling isInputAvailable(). + const float *getNextInputFrame(); + + resampler::MultiChannelResampler &mResampler; + + int32_t mInputCursor = 0; // offset into the input port buffer + int32_t mNumValidInputFrames = 0; // number of valid frames currently in the input port buffer + // We need our own callCount for upstream calls because calls occur at a different rate. + // This means we cannot have cyclic graphs or merges that contain an SRC. + int64_t mInputCallCount = 0; + +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SAMPLE_RATE_CONVERTER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkFloat_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkFloat_android.cpp new file mode 100644 index 0000000..e89e85f --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkFloat_android.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_SinkFloat_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SinkFloat::SinkFloat(int32_t channelCount) + : FlowGraphSink(channelCount) { +} + +int32_t SinkFloat::read(void *data, int32_t numFrames) { + float *floatData = (float *) data; + const int32_t channelCount = input.getSamplesPerFrame(); + + int32_t framesLeft = numFrames; + while (framesLeft > 0) { + // Run the graph and pull data through the input port. + int32_t framesPulled = pullData(framesLeft); + if (framesPulled <= 0) { + break; + } + const float *signal = input.getBuffer(); + int32_t numSamples = framesPulled * channelCount; + memcpy(floatData, signal, numSamples * sizeof(float)); + floatData += numSamples; + framesLeft -= framesPulled; + } + return numFrames - framesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkFloat_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkFloat_android.h new file mode 100644 index 0000000..adbce83 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkFloat_android.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef FLOWGRAPH_SINK_FLOAT_H +#define FLOWGRAPH_SINK_FLOAT_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * AudioSink that lets you read data as 32-bit floats. + */ +class SinkFloat : public FlowGraphSink { +public: + explicit SinkFloat(int32_t channelCount); + ~SinkFloat() override = default; + + int32_t read(void *data, int32_t numFrames) override; + + const char *getName() override { + return "SinkFloat"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SINK_FLOAT_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI16_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI16_android.cpp new file mode 100644 index 0000000..41142ad --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI16_android.cpp @@ -0,0 +1,57 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_flowgraph_SinkI16_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SinkI16::SinkI16(int32_t channelCount) + : FlowGraphSink(channelCount) {} + +int32_t SinkI16::read(void *data, int32_t numFrames) { + int16_t *shortData = (int16_t *) data; + const int32_t channelCount = input.getSamplesPerFrame(); + + int32_t framesLeft = numFrames; + while (framesLeft > 0) { + // Run the graph and pull data through the input port. + int32_t framesRead = pullData(framesLeft); + if (framesRead <= 0) { + break; + } + const float *signal = input.getBuffer(); + int32_t numSamples = framesRead * channelCount; +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_i16_from_float(shortData, signal, numSamples); + shortData += numSamples; + signal += numSamples; +#else + for (int i = 0; i < numSamples; i++) { + int32_t n = (int32_t) (*signal++ * 32768.0f); + *shortData++ = std::min(INT16_MAX, std::max(INT16_MIN, n)); // clip + } +#endif + framesLeft -= framesRead; + } + return numFrames - framesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI16_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI16_android.h new file mode 100644 index 0000000..5ac36a0 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI16_android.h @@ -0,0 +1,43 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SINK_I16_H +#define FLOWGRAPH_SINK_I16_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * AudioSink that lets you read data as 16-bit signed integers. + */ +class SinkI16 : public FlowGraphSink { +public: + explicit SinkI16(int32_t channelCount); + + int32_t read(void *data, int32_t numFrames) override; + + const char *getName() override { + return "SinkI16"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SINK_I16_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI24_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI24_android.cpp new file mode 100644 index 0000000..4926d0d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI24_android.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_SinkI24_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SinkI24::SinkI24(int32_t channelCount) + : FlowGraphSink(channelCount) {} + +int32_t SinkI24::read(void *data, int32_t numFrames) { + uint8_t *byteData = (uint8_t *) data; + const int32_t channelCount = input.getSamplesPerFrame(); + + int32_t framesLeft = numFrames; + while (framesLeft > 0) { + // Run the graph and pull data through the input port. + int32_t framesRead = pullData(framesLeft); + if (framesRead <= 0) { + break; + } + const float *floatData = input.getBuffer(); + int32_t numSamples = framesRead * channelCount; +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_p24_from_float(byteData, floatData, numSamples); + static const int kBytesPerI24Packed = 3; + byteData += numSamples * kBytesPerI24Packed; + floatData += numSamples; +#else + const int32_t kI24PackedMax = 0x007FFFFF; + const int32_t kI24PackedMin = 0xFF800000; + for (int i = 0; i < numSamples; i++) { + int32_t n = (int32_t) (*floatData++ * 0x00800000); + n = std::min(kI24PackedMax, std::max(kI24PackedMin, n)); // clip + // Write as a packed 24-bit integer in Little Endian format. + *byteData++ = (uint8_t) n; + *byteData++ = (uint8_t) (n >> 8); + *byteData++ = (uint8_t) (n >> 16); + } +#endif + framesLeft -= framesRead; + } + return numFrames - framesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI24_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI24_android.h new file mode 100644 index 0000000..74d1ec9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI24_android.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SINK_I24_H +#define FLOWGRAPH_SINK_I24_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * AudioSink that lets you read data as packed 24-bit signed integers. + * The sample size is 3 bytes. + */ +class SinkI24 : public FlowGraphSink { +public: + explicit SinkI24(int32_t channelCount); + + int32_t read(void *data, int32_t numFrames) override; + + const char *getName() override { + return "SinkI24"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SINK_I24_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI32_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI32_android.cpp new file mode 100644 index 0000000..8f1adcb --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI32_android.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_FlowgraphUtilities_android.h" +#include "oboe_flowgraph_SinkI32_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SinkI32::SinkI32(int32_t channelCount) + : FlowGraphSink(channelCount) {} + +int32_t SinkI32::read(void *data, int32_t numFrames) { + int32_t *intData = (int32_t *) data; + const int32_t channelCount = input.getSamplesPerFrame(); + + int32_t framesLeft = numFrames; + while (framesLeft > 0) { + // Run the graph and pull data through the input port. + int32_t framesRead = pullData(framesLeft); + if (framesRead <= 0) { + break; + } + const float *signal = input.getBuffer(); + int32_t numSamples = framesRead * channelCount; +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_i32_from_float(intData, signal, numSamples); + intData += numSamples; + signal += numSamples; +#else + for (int i = 0; i < numSamples; i++) { + *intData++ = FlowgraphUtilities::clamp32FromFloat(*signal++); + } +#endif + framesLeft -= framesRead; + } + return numFrames - framesLeft; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI32_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI32_android.h new file mode 100644 index 0000000..221692b --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SinkI32_android.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SINK_I32_H +#define FLOWGRAPH_SINK_I32_H + +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +class SinkI32 : public FlowGraphSink { +public: + explicit SinkI32(int32_t channelCount); + ~SinkI32() override = default; + + int32_t read(void *data, int32_t numFrames) override; + + const char *getName() override { + return "SinkI32"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SINK_I32_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceFloat_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceFloat_android.cpp new file mode 100644 index 0000000..5780240 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceFloat_android.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_SourceFloat_android.h" + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SourceFloat::SourceFloat(int32_t channelCount) + : FlowGraphSourceBuffered(channelCount) { +} + +int32_t SourceFloat::onProcess(int32_t numFrames) { + float *outputBuffer = output.getBuffer(); + const int32_t channelCount = output.getSamplesPerFrame(); + + const int32_t framesLeft = mSizeInFrames - mFrameIndex; + const int32_t framesToProcess = std::min(numFrames, framesLeft); + const int32_t numSamples = framesToProcess * channelCount; + + const float *floatBase = (float *) mData; + const float *floatData = &floatBase[mFrameIndex * channelCount]; + memcpy(outputBuffer, floatData, numSamples * sizeof(float)); + mFrameIndex += framesToProcess; + return framesToProcess; +} + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceFloat_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceFloat_android.h new file mode 100644 index 0000000..461b202 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceFloat_android.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SOURCE_FLOAT_H +#define FLOWGRAPH_SOURCE_FLOAT_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * AudioSource that reads a block of pre-defined float data. + */ +class SourceFloat : public FlowGraphSourceBuffered { +public: + explicit SourceFloat(int32_t channelCount); + ~SourceFloat() override = default; + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceFloat"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SOURCE_FLOAT_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI16_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI16_android.cpp new file mode 100644 index 0000000..cf0696a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI16_android.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_SourceI16_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SourceI16::SourceI16(int32_t channelCount) + : FlowGraphSourceBuffered(channelCount) { +} + +int32_t SourceI16::onProcess(int32_t numFrames) { + float *floatData = output.getBuffer(); + int32_t channelCount = output.getSamplesPerFrame(); + + int32_t framesLeft = mSizeInFrames - mFrameIndex; + int32_t framesToProcess = std::min(numFrames, framesLeft); + int32_t numSamples = framesToProcess * channelCount; + + const int16_t *shortBase = static_cast(mData); + const int16_t *shortData = &shortBase[mFrameIndex * channelCount]; + +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_float_from_i16(floatData, shortData, numSamples); +#else + for (int i = 0; i < numSamples; i++) { + *floatData++ = *shortData++ * (1.0f / 32768); + } +#endif + + mFrameIndex += framesToProcess; + return framesToProcess; +} \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI16_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI16_android.h new file mode 100644 index 0000000..edcf2c5 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI16_android.h @@ -0,0 +1,42 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SOURCE_I16_H +#define FLOWGRAPH_SOURCE_I16_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { +/** + * AudioSource that reads a block of pre-defined 16-bit integer data. + */ +class SourceI16 : public FlowGraphSourceBuffered { +public: + explicit SourceI16(int32_t channelCount); + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceI16"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SOURCE_I16_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI24_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI24_android.cpp new file mode 100644 index 0000000..cb61cb7 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI24_android.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_SourceI24_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +constexpr int kBytesPerI24Packed = 3; + +SourceI24::SourceI24(int32_t channelCount) + : FlowGraphSourceBuffered(channelCount) { +} + +int32_t SourceI24::onProcess(int32_t numFrames) { + float *floatData = output.getBuffer(); + int32_t channelCount = output.getSamplesPerFrame(); + + int32_t framesLeft = mSizeInFrames - mFrameIndex; + int32_t framesToProcess = std::min(numFrames, framesLeft); + int32_t numSamples = framesToProcess * channelCount; + + const uint8_t *byteBase = (uint8_t *) mData; + const uint8_t *byteData = &byteBase[mFrameIndex * channelCount * kBytesPerI24Packed]; + +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_float_from_p24(floatData, byteData, numSamples); +#else + static const float scale = 1. / (float)(1UL << 31); + for (int i = 0; i < numSamples; i++) { + // Assemble the data assuming Little Endian format. + int32_t pad = byteData[2]; + pad <<= 8; + pad |= byteData[1]; + pad <<= 8; + pad |= byteData[0]; + pad <<= 8; // Shift to 32 bit data so the sign is correct. + byteData += kBytesPerI24Packed; + *floatData++ = pad * scale; // scale to range -1.0 to 1.0 + } +#endif + + mFrameIndex += framesToProcess; + return framesToProcess; +} \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI24_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI24_android.h new file mode 100644 index 0000000..9d98296 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI24_android.h @@ -0,0 +1,43 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SOURCE_I24_H +#define FLOWGRAPH_SOURCE_I24_H + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +/** + * AudioSource that reads a block of pre-defined 24-bit packed integer data. + */ +class SourceI24 : public FlowGraphSourceBuffered { +public: + explicit SourceI24(int32_t channelCount); + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceI24"; + } +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SOURCE_I24_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI32_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI32_android.cpp new file mode 100644 index 0000000..26f0bb3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI32_android.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" +#include "oboe_flowgraph_SourceI32_android.h" + +#if FLOWGRAPH_ANDROID_INTERNAL +#include +#endif + +using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; + +SourceI32::SourceI32(int32_t channelCount) + : FlowGraphSourceBuffered(channelCount) { +} + +int32_t SourceI32::onProcess(int32_t numFrames) { + float *floatData = output.getBuffer(); + const int32_t channelCount = output.getSamplesPerFrame(); + + const int32_t framesLeft = mSizeInFrames - mFrameIndex; + const int32_t framesToProcess = std::min(numFrames, framesLeft); + const int32_t numSamples = framesToProcess * channelCount; + + const int32_t *intBase = static_cast(mData); + const int32_t *intData = &intBase[mFrameIndex * channelCount]; + +#if FLOWGRAPH_ANDROID_INTERNAL + memcpy_to_float_from_i32(floatData, intData, numSamples); +#else + for (int i = 0; i < numSamples; i++) { + *floatData++ = *intData++ * kScale; + } +#endif + + mFrameIndex += framesToProcess; + return framesToProcess; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI32_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI32_android.h new file mode 100644 index 0000000..ed82a08 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_SourceI32_android.h @@ -0,0 +1,42 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLOWGRAPH_SOURCE_I32_H +#define FLOWGRAPH_SOURCE_I32_H + +#include + +#include "oboe_flowgraph_FlowGraphNode_android.h" + +namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph { + +class SourceI32 : public FlowGraphSourceBuffered { +public: + explicit SourceI32(int32_t channelCount); + ~SourceI32() override = default; + + int32_t onProcess(int32_t numFrames) override; + + const char *getName() override { + return "SourceI32"; + } +private: + static constexpr float kScale = 1.0 / (1UL << 31); +}; + +} /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */ + +#endif //FLOWGRAPH_SOURCE_I32_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_HyperbolicCosineWindow_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_HyperbolicCosineWindow_android.h new file mode 100644 index 0000000..f2f94c3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_HyperbolicCosineWindow_android.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_HYPERBOLIC_COSINE_WINDOW_H +#define RESAMPLER_HYPERBOLIC_COSINE_WINDOW_H + +#include + +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +/** + * Calculate a HyperbolicCosineWindow window centered at 0. + * This can be used in place of a Kaiser window. + * + * The code is based on an anonymous contribution by "a concerned citizen": + * https://dsp.stackexchange.com/questions/37714/kaiser-window-approximation + */ +class HyperbolicCosineWindow { +public: + HyperbolicCosineWindow() { + setStopBandAttenuation(60); + } + + /** + * @param attenuation typical values range from 30 to 90 dB + * @return beta + */ + double setStopBandAttenuation(double attenuation) { + double alpha = ((-325.1e-6 * attenuation + 0.1677) * attenuation) - 3.149; + setAlpha(alpha); + return alpha; + } + + void setAlpha(double alpha) { + mAlpha = alpha; + mInverseCoshAlpha = 1.0 / cosh(alpha); + } + + /** + * @param x ranges from -1.0 to +1.0 + */ + double operator()(double x) { + double x2 = x * x; + if (x2 >= 1.0) return 0.0; + double w = mAlpha * sqrt(1.0 - x2); + return cosh(w) * mInverseCoshAlpha; + } + +private: + double mAlpha = 0.0; + double mInverseCoshAlpha = 1.0; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_HYPERBOLIC_COSINE_WINDOW_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_IntegerRatio_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_IntegerRatio_android.cpp new file mode 100644 index 0000000..e16307a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_IntegerRatio_android.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_flowgraph_resampler_IntegerRatio_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +// Enough primes to cover the common sample rates. +static const int kPrimes[] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, + 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, + 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199}; + +void IntegerRatio::reduce() { + for (int prime : kPrimes) { + if (mNumerator < prime || mDenominator < prime) { + break; + } + + // Find biggest prime factor for numerator. + while (true) { + int top = mNumerator / prime; + int bottom = mDenominator / prime; + if ((top >= 1) + && (bottom >= 1) + && (top * prime == mNumerator) // divided evenly? + && (bottom * prime == mDenominator)) { + mNumerator = top; + mDenominator = bottom; + } else { + break; + } + } + + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_IntegerRatio_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_IntegerRatio_android.h new file mode 100644 index 0000000..ca10d24 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_IntegerRatio_android.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_INTEGER_RATIO_H +#define RESAMPLER_INTEGER_RATIO_H + +#include + +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +/** + * Represent the ratio of two integers. + */ +class IntegerRatio { +public: + IntegerRatio(int32_t numerator, int32_t denominator) + : mNumerator(numerator), mDenominator(denominator) {} + + /** + * Reduce by removing common prime factors. + */ + void reduce(); + + int32_t getNumerator() { + return mNumerator; + } + + int32_t getDenominator() { + return mDenominator; + } + +private: + int32_t mNumerator; + int32_t mDenominator; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_INTEGER_RATIO_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_KaiserWindow_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_KaiserWindow_android.h new file mode 100644 index 0000000..059c8fc --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_KaiserWindow_android.h @@ -0,0 +1,90 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_KAISER_WINDOW_H +#define RESAMPLER_KAISER_WINDOW_H + +#include + +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +/** + * Calculate a Kaiser window centered at 0. + */ +class KaiserWindow { +public: + KaiserWindow() { + setStopBandAttenuation(60); + } + + /** + * @param attenuation typical values range from 30 to 90 dB + * @return beta + */ + double setStopBandAttenuation(double attenuation) { + double beta = 0.0; + if (attenuation > 50) { + beta = 0.1102 * (attenuation - 8.7); + } else if (attenuation >= 21) { + double a21 = attenuation - 21; + beta = 0.5842 * pow(a21, 0.4) + (0.07886 * a21); + } + setBeta(beta); + return beta; + } + + void setBeta(double beta) { + mBeta = beta; + mInverseBesselBeta = 1.0 / bessel(beta); + } + + /** + * @param x ranges from -1.0 to +1.0 + */ + double operator()(double x) { + double x2 = x * x; + if (x2 >= 1.0) return 0.0; + double w = mBeta * sqrt(1.0 - x2); + return bessel(w) * mInverseBesselBeta; + } + + // Approximation of a + // modified zero order Bessel function of the first kind. + // Based on a discussion at: + // https://dsp.stackexchange.com/questions/37714/kaiser-window-approximation + static double bessel(double x) { + double y = cosh(0.970941817426052 * x); + y += cosh(0.8854560256532099 * x); + y += cosh(0.7485107481711011 * x); + y += cosh(0.5680647467311558 * x); + y += cosh(0.3546048870425356 * x); + y += cosh(0.120536680255323 * x); + y *= 2; + y += cosh(x); + y /= 13; + return y; + } + +private: + double mBeta = 0.0; + double mInverseBesselBeta = 1.0; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_KAISER_WINDOW_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_LinearResampler_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_LinearResampler_android.cpp new file mode 100644 index 0000000..616a762 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_LinearResampler_android.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_flowgraph_resampler_LinearResampler_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +LinearResampler::LinearResampler(const MultiChannelResampler::Builder &builder) + : MultiChannelResampler(builder) { + mPreviousFrame = std::make_unique(getChannelCount()); + mCurrentFrame = std::make_unique(getChannelCount()); +} + +void LinearResampler::writeFrame(const float *frame) { + memcpy(mPreviousFrame.get(), mCurrentFrame.get(), sizeof(float) * getChannelCount()); + memcpy(mCurrentFrame.get(), frame, sizeof(float) * getChannelCount()); +} + +void LinearResampler::readFrame(float *frame) { + float *previous = mPreviousFrame.get(); + float *current = mCurrentFrame.get(); + float phase = (float) getIntegerPhase() / mDenominator; + // iterate across samples in the frame + for (int channel = 0; channel < getChannelCount(); channel++) { + float f0 = *previous++; + float f1 = *current++; + *frame++ = f0 + (phase * (f1 - f0)); + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_LinearResampler_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_LinearResampler_android.h new file mode 100644 index 0000000..51a7cce --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_LinearResampler_android.h @@ -0,0 +1,47 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_LINEAR_RESAMPLER_H +#define RESAMPLER_LINEAR_RESAMPLER_H + +#include +#include +#include + +#include "oboe_flowgraph_resampler_MultiChannelResampler_android.h" +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +/** + * Simple resampler that uses bi-linear interpolation. + */ +class LinearResampler : public MultiChannelResampler { +public: + explicit LinearResampler(const MultiChannelResampler::Builder &builder); + + void writeFrame(const float *frame) override; + + void readFrame(float *frame) override; + +private: + std::unique_ptr mPreviousFrame; + std::unique_ptr mCurrentFrame; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_LINEAR_RESAMPLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_MultiChannelResampler_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_MultiChannelResampler_android.cpp new file mode 100644 index 0000000..830d4e3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_MultiChannelResampler_android.cpp @@ -0,0 +1,172 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_flowgraph_resampler_IntegerRatio_android.h" +#include "oboe_flowgraph_resampler_LinearResampler_android.h" +#include "oboe_flowgraph_resampler_MultiChannelResampler_android.h" +#include "oboe_flowgraph_resampler_PolyphaseResampler_android.h" +#include "oboe_flowgraph_resampler_PolyphaseResamplerMono_android.h" +#include "oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.h" +#include "oboe_flowgraph_resampler_SincResampler_android.h" +#include "oboe_flowgraph_resampler_SincResamplerStereo_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +MultiChannelResampler::MultiChannelResampler(const MultiChannelResampler::Builder &builder) + : mNumTaps(builder.getNumTaps()) + , mX(static_cast(builder.getChannelCount()) + * static_cast(builder.getNumTaps()) * 2) + , mSingleFrame(builder.getChannelCount()) + , mChannelCount(builder.getChannelCount()) + { + // Reduce sample rates to the smallest ratio. + // For example 44100/48000 would become 147/160. + IntegerRatio ratio(builder.getInputRate(), builder.getOutputRate()); + ratio.reduce(); + mNumerator = ratio.getNumerator(); + mDenominator = ratio.getDenominator(); + mIntegerPhase = mDenominator; // so we start with a write needed +} + +// static factory method +MultiChannelResampler *MultiChannelResampler::make(int32_t channelCount, + int32_t inputRate, + int32_t outputRate, + Quality quality) { + Builder builder; + builder.setInputRate(inputRate); + builder.setOutputRate(outputRate); + builder.setChannelCount(channelCount); + + switch (quality) { + case Quality::Fastest: + builder.setNumTaps(2); + break; + case Quality::Low: + builder.setNumTaps(4); + break; + case Quality::Medium: + default: + builder.setNumTaps(8); + break; + case Quality::High: + builder.setNumTaps(16); + break; + case Quality::Best: + builder.setNumTaps(32); + break; + } + + // Set the cutoff frequency so that we do not get aliasing when down-sampling. + if (inputRate > outputRate) { + builder.setNormalizedCutoff(kDefaultNormalizedCutoff); + } + return builder.build(); +} + +MultiChannelResampler *MultiChannelResampler::Builder::build() { + if (getNumTaps() == 2) { + // Note that this does not do low pass filteringh. + return new LinearResampler(*this); + } + IntegerRatio ratio(getInputRate(), getOutputRate()); + ratio.reduce(); + bool usePolyphase = (getNumTaps() * ratio.getDenominator()) <= kMaxCoefficients; + if (usePolyphase) { + if (getChannelCount() == 1) { + return new PolyphaseResamplerMono(*this); + } else if (getChannelCount() == 2) { + return new PolyphaseResamplerStereo(*this); + } else { + return new PolyphaseResampler(*this); + } + } else { + // Use less optimized resampler that uses a float phaseIncrement. + // TODO mono resampler + if (getChannelCount() == 2) { + return new SincResamplerStereo(*this); + } else { + return new SincResampler(*this); + } + } +} + +void MultiChannelResampler::writeFrame(const float *frame) { + // Move cursor before write so that cursor points to last written frame in read. + if (--mCursor < 0) { + mCursor = getNumTaps() - 1; + } + float *dest = &mX[static_cast(mCursor) * static_cast(getChannelCount())]; + int offset = getNumTaps() * getChannelCount(); + for (int channel = 0; channel < getChannelCount(); channel++) { + // Write twice so we avoid having to wrap when reading. + dest[channel] = dest[channel + offset] = frame[channel]; + } +} + +float MultiChannelResampler::sinc(float radians) { + if (abs(radians) < 1.0e-9) return 1.0f; // avoid divide by zero + return sinf(radians) / radians; // Sinc function +} + +// Generate coefficients in the order they will be used by readFrame(). +// This is more complicated but readFrame() is called repeatedly and should be optimized. +void MultiChannelResampler::generateCoefficients(int32_t inputRate, + int32_t outputRate, + int32_t numRows, + double phaseIncrement, + float normalizedCutoff) { + mCoefficients.resize(static_cast(getNumTaps()) * static_cast(numRows)); + int coefficientIndex = 0; + double phase = 0.0; // ranges from 0.0 to 1.0, fraction between samples + // Stretch the sinc function for low pass filtering. + const float cutoffScaler = normalizedCutoff * + ((outputRate < inputRate) + ? ((float)outputRate / inputRate) + : ((float)inputRate / outputRate)); + const int numTapsHalf = getNumTaps() / 2; // numTaps must be even. + const float numTapsHalfInverse = 1.0f / numTapsHalf; + for (int i = 0; i < numRows; i++) { + float tapPhase = phase - numTapsHalf; + float gain = 0.0; // sum of raw coefficients + int gainCursor = coefficientIndex; + for (int tap = 0; tap < getNumTaps(); tap++) { + float radians = tapPhase * M_PI; + +#if MCR_USE_KAISER + float window = mKaiserWindow(tapPhase * numTapsHalfInverse); +#else + float window = mCoshWindow(static_cast(tapPhase) * numTapsHalfInverse); +#endif + float coefficient = sinc(radians * cutoffScaler) * window; + mCoefficients.at(coefficientIndex++) = coefficient; + gain += coefficient; + tapPhase += 1.0; + } + phase += phaseIncrement; + while (phase >= 1.0) { + phase -= 1.0; + } + + // Correct for gain variations. + float gainCorrection = 1.0 / gain; // normalize the gain + for (int tap = 0; tap < getNumTaps(); tap++) { + mCoefficients.at(gainCursor + tap) *= gainCorrection; + } + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_MultiChannelResampler_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_MultiChannelResampler_android.h new file mode 100644 index 0000000..0dde44e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_MultiChannelResampler_android.h @@ -0,0 +1,274 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_MULTICHANNEL_RESAMPLER_H +#define RESAMPLER_MULTICHANNEL_RESAMPLER_H + +#include +#include +#include +#include + +#ifndef MCR_USE_KAISER +// It appears from the spectrogram that the HyperbolicCosine window leads to fewer artifacts. +// And it is faster to calculate. +#define MCR_USE_KAISER 0 +#endif + +#if MCR_USE_KAISER +#include "oboe_flowgraph_resampler_KaiserWindow_android.h" +#else +#include "oboe_flowgraph_resampler_HyperbolicCosineWindow_android.h" +#endif + +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +class MultiChannelResampler { + +public: + + enum class Quality : int32_t { + Fastest, + Low, + Medium, + High, + Best, + }; + + class Builder { + public: + /** + * Construct an optimal resampler based on the specified parameters. + * @return address of a resampler + */ + MultiChannelResampler *build(); + + /** + * The number of taps in the resampling filter. + * More taps gives better quality but uses more CPU time. + * This typically ranges from 4 to 64. Default is 16. + * + * For polyphase filters, numTaps must be a multiple of four for loop unrolling. + * @param numTaps number of taps for the filter + * @return address of this builder for chaining calls + */ + Builder *setNumTaps(int32_t numTaps) { + mNumTaps = numTaps; + return this; + } + + /** + * Use 1 for mono, 2 for stereo, etc. Default is 1. + * + * @param channelCount number of channels + * @return address of this builder for chaining calls + */ + Builder *setChannelCount(int32_t channelCount) { + mChannelCount = channelCount; + return this; + } + + /** + * Default is 48000. + * + * @param inputRate sample rate of the input stream + * @return address of this builder for chaining calls + */ + Builder *setInputRate(int32_t inputRate) { + mInputRate = inputRate; + return this; + } + + /** + * Default is 48000. + * + * @param outputRate sample rate of the output stream + * @return address of this builder for chaining calls + */ + Builder *setOutputRate(int32_t outputRate) { + mOutputRate = outputRate; + return this; + } + + /** + * Set cutoff frequency relative to the Nyquist rate of the output sample rate. + * Set to 1.0 to match the Nyquist frequency. + * Set lower to reduce aliasing. + * Default is 0.70. + * + * @param normalizedCutoff anti-aliasing filter cutoff + * @return address of this builder for chaining calls + */ + Builder *setNormalizedCutoff(float normalizedCutoff) { + mNormalizedCutoff = normalizedCutoff; + return this; + } + + int32_t getNumTaps() const { + return mNumTaps; + } + + int32_t getChannelCount() const { + return mChannelCount; + } + + int32_t getInputRate() const { + return mInputRate; + } + + int32_t getOutputRate() const { + return mOutputRate; + } + + float getNormalizedCutoff() const { + return mNormalizedCutoff; + } + + protected: + int32_t mChannelCount = 1; + int32_t mNumTaps = 16; + int32_t mInputRate = 48000; + int32_t mOutputRate = 48000; + float mNormalizedCutoff = kDefaultNormalizedCutoff; + }; + + virtual ~MultiChannelResampler() = default; + + /** + * Factory method for making a resampler that is optimal for the given inputs. + * + * @param channelCount number of channels, 2 for stereo + * @param inputRate sample rate of the input stream + * @param outputRate sample rate of the output stream + * @param quality higher quality sounds better but uses more CPU + * @return an optimal resampler + */ + static MultiChannelResampler *make(int32_t channelCount, + int32_t inputRate, + int32_t outputRate, + Quality quality); + + bool isWriteNeeded() const { + return mIntegerPhase >= mDenominator; + } + + /** + * Write a frame containing N samples. + * + * @param frame pointer to the first sample in a frame + */ + void writeNextFrame(const float *frame) { + writeFrame(frame); + advanceWrite(); + } + + /** + * Read a frame containing N samples. + * + * @param frame pointer to the first sample in a frame + */ + void readNextFrame(float *frame) { + readFrame(frame); + advanceRead(); + } + + int getNumTaps() const { + return mNumTaps; + } + + int getChannelCount() const { + return mChannelCount; + } + + static float hammingWindow(float radians, float spread); + + static float sinc(float radians); + +protected: + + explicit MultiChannelResampler(const MultiChannelResampler::Builder &builder); + + /** + * Write a frame containing N samples. + * Call advanceWrite() after calling this. + * @param frame pointer to the first sample in a frame + */ + virtual void writeFrame(const float *frame); + + /** + * Read a frame containing N samples using interpolation. + * Call advanceRead() after calling this. + * @param frame pointer to the first sample in a frame + */ + virtual void readFrame(float *frame) = 0; + + void advanceWrite() { + mIntegerPhase -= mDenominator; + } + + void advanceRead() { + mIntegerPhase += mNumerator; + } + + /** + * Generate the filter coefficients in optimal order. + * @param inputRate sample rate of the input stream + * @param outputRate sample rate of the output stream + * @param numRows number of rows in the array that contain a set of tap coefficients + * @param phaseIncrement how much to increment the phase between rows + * @param normalizedCutoff filter cutoff frequency normalized to Nyquist rate of output + */ + void generateCoefficients(int32_t inputRate, + int32_t outputRate, + int32_t numRows, + double phaseIncrement, + float normalizedCutoff); + + + int32_t getIntegerPhase() { + return mIntegerPhase; + } + + static constexpr int kMaxCoefficients = 8 * 1024; + std::vector mCoefficients; + + const int mNumTaps; + int mCursor = 0; + std::vector mX; // delayed input values for the FIR + std::vector mSingleFrame; // one frame for temporary use + int32_t mIntegerPhase = 0; + int32_t mNumerator = 0; + int32_t mDenominator = 0; + + +private: + +#if MCR_USE_KAISER + KaiserWindow mKaiserWindow; +#else + HyperbolicCosineWindow mCoshWindow; +#endif + + static constexpr float kDefaultNormalizedCutoff = 0.70f; + + const int mChannelCount; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_MULTICHANNEL_RESAMPLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerMono_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerMono_android.cpp new file mode 100644 index 0000000..6e149ec --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerMono_android.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_flowgraph_resampler_PolyphaseResamplerMono_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +#define MONO 1 + +PolyphaseResamplerMono::PolyphaseResamplerMono(const MultiChannelResampler::Builder &builder) + : PolyphaseResampler(builder) { + assert(builder.getChannelCount() == MONO); +} + +void PolyphaseResamplerMono::writeFrame(const float *frame) { + // Move cursor before write so that cursor points to last written frame in read. + if (--mCursor < 0) { + mCursor = getNumTaps() - 1; + } + float *dest = &mX[mCursor * MONO]; + const int offset = mNumTaps * MONO; + // Write each channel twice so we avoid having to wrap when running the FIR. + const float sample = frame[0]; + // Put ordered writes together. + dest[0] = sample; + dest[offset] = sample; +} + +void PolyphaseResamplerMono::readFrame(float *frame) { + // Clear accumulator. + float sum = 0.0; + + // Multiply input times precomputed windowed sinc function. + const float *coefficients = &mCoefficients[mCoefficientCursor]; + float *xFrame = &mX[mCursor * MONO]; + const int numLoops = mNumTaps >> 2; // n/4 + for (int i = 0; i < numLoops; i++) { + // Manual loop unrolling, might get converted to SIMD. + sum += *xFrame++ * *coefficients++; + sum += *xFrame++ * *coefficients++; + sum += *xFrame++ * *coefficients++; + sum += *xFrame++ * *coefficients++; + } + + mCoefficientCursor = (mCoefficientCursor + mNumTaps) % mCoefficients.size(); + + // Copy accumulator to output. + frame[0] = sum; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerMono_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerMono_android.h new file mode 100644 index 0000000..d3195bd --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerMono_android.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_POLYPHASE_RESAMPLER_MONO_H +#define RESAMPLER_POLYPHASE_RESAMPLER_MONO_H + +#include +#include + +#include "oboe_flowgraph_resampler_PolyphaseResampler_android.h" +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +class PolyphaseResamplerMono : public PolyphaseResampler { +public: + explicit PolyphaseResamplerMono(const MultiChannelResampler::Builder &builder); + + virtual ~PolyphaseResamplerMono() = default; + + void writeFrame(const float *frame) override; + + void readFrame(float *frame) override; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_POLYPHASE_RESAMPLER_MONO_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.cpp new file mode 100644 index 0000000..e02aa66 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +#define STEREO 2 + +PolyphaseResamplerStereo::PolyphaseResamplerStereo(const MultiChannelResampler::Builder &builder) + : PolyphaseResampler(builder) { + assert(builder.getChannelCount() == STEREO); +} + +void PolyphaseResamplerStereo::writeFrame(const float *frame) { + // Move cursor before write so that cursor points to last written frame in read. + if (--mCursor < 0) { + mCursor = getNumTaps() - 1; + } + float *dest = &mX[mCursor * STEREO]; + const int offset = mNumTaps * STEREO; + // Write each channel twice so we avoid having to wrap when running the FIR. + const float left = frame[0]; + const float right = frame[1]; + // Put ordered writes together. + dest[0] = left; + dest[1] = right; + dest[offset] = left; + dest[1 + offset] = right; +} + +void PolyphaseResamplerStereo::readFrame(float *frame) { + // Clear accumulators. + float left = 0.0; + float right = 0.0; + + // Multiply input times precomputed windowed sinc function. + const float *coefficients = &mCoefficients[mCoefficientCursor]; + float *xFrame = &mX[mCursor * STEREO]; + const int numLoops = mNumTaps >> 2; // n/4 + for (int i = 0; i < numLoops; i++) { + // Manual loop unrolling, might get converted to SIMD. + float coefficient = *coefficients++; + left += *xFrame++ * coefficient; + right += *xFrame++ * coefficient; + + coefficient = *coefficients++; // next tap + left += *xFrame++ * coefficient; + right += *xFrame++ * coefficient; + + coefficient = *coefficients++; // next tap + left += *xFrame++ * coefficient; + right += *xFrame++ * coefficient; + + coefficient = *coefficients++; // next tap + left += *xFrame++ * coefficient; + right += *xFrame++ * coefficient; + } + + mCoefficientCursor = (mCoefficientCursor + mNumTaps) % mCoefficients.size(); + + // Copy accumulators to output. + frame[0] = left; + frame[1] = right; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.h new file mode 100644 index 0000000..a8d0101 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResamplerStereo_android.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_POLYPHASE_RESAMPLER_STEREO_H +#define RESAMPLER_POLYPHASE_RESAMPLER_STEREO_H + +#include +#include + +#include "oboe_flowgraph_resampler_PolyphaseResampler_android.h" +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +class PolyphaseResamplerStereo : public PolyphaseResampler { +public: + explicit PolyphaseResamplerStereo(const MultiChannelResampler::Builder &builder); + + virtual ~PolyphaseResamplerStereo() = default; + + void writeFrame(const float *frame) override; + + void readFrame(float *frame) override; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_POLYPHASE_RESAMPLER_STEREO_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResampler_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResampler_android.cpp new file mode 100644 index 0000000..70a70d2 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResampler_android.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_resampler_IntegerRatio_android.h" +#include "oboe_flowgraph_resampler_PolyphaseResampler_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +PolyphaseResampler::PolyphaseResampler(const MultiChannelResampler::Builder &builder) + : MultiChannelResampler(builder) + { + assert((getNumTaps() % 4) == 0); // Required for loop unrolling. + + int32_t inputRate = builder.getInputRate(); + int32_t outputRate = builder.getOutputRate(); + + int32_t numRows = mDenominator; + double phaseIncrement = (double) inputRate / (double) outputRate; + generateCoefficients(inputRate, outputRate, + numRows, phaseIncrement, + builder.getNormalizedCutoff()); +} + +void PolyphaseResampler::readFrame(float *frame) { + // Clear accumulator for mixing. + std::fill(mSingleFrame.begin(), mSingleFrame.end(), 0.0); + + // Multiply input times windowed sinc function. + float *coefficients = &mCoefficients[mCoefficientCursor]; + float *xFrame = &mX[static_cast(mCursor) * static_cast(getChannelCount())]; + for (int i = 0; i < mNumTaps; i++) { + float coefficient = *coefficients++; + for (int channel = 0; channel < getChannelCount(); channel++) { + mSingleFrame[channel] += *xFrame++ * coefficient; + } + } + + // Advance and wrap through coefficients. + mCoefficientCursor = (mCoefficientCursor + mNumTaps) % mCoefficients.size(); + + // Copy accumulator to output. + for (int channel = 0; channel < getChannelCount(); channel++) { + frame[channel] = mSingleFrame[channel]; + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResampler_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResampler_android.h new file mode 100644 index 0000000..74cdd7d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_PolyphaseResampler_android.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_POLYPHASE_RESAMPLER_H +#define RESAMPLER_POLYPHASE_RESAMPLER_H + +#include +#include +#include +#include + +#include "oboe_flowgraph_resampler_MultiChannelResampler_android.h" +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { +/** + * Resampler that is optimized for a reduced ratio of sample rates. + * All of the coefficients for each possible phase value are pre-calculated. + */ +class PolyphaseResampler : public MultiChannelResampler { +public: + /** + * + * @param builder containing lots of parameters + */ + explicit PolyphaseResampler(const MultiChannelResampler::Builder &builder); + + virtual ~PolyphaseResampler() = default; + + void readFrame(float *frame) override; + +protected: + + int32_t mCoefficientCursor = 0; + +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_POLYPHASE_RESAMPLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_ResamplerDefinitions_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_ResamplerDefinitions_android.h new file mode 100644 index 0000000..c6791ec --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_ResamplerDefinitions_android.h @@ -0,0 +1,27 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Set flag RESAMPLER_OUTER_NAMESPACE based on whether compiler flag +// __ANDROID_NDK__ is defined. __ANDROID_NDK__ should be defined in oboe +// but not in android. + +#ifndef RESAMPLER_OUTER_NAMESPACE +#ifdef __ANDROID_NDK__ +#define RESAMPLER_OUTER_NAMESPACE oboe +#else +#define RESAMPLER_OUTER_NAMESPACE aaudio +#endif // __ANDROID_NDK__ +#endif // RESAMPLER_OUTER_NAMESPACE diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResamplerStereo_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResamplerStereo_android.cpp new file mode 100644 index 0000000..cd31299 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResamplerStereo_android.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "oboe_flowgraph_resampler_SincResamplerStereo_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +#define STEREO 2 + +SincResamplerStereo::SincResamplerStereo(const MultiChannelResampler::Builder &builder) + : SincResampler(builder) { + assert(builder.getChannelCount() == STEREO); +} + +void SincResamplerStereo::writeFrame(const float *frame) { + // Move cursor before write so that cursor points to last written frame in read. + if (--mCursor < 0) { + mCursor = getNumTaps() - 1; + } + float *dest = &mX[mCursor * STEREO]; + const int offset = mNumTaps * STEREO; + // Write each channel twice so we avoid having to wrap when running the FIR. + const float left = frame[0]; + const float right = frame[1]; + // Put ordered writes together. + dest[0] = left; + dest[1] = right; + dest[offset] = left; + dest[1 + offset] = right; +} + +// Multiply input times windowed sinc function. +void SincResamplerStereo::readFrame(float *frame) { + // Clear accumulator for mixing. + std::fill(mSingleFrame.begin(), mSingleFrame.end(), 0.0); + std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0); + + // Determine indices into coefficients table. + double tablePhase = getIntegerPhase() * mPhaseScaler; + int index1 = static_cast(floor(tablePhase)); + float *coefficients1 = &mCoefficients[static_cast(index1) + * static_cast(getNumTaps())]; + int index2 = (index1 + 1); + assert (index2 < mNumRows); + float *coefficients2 = &mCoefficients[static_cast(index2) + * static_cast(getNumTaps())]; + float *xFrame = &mX[static_cast(mCursor) * static_cast(getChannelCount())]; + for (int i = 0; i < mNumTaps; i++) { + float coefficient1 = *coefficients1++; + float coefficient2 = *coefficients2++; + for (int channel = 0; channel < getChannelCount(); channel++) { + float sample = *xFrame++; + mSingleFrame[channel] += sample * coefficient1; + mSingleFrame2[channel] += sample * coefficient2; + } + } + + // Interpolate and copy to output. + float fraction = tablePhase - index1; + for (int channel = 0; channel < getChannelCount(); channel++) { + float low = mSingleFrame[channel]; + float high = mSingleFrame2[channel]; + frame[channel] = low + (fraction * (high - low)); + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResamplerStereo_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResamplerStereo_android.h new file mode 100644 index 0000000..16d3d37 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResamplerStereo_android.h @@ -0,0 +1,42 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_SINC_RESAMPLER_STEREO_H +#define RESAMPLER_SINC_RESAMPLER_STEREO_H + +#include +#include + +#include "oboe_flowgraph_resampler_SincResampler_android.h" +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +class SincResamplerStereo : public SincResampler { +public: + explicit SincResamplerStereo(const MultiChannelResampler::Builder &builder); + + virtual ~SincResamplerStereo() = default; + + void writeFrame(const float *frame) override; + + void readFrame(float *frame) override; + +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_SINC_RESAMPLER_STEREO_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResampler_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResampler_android.cpp new file mode 100644 index 0000000..7c86f3d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResampler_android.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "oboe_flowgraph_resampler_SincResampler_android.h" + +using namespace RESAMPLER_OUTER_NAMESPACE::resampler; + +SincResampler::SincResampler(const MultiChannelResampler::Builder &builder) + : MultiChannelResampler(builder) + , mSingleFrame2(builder.getChannelCount()) { + assert((getNumTaps() % 4) == 0); // Required for loop unrolling. + mNumRows = kMaxCoefficients / getNumTaps(); // includes guard row + int32_t numRowsNoGuard = mNumRows - 1; + mPhaseScaler = (double) numRowsNoGuard / mDenominator; + double phaseIncrement = 1.0 / numRowsNoGuard; + generateCoefficients(builder.getInputRate(), + builder.getOutputRate(), + mNumRows, + phaseIncrement, + builder.getNormalizedCutoff()); +} + +void SincResampler::readFrame(float *frame) { + // Clear accumulator for mixing. + std::fill(mSingleFrame.begin(), mSingleFrame.end(), 0.0); + std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0); + + // Determine indices into coefficients table. + double tablePhase = getIntegerPhase() * mPhaseScaler; + int indexLow = static_cast(floor(tablePhase)); + int indexHigh = indexLow + 1; // OK because using a guard row. + assert (indexHigh < mNumRows); + float *coefficientsLow = &mCoefficients[static_cast(indexLow) + * static_cast(getNumTaps())]; + float *coefficientsHigh = &mCoefficients[static_cast(indexHigh) + * static_cast(getNumTaps())]; + + float *xFrame = &mX[static_cast(mCursor) * static_cast(getChannelCount())]; + for (int tap = 0; tap < mNumTaps; tap++) { + float coefficientLow = *coefficientsLow++; + float coefficientHigh = *coefficientsHigh++; + for (int channel = 0; channel < getChannelCount(); channel++) { + float sample = *xFrame++; + mSingleFrame[channel] += sample * coefficientLow; + mSingleFrame2[channel] += sample * coefficientHigh; + } + } + + // Interpolate and copy to output. + float fraction = tablePhase - indexLow; + for (int channel = 0; channel < getChannelCount(); channel++) { + float low = mSingleFrame[channel]; + float high = mSingleFrame2[channel]; + frame[channel] = low + (fraction * (high - low)); + } +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResampler_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResampler_android.h new file mode 100644 index 0000000..c8a9a2c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_flowgraph_resampler_SincResampler_android.h @@ -0,0 +1,50 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESAMPLER_SINC_RESAMPLER_H +#define RESAMPLER_SINC_RESAMPLER_H + +#include +#include +#include + +#include "oboe_flowgraph_resampler_MultiChannelResampler_android.h" +#include "oboe_flowgraph_resampler_ResamplerDefinitions_android.h" + +namespace RESAMPLER_OUTER_NAMESPACE::resampler { + +/** + * Resampler that can interpolate between coefficients. + * This can be used to support arbitrary ratios. + */ +class SincResampler : public MultiChannelResampler { +public: + explicit SincResampler(const MultiChannelResampler::Builder &builder); + + virtual ~SincResampler() = default; + + void readFrame(float *frame) override; + +protected: + + std::vector mSingleFrame2; // for interpolation + int32_t mNumRows = 0; + double mPhaseScaler = 1.0; +}; + +} /* namespace RESAMPLER_OUTER_NAMESPACE::resampler */ + +#endif //RESAMPLER_SINC_RESAMPLER_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamBase_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamBase_android.h new file mode 100644 index 0000000..650fbc3 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamBase_android.h @@ -0,0 +1,274 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STREAM_BASE_H_ +#define OBOE_STREAM_BASE_H_ + +#include +#include +#include "oboe_oboe_AudioStreamCallback_android.h" +#include "oboe_oboe_Definitions_android.h" + +namespace oboe { + +/** + * Base class containing parameters for audio streams and builders. + **/ +class AudioStreamBase { + +public: + + AudioStreamBase() {} + + virtual ~AudioStreamBase() = default; + + // This class only contains primitives so we can use default constructor and copy methods. + + /** + * Default copy constructor + */ + AudioStreamBase(const AudioStreamBase&) = default; + + /** + * Default assignment operator + */ + AudioStreamBase& operator=(const AudioStreamBase&) = default; + + /** + * @return number of channels, for example 2 for stereo, or kUnspecified + */ + int32_t getChannelCount() const { return mChannelCount; } + + /** + * @return Direction::Input or Direction::Output + */ + Direction getDirection() const { return mDirection; } + + /** + * @return sample rate for the stream or kUnspecified + */ + int32_t getSampleRate() const { return mSampleRate; } + + /** + * @deprecated use `getFramesPerDataCallback` instead. + */ + int32_t getFramesPerCallback() const { return getFramesPerDataCallback(); } + + /** + * @return the number of frames in each data callback or kUnspecified. + */ + int32_t getFramesPerDataCallback() const { return mFramesPerCallback; } + + /** + * @return the audio sample format (e.g. Float or I16) + */ + AudioFormat getFormat() const { return mFormat; } + + /** + * Query the maximum number of frames that can be filled without blocking. + * If the stream has been closed the last known value will be returned. + * + * @return buffer size + */ + virtual int32_t getBufferSizeInFrames() { return mBufferSizeInFrames; } + + /** + * @return capacityInFrames or kUnspecified + */ + virtual int32_t getBufferCapacityInFrames() const { return mBufferCapacityInFrames; } + + /** + * @return the sharing mode of the stream. + */ + SharingMode getSharingMode() const { return mSharingMode; } + + /** + * @return the performance mode of the stream. + */ + PerformanceMode getPerformanceMode() const { return mPerformanceMode; } + + /** + * @return the device ID of the stream. + */ + int32_t getDeviceId() const { return mDeviceId; } + + /** + * For internal use only. + * @return the data callback object for this stream, if set. + */ + AudioStreamDataCallback *getDataCallback() const { + return mDataCallback; + } + + /** + * For internal use only. + * @return the error callback object for this stream, if set. + */ + AudioStreamErrorCallback *getErrorCallback() const { + return mErrorCallback; + } + + /** + * @return true if a data callback was set for this stream + */ + bool isDataCallbackSpecified() const { + return mDataCallback != nullptr; + } + + /** + * Note that if the app does not set an error callback then a + * default one may be provided. + * @return true if an error callback was set for this stream + */ + bool isErrorCallbackSpecified() const { + return mErrorCallback != nullptr; + } + + /** + * @return the usage for this stream. + */ + Usage getUsage() const { return mUsage; } + + /** + * @return the stream's content type. + */ + ContentType getContentType() const { return mContentType; } + + /** + * @return the stream's input preset. + */ + InputPreset getInputPreset() const { return mInputPreset; } + + /** + * @return the stream's session ID allocation strategy (None or Allocate). + */ + SessionId getSessionId() const { return mSessionId; } + + /** + * @return true if Oboe can convert channel counts to achieve optimal results. + */ + bool isChannelConversionAllowed() const { + return mChannelConversionAllowed; + } + + /** + * @return true if Oboe can convert data formats to achieve optimal results. + */ + bool isFormatConversionAllowed() const { + return mFormatConversionAllowed; + } + + /** + * @return whether and how Oboe can convert sample rates to achieve optimal results. + */ + SampleRateConversionQuality getSampleRateConversionQuality() const { + return mSampleRateConversionQuality; + } + + /** + * @return the stream's channel mask. + */ + ChannelMask getChannelMask() const { + return mChannelMask; + } + +protected: + /** The callback which will be fired when new data is ready to be read/written. **/ + AudioStreamDataCallback *mDataCallback = nullptr; + std::shared_ptr mSharedDataCallback; + + /** The callback which will be fired when an error or a disconnect occurs. **/ + AudioStreamErrorCallback *mErrorCallback = nullptr; + std::shared_ptr mSharedErrorCallback; + + /** Number of audio frames which will be requested in each callback */ + int32_t mFramesPerCallback = kUnspecified; + /** Stream channel count */ + int32_t mChannelCount = kUnspecified; + /** Stream sample rate */ + int32_t mSampleRate = kUnspecified; + /** Stream audio device ID */ + int32_t mDeviceId = kUnspecified; + /** Stream buffer capacity specified as a number of audio frames */ + int32_t mBufferCapacityInFrames = kUnspecified; + /** Stream buffer size specified as a number of audio frames */ + int32_t mBufferSizeInFrames = kUnspecified; + /** Stream channel mask. Only active on Android 32+ */ + ChannelMask mChannelMask = ChannelMask::Unspecified; + + /** Stream sharing mode */ + SharingMode mSharingMode = SharingMode::Shared; + /** Format of audio frames */ + AudioFormat mFormat = AudioFormat::Unspecified; + /** Stream direction */ + Direction mDirection = Direction::Output; + /** Stream performance mode */ + PerformanceMode mPerformanceMode = PerformanceMode::None; + + /** Stream usage. Only active on Android 28+ */ + Usage mUsage = Usage::Media; + /** Stream content type. Only active on Android 28+ */ + ContentType mContentType = ContentType::Music; + /** Stream input preset. Only active on Android 28+ + * TODO InputPreset::Unspecified should be considered as a possible default alternative. + */ + InputPreset mInputPreset = InputPreset::VoiceRecognition; + /** Stream session ID allocation strategy. Only active on Android 28+ */ + SessionId mSessionId = SessionId::None; + + /** Control the name of the package creating the stream. Only active on Android 31+ */ + std::string mPackageName; + /** Control the attribution tag of the context creating the stream. Only active on Android 31+ */ + std::string mAttributionTag; + + // Control whether Oboe can convert channel counts to achieve optimal results. + bool mChannelConversionAllowed = false; + // Control whether Oboe can convert data formats to achieve optimal results. + bool mFormatConversionAllowed = false; + // Control whether and how Oboe can convert sample rates to achieve optimal results. + SampleRateConversionQuality mSampleRateConversionQuality = SampleRateConversionQuality::None; + + /** Validate stream parameters that might not be checked in lower layers */ + virtual Result isValidConfig() { + switch (mFormat) { + case AudioFormat::Unspecified: + case AudioFormat::I16: + case AudioFormat::Float: + case AudioFormat::I24: + case AudioFormat::I32: + break; + + default: + return Result::ErrorInvalidFormat; + } + + switch (mSampleRateConversionQuality) { + case SampleRateConversionQuality::None: + case SampleRateConversionQuality::Fastest: + case SampleRateConversionQuality::Low: + case SampleRateConversionQuality::Medium: + case SampleRateConversionQuality::High: + case SampleRateConversionQuality::Best: + return Result::OK; + default: + return Result::ErrorIllegalArgument; + } + } +}; + +} // namespace oboe + +#endif /* OBOE_STREAM_BASE_H_ */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamBuilder_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamBuilder_android.h new file mode 100644 index 0000000..773686b --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamBuilder_android.h @@ -0,0 +1,602 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STREAM_BUILDER_H_ +#define OBOE_STREAM_BUILDER_H_ + +#include "oboe_oboe_Definitions_android.h" +#include "oboe_oboe_AudioStreamBase_android.h" +#include "oboe_oboe_Utilities_android.h" +#include "oboe_oboe_ResultWithValue_android.h" + +namespace oboe { + + // This depends on AudioStream, so we use forward declaration, it will close and delete the stream + struct StreamDeleterFunctor; + using ManagedStream = std::unique_ptr; + +/** + * Factory class for an audio Stream. + */ +class AudioStreamBuilder : public AudioStreamBase { +public: + + AudioStreamBuilder() : AudioStreamBase() {} + + AudioStreamBuilder(const AudioStreamBase &audioStreamBase): AudioStreamBase(audioStreamBase) {} + + /** + * Request a specific number of channels. + * + * Default is kUnspecified. If the value is unspecified then + * the application should query for the actual value after the stream is opened. + * + * As the channel count here may be different from the corresponding channel count of + * provided channel mask used in setChannelMask(). The last called will be respected + * if this function and setChannelMask() are called. + */ + AudioStreamBuilder *setChannelCount(int channelCount) { + mChannelCount = channelCount; + mChannelMask = ChannelMask::Unspecified; + return this; + } + + /** + * Request a specific channel mask. + * + * Default is kUnspecified. If the value is unspecified then the application + * should query for the actual value after the stream is opened. + * + * As the corresponding channel count of provided channel mask here may be different + * from the channel count used in setChannelCount(). The last called will be respected + * if this function and setChannelCount() are called. + * + * As the setChannelMask API is available on Android 32+, this call will only take effects + * on Android 32+. + */ + AudioStreamBuilder *setChannelMask(ChannelMask channelMask) { + mChannelMask = channelMask; + mChannelCount = getChannelCountFromChannelMask(channelMask); + return this; + } + + /** + * Request the direction for a stream. The default is Direction::Output. + * + * @param direction Direction::Output or Direction::Input + */ + AudioStreamBuilder *setDirection(Direction direction) { + mDirection = direction; + return this; + } + + /** + * Request a specific sample rate in Hz. + * + * Default is kUnspecified. If the value is unspecified then + * the application should query for the actual value after the stream is opened. + * + * Technically, this should be called the "frame rate" or "frames per second", + * because it refers to the number of complete frames transferred per second. + * But it is traditionally called "sample rate". Se we use that term. + * + */ + AudioStreamBuilder *setSampleRate(int32_t sampleRate) { + mSampleRate = sampleRate; + return this; + } + + /** + * @deprecated use `setFramesPerDataCallback` instead. + */ + AudioStreamBuilder *setFramesPerCallback(int framesPerCallback) { + return setFramesPerDataCallback(framesPerCallback); + } + + /** + * Request a specific number of frames for the data callback. + * + * Default is kUnspecified. If the value is unspecified then + * the actual number may vary from callback to callback. + * + * If an application can handle a varying number of frames then we recommend + * leaving this unspecified. This allow the underlying API to optimize + * the callbacks. But if your application is, for example, doing FFTs or other block + * oriented operations, then call this function to get the sizes you need. + * + * Calling setFramesPerDataCallback() does not guarantee anything about timing. + * This just collects the data into a the number of frames that your app requires. + * We encourage leaving this unspecified in most cases. + * + * If this number is larger than the burst size, some bursts will not receive a callback. + * If this number is smaller than the burst size, there may be multiple callbacks in a single + * burst. + * + * @param framesPerCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setFramesPerDataCallback(int framesPerCallback) { + mFramesPerCallback = framesPerCallback; + return this; + } + + /** + * Request a sample data format, for example Format::Float. + * + * Default is Format::Unspecified. If the value is unspecified then + * the application should query for the actual value after the stream is opened. + */ + AudioStreamBuilder *setFormat(AudioFormat format) { + mFormat = format; + return this; + } + + /** + * Set the requested buffer capacity in frames. + * BufferCapacityInFrames is the maximum possible BufferSizeInFrames. + * + * The final stream capacity may differ. For AAudio it should be at least this big. + * For OpenSL ES, it could be smaller. + * + * Default is kUnspecified. + * + * @param bufferCapacityInFrames the desired buffer capacity in frames or kUnspecified + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setBufferCapacityInFrames(int32_t bufferCapacityInFrames) { + mBufferCapacityInFrames = bufferCapacityInFrames; + return this; + } + + /** + * Get the audio API which will be requested when opening the stream. No guarantees that this is + * the API which will actually be used. Query the stream itself to find out the API which is + * being used. + * + * If you do not specify the API, then AAudio will be used if isAAudioRecommended() + * returns true. Otherwise OpenSL ES will be used. + * + * @return the requested audio API + */ + AudioApi getAudioApi() const { return mAudioApi; } + + /** + * If you leave this unspecified then Oboe will choose the best API + * for the device and SDK version at runtime. + * + * This should almost always be left unspecified, except for debugging purposes. + * Specifying AAudio will force Oboe to use AAudio on 8.0, which is extremely risky. + * Specifying OpenSLES should mainly be used to test legacy performance/functionality. + * + * If the caller requests AAudio and it is supported then AAudio will be used. + * + * @param audioApi Must be AudioApi::Unspecified, AudioApi::OpenSLES or AudioApi::AAudio. + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setAudioApi(AudioApi audioApi) { + mAudioApi = audioApi; + return this; + } + + /** + * Is the AAudio API supported on this device? + * + * AAudio was introduced in the Oreo 8.0 release. + * + * @return true if supported + */ + static bool isAAudioSupported(); + + /** + * Is the AAudio API recommended this device? + * + * AAudio may be supported but not recommended because of version specific issues. + * AAudio is not recommended for Android 8.0 or earlier versions. + * + * @return true if recommended + */ + static bool isAAudioRecommended(); + + /** + * Request a mode for sharing the device. + * The requested sharing mode may not be available. + * So the application should query for the actual mode after the stream is opened. + * + * @param sharingMode SharingMode::Shared or SharingMode::Exclusive + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setSharingMode(SharingMode sharingMode) { + mSharingMode = sharingMode; + return this; + } + + /** + * Request a performance level for the stream. + * This will determine the latency, the power consumption, and the level of + * protection from glitches. + * + * @param performanceMode for example, PerformanceMode::LowLatency + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setPerformanceMode(PerformanceMode performanceMode) { + mPerformanceMode = performanceMode; + return this; + } + + + /** + * Set the intended use case for an output stream. + * + * The system will use this information to optimize the behavior of the stream. + * This could, for example, affect how volume and focus is handled for the stream. + * The usage is ignored for input streams. + * + * The default, if you do not call this function, is Usage::Media. + * + * Added in API level 28. + * + * @param usage the desired usage, eg. Usage::Game + */ + AudioStreamBuilder *setUsage(Usage usage) { + mUsage = usage; + return this; + } + + /** + * Set the type of audio data that an output stream will carry. + * + * The system will use this information to optimize the behavior of the stream. + * This could, for example, affect whether a stream is paused when a notification occurs. + * The contentType is ignored for input streams. + * + * The default, if you do not call this function, is ContentType::Music. + * + * Added in API level 28. + * + * @param contentType the type of audio data, eg. ContentType::Speech + */ + AudioStreamBuilder *setContentType(ContentType contentType) { + mContentType = contentType; + return this; + } + + /** + * Set the input (capture) preset for the stream. + * + * The system will use this information to optimize the behavior of the stream. + * This could, for example, affect which microphones are used and how the + * recorded data is processed. + * + * The default, if you do not call this function, is InputPreset::VoiceRecognition. + * That is because VoiceRecognition is the preset with the lowest latency + * on many platforms. + * + * Added in API level 28. + * + * @param inputPreset the desired configuration for recording + */ + AudioStreamBuilder *setInputPreset(InputPreset inputPreset) { + mInputPreset = inputPreset; + return this; + } + + /** Set the requested session ID. + * + * The session ID can be used to associate a stream with effects processors. + * The effects are controlled using the Android AudioEffect Java API. + * + * The default, if you do not call this function, is SessionId::None. + * + * If set to SessionId::Allocate then a session ID will be allocated + * when the stream is opened. + * + * The allocated session ID can be obtained by calling AudioStream::getSessionId() + * and then used with this function when opening another stream. + * This allows effects to be shared between streams. + * + * Session IDs from Oboe can be used the Android Java APIs and vice versa. + * So a session ID from an Oboe stream can be passed to Java + * and effects applied using the Java AudioEffect API. + * + * Allocated session IDs will always be positive and nonzero. + * + * Added in API level 28. + * + * @param sessionId an allocated sessionID or SessionId::Allocate + */ + AudioStreamBuilder *setSessionId(SessionId sessionId) { + mSessionId = sessionId; + return this; + } + + /** + * Request a stream to a specific audio input/output device given an audio device ID. + * + * In most cases, the primary device will be the appropriate device to use, and the + * deviceId can be left kUnspecified. + * + * The ID could be obtained from the Java AudioManager. + * AudioManager.getDevices() returns an array of AudioDeviceInfo, + * which contains a getId() method. That ID can be passed to this function. + * + * It is possible that you may not get the device that you requested. + * So if it is important to you, you should call + * stream->getDeviceId() after the stream is opened to + * verify the actual ID. + * + * Note that when using OpenSL ES, this will be ignored and the created + * stream will have deviceId kUnspecified. + * + * @param deviceId device identifier or kUnspecified + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setDeviceId(int32_t deviceId) { + mDeviceId = deviceId; + return this; + } + + /** + * Specifies an object to handle data related callbacks from the underlying API. + * + * Important: See AudioStreamCallback for restrictions on what may be called + * from the callback methods. + * + * We pass a shared_ptr so that the sharedDataCallback object cannot be deleted + * before the stream is deleted. + * + * @param dataCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setDataCallback(std::shared_ptr sharedDataCallback) { + // Use this raw pointer in the rest of the code to retain backwards compatibility. + mDataCallback = sharedDataCallback.get(); + // Hold a shared_ptr to protect the raw pointer for the lifetime of the stream. + mSharedDataCallback = sharedDataCallback; + return this; + } + + /** + * Pass a raw pointer to a data callback. This is not recommended because the dataCallback + * object might get deleted by the app while it is being used. + * + * @deprecated Call setDataCallback(std::shared_ptr) instead. + * @param dataCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setDataCallback(AudioStreamDataCallback *dataCallback) { + mDataCallback = dataCallback; + mSharedDataCallback = nullptr; + return this; + } + + /** + * Specifies an object to handle error related callbacks from the underlying API. + * This can occur when a stream is disconnected because a headset is plugged in or unplugged. + * It can also occur if the audio service fails or if an exclusive stream is stolen by + * another stream. + * + * Important: See AudioStreamCallback for restrictions on what may be called + * from the callback methods. + * + * When an error callback occurs, the associated stream must be stopped and closed + * in a separate thread. + * + * We pass a shared_ptr so that the errorCallback object cannot be deleted before the stream is deleted. + * If the stream was created using a shared_ptr then the stream cannot be deleted before the + * error callback has finished running. + * + * @param sharedErrorCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setErrorCallback(std::shared_ptr sharedErrorCallback) { + // Use this raw pointer in the rest of the code to retain backwards compatibility. + mErrorCallback = sharedErrorCallback.get(); + // Hold a shared_ptr to protect the raw pointer for the lifetime of the stream. + mSharedErrorCallback = sharedErrorCallback; + return this; + } + + /** + * Pass a raw pointer to an error callback. This is not recommended because the errorCallback + * object might get deleted by the app while it is being used. + * + * @deprecated Call setErrorCallback(std::shared_ptr) instead. + * @param errorCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setErrorCallback(AudioStreamErrorCallback *errorCallback) { + mErrorCallback = errorCallback; + mSharedErrorCallback = nullptr; + return this; + } + + /** + * Specifies an object to handle data or error related callbacks from the underlying API. + * + * This is the equivalent of calling both setDataCallback() and setErrorCallback(). + * + * Important: See AudioStreamCallback for restrictions on what may be called + * from the callback methods. + * + * When an error callback occurs, the associated stream will be stopped and closed in a separate thread. + * + * A note on why the streamCallback parameter is a raw pointer rather than a smart pointer: + * + * The caller should retain ownership of the object streamCallback points to. At first glance weak_ptr may seem like + * a good candidate for streamCallback as this implies temporary ownership. However, a weak_ptr can only be created + * from a shared_ptr. A shared_ptr incurs some performance overhead. The callback object is likely to be accessed + * every few milliseconds when the stream requires new data so this overhead is something we want to avoid. + * + * This leaves a raw pointer as the logical type choice. The only caveat being that the caller must not destroy + * the callback before the stream has been closed. + * + * @param streamCallback + * @return pointer to the builder so calls can be chained + */ + AudioStreamBuilder *setCallback(AudioStreamCallback *streamCallback) { + // Use the same callback object for both, dual inheritance. + mDataCallback = streamCallback; + mErrorCallback = streamCallback; + return this; + } + + /** + * If true then Oboe might convert channel counts to achieve optimal results. + * On some versions of Android for example, stereo streams could not use a FAST track. + * So a mono stream might be used instead and duplicated to two channels. + * On some devices, mono streams might be broken, so a stereo stream might be opened + * and converted to mono. + * + * Default is false. + */ + AudioStreamBuilder *setChannelConversionAllowed(bool allowed) { + mChannelConversionAllowed = allowed; + return this; + } + + /** + * If true then Oboe might convert data formats to achieve optimal results. + * On some versions of Android, for example, a float stream could not get a + * low latency data path. So an I16 stream might be opened and converted to float. + * + * Default is false. + */ + AudioStreamBuilder *setFormatConversionAllowed(bool allowed) { + mFormatConversionAllowed = allowed; + return this; + } + + /** + * Specify the quality of the sample rate converter in Oboe. + * + * If set to None then Oboe will not do sample rate conversion. But the underlying APIs might + * still do sample rate conversion if you specify a sample rate. + * That can prevent you from getting a low latency stream. + * + * If you do the conversion in Oboe then you might still get a low latency stream. + * + * Default is SampleRateConversionQuality::None + */ + AudioStreamBuilder *setSampleRateConversionQuality(SampleRateConversionQuality quality) { + mSampleRateConversionQuality = quality; + return this; + } + + /** + * Declare the name of the package creating the stream. + * + * This is usually {@code Context#getPackageName()}. + * + * The default, if you do not call this function, is a random package in the calling uid. + * The vast majority of apps have only one package per calling UID. + * If an invalid package name is set, input streams may not be given permission to + * record when started. + * + * The package name is usually the applicationId in your app's build.gradle file. + * + * Available since API level 31. + * + * @param packageName packageName of the calling app. + */ + AudioStreamBuilder *setPackageName(std::string packageName) { + mPackageName = packageName; + return this; + } + + /** + * Declare the attribution tag of the context creating the stream. + * + * This is usually {@code Context#getAttributionTag()}. + * + * The default, if you do not call this function, is null. + * + * Available since API level 31. + * + * @param attributionTag attributionTag of the calling context. + */ + AudioStreamBuilder *setAttributionTag(std::string attributionTag) { + mAttributionTag = attributionTag; + return this; + } + + /** + * @return true if AAudio will be used based on the current settings. + */ + bool willUseAAudio() const { + return (mAudioApi == AudioApi::AAudio && isAAudioSupported()) + || (mAudioApi == AudioApi::Unspecified && isAAudioRecommended()); + } + + /** + * Create and open a stream object based on the current settings. + * + * The caller owns the pointer to the AudioStream object + * and must delete it when finished. + * + * @deprecated Use openStream(std::shared_ptr &stream) instead. + * @param stream pointer to a variable to receive the stream address + * @return OBOE_OK if successful or a negative error code + */ + Result openStream(AudioStream **stream); + + /** + * Create and open a stream object based on the current settings. + * + * The caller shares the pointer to the AudioStream object. + * The shared_ptr is used internally by Oboe to prevent the stream from being + * deleted while it is being used by callbacks. + * + * @param stream reference to a shared_ptr to receive the stream address + * @return OBOE_OK if successful or a negative error code + */ + Result openStream(std::shared_ptr &stream); + + /** + * Create and open a ManagedStream object based on the current builder state. + * + * The caller must create a unique ptr, and pass by reference so it can be + * modified to point to an opened stream. The caller owns the unique ptr, + * and it will be automatically closed and deleted when going out of scope. + * + * @deprecated Use openStream(std::shared_ptr &stream) instead. + * @param stream Reference to the ManagedStream (uniqueptr) used to keep track of stream + * @return OBOE_OK if successful or a negative error code. + */ + Result openManagedStream(ManagedStream &stream); + +private: + + /** + * @param other + * @return true if channels, format and sample rate match + */ + bool isCompatible(AudioStreamBase &other); + + /** + * Create an AudioStream object. The AudioStream must be opened before use. + * + * The caller owns the pointer. + * + * @return pointer to an AudioStream object or nullptr. + */ + oboe::AudioStream *build(); + + AudioApi mAudioApi = AudioApi::Unspecified; +}; + +} // namespace oboe + +#endif /* OBOE_STREAM_BUILDER_H_ */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamCallback_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamCallback_android.h new file mode 100644 index 0000000..35e544a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStreamCallback_android.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STREAM_CALLBACK_H +#define OBOE_STREAM_CALLBACK_H + +#include "oboe_oboe_Definitions_android.h" + +namespace oboe { + +class AudioStream; + +/** + * AudioStreamDataCallback defines a callback interface for + * moving data to/from an audio stream using `onAudioReady` + * 2) being alerted when a stream has an error using `onError*` methods + * + * It is used with AudioStreamBuilder::setDataCallback(). + */ + +class AudioStreamDataCallback { +public: + virtual ~AudioStreamDataCallback() = default; + + /** + * A buffer is ready for processing. + * + * For an output stream, this function should render and write numFrames of data + * in the stream's current data format to the audioData buffer. + * + * For an input stream, this function should read and process numFrames of data + * from the audioData buffer. + * + * The audio data is passed through the buffer. So do NOT call read() or + * write() on the stream that is making the callback. + * + * Note that numFrames can vary unless AudioStreamBuilder::setFramesPerCallback() + * is called. + * + * Also note that this callback function should be considered a "real-time" function. + * It must not do anything that could cause an unbounded delay because that can cause the + * audio to glitch or pop. + * + * These are things the function should NOT do: + *
    + *
  • allocate memory using, for example, malloc() or new
  • + *
  • any file operations such as opening, closing, reading or writing
  • + *
  • any network operations such as streaming
  • + *
  • use any mutexes or other synchronization primitives
  • + *
  • sleep
  • + *
  • oboeStream->stop(), pause(), flush() or close()
  • + *
  • oboeStream->read()
  • + *
  • oboeStream->write()
  • + *
+ * + * The following are OK to call from the data callback: + *
    + *
  • oboeStream->get*()
  • + *
  • oboe::convertToText()
  • + *
  • oboeStream->setBufferSizeInFrames()
  • + *
+ * + * If you need to move data, eg. MIDI commands, in or out of the callback function then + * we recommend the use of non-blocking techniques such as an atomic FIFO. + * + * @param audioStream pointer to the associated stream + * @param audioData buffer containing input data or a place to put output data + * @param numFrames number of frames to be processed + * @return DataCallbackResult::Continue or DataCallbackResult::Stop + */ + virtual DataCallbackResult onAudioReady( + AudioStream *audioStream, + void *audioData, + int32_t numFrames) = 0; +}; + +/** + * AudioStreamErrorCallback defines a callback interface for + * being alerted when a stream has an error or is disconnected + * using `onError*` methods. + * + * Note: This callback is only fired when an AudioStreamCallback is set. + * If you use AudioStream::write() you have to evaluate the return codes of + * AudioStream::write() to notice errors in the stream. + * + * It is used with AudioStreamBuilder::setErrorCallback(). + */ +class AudioStreamErrorCallback { +public: + virtual ~AudioStreamErrorCallback() = default; + + /** + * This will be called before other `onError` methods when an error occurs on a stream, + * such as when the stream is disconnected. + * + * It can be used to override and customize the normal error processing. + * Use of this method is considered an advanced technique. + * It might, for example, be used if an app want to use a high level lock when + * closing and reopening a stream. + * Or it might be used when an app want to signal a management thread that handles + * all of the stream state. + * + * If this method returns false it indicates that the stream has *not been stopped and closed + * by the application. In this case it will be stopped by Oboe in the following way: + * onErrorBeforeClose() will be called, then the stream will be closed and onErrorAfterClose() + * will be closed. + * + * If this method returns true it indicates that the stream *has* been stopped and closed + * by the application and Oboe will not do this. + * In that case, the app MUST stop() and close() the stream. + * + * This method will be called on a thread created by Oboe. + * + * @param audioStream pointer to the associated stream + * @param error + * @return true if the stream has been stopped and closed, false if not + */ + virtual bool onError(AudioStream* /* audioStream */, Result /* error */) { + return false; + } + + /** + * This will be called when an error occurs on a stream, + * such as when the stream is disconnected, + * and if onError() returns false (indicating that the error has not already been handled). + * + * Note that this will be called on a thread created by Oboe. + * + * The underlying stream will already be stopped by Oboe but not yet closed. + * So the stream can be queried. + * + * Do not close or delete the stream in this method because it will be + * closed after this method returns. + * + * @param audioStream pointer to the associated stream + * @param error + */ + virtual void onErrorBeforeClose(AudioStream* /* audioStream */, Result /* error */) {} + + /** + * This will be called when an error occurs on a stream, + * such as when the stream is disconnected, + * and if onError() returns false (indicating that the error has not already been handled). + * + * The underlying AAudio or OpenSL ES stream will already be stopped AND closed by Oboe. + * So the underlying stream cannot be referenced. + * But you can still query most parameters. + * + * This callback could be used to reopen a new stream on another device. + * + * @param audioStream pointer to the associated stream + * @param error + */ + virtual void onErrorAfterClose(AudioStream* /* audioStream */, Result /* error */) {} + +}; + +/** + * AudioStreamCallback defines a callback interface for: + * + * 1) moving data to/from an audio stream using `onAudioReady` + * 2) being alerted when a stream has an error using `onError*` methods + * + * It is used with AudioStreamBuilder::setCallback(). + * + * It combines the interfaces defined by AudioStreamDataCallback and AudioStreamErrorCallback. + * This was the original callback object. We now recommend using the individual interfaces + * and using setDataCallback() and setErrorCallback(). + * + * @deprecated Use `AudioStreamDataCallback` and `AudioStreamErrorCallback` instead + */ +class AudioStreamCallback : public AudioStreamDataCallback, + public AudioStreamErrorCallback { +public: + virtual ~AudioStreamCallback() = default; +}; + +} // namespace oboe + +#endif //OBOE_STREAM_CALLBACK_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStream_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStream_android.h new file mode 100644 index 0000000..9f13180 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_AudioStream_android.h @@ -0,0 +1,623 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STREAM_H_ +#define OBOE_STREAM_H_ + +#include +#include +#include +#include +#include "oboe_oboe_Definitions_android.h" +#include "oboe_oboe_ResultWithValue_android.h" +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_oboe_AudioStreamBase_android.h" + +/** WARNING - UNDER CONSTRUCTION - THIS API WILL CHANGE. */ + +namespace oboe { + +/** + * The default number of nanoseconds to wait for when performing state change operations on the + * stream, such as `start` and `stop`. + * + * @see oboe::AudioStream::start + */ +constexpr int64_t kDefaultTimeoutNanos = (2000 * kNanosPerMillisecond); + +/** + * Base class for Oboe C++ audio stream. + */ +class AudioStream : public AudioStreamBase { + friend class AudioStreamBuilder; // allow access to setWeakThis() and lockWeakThis() +public: + + AudioStream() {} + + /** + * Construct an `AudioStream` using the given `AudioStreamBuilder` + * + * @param builder containing all the stream's attributes + */ + explicit AudioStream(const AudioStreamBuilder &builder); + + virtual ~AudioStream() = default; + + /** + * Open a stream based on the current settings. + * + * Note that we do not recommend re-opening a stream that has been closed. + * TODO Should we prevent re-opening? + * + * @return + */ + virtual Result open() { + return Result::OK; // Called by subclasses. Might do more in the future. + } + + /** + * Close the stream and deallocate any resources from the open() call. + */ + virtual Result close(); + + /** + * Start the stream. This will block until the stream has been started, an error occurs + * or `timeoutNanoseconds` has been reached. + */ + virtual Result start(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); + + /** + * Pause the stream. This will block until the stream has been paused, an error occurs + * or `timeoutNanoseconds` has been reached. + */ + virtual Result pause(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); + + /** + * Flush the stream. This will block until the stream has been flushed, an error occurs + * or `timeoutNanoseconds` has been reached. + */ + virtual Result flush(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); + + /** + * Stop the stream. This will block until the stream has been stopped, an error occurs + * or `timeoutNanoseconds` has been reached. + */ + virtual Result stop(int64_t timeoutNanoseconds = kDefaultTimeoutNanos); + + /* Asynchronous requests. + * Use waitForStateChange() if you need to wait for completion. + */ + + /** + * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `start(0)`. + */ + virtual Result requestStart() = 0; + + /** + * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `pause(0)`. + */ + virtual Result requestPause() = 0; + + /** + * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `flush(0)`. + */ + virtual Result requestFlush() = 0; + + /** + * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling + * `stop(0)`. + */ + virtual Result requestStop() = 0; + + /** + * Query the current state, eg. StreamState::Pausing + * + * @return state or a negative error. + */ + virtual StreamState getState() = 0; + + /** + * Wait until the stream's current state no longer matches the input state. + * The input state is passed to avoid race conditions caused by the state + * changing between calls. + * + * Note that generally applications do not need to call this. It is considered + * an advanced technique and is mostly used for testing. + * + *

+     * int64_t timeoutNanos = 500 * kNanosPerMillisecond; // arbitrary 1/2 second
+     * StreamState currentState = stream->getState();
+     * StreamState nextState = StreamState::Unknown;
+     * while (result == Result::OK && currentState != StreamState::Paused) {
+     *     result = stream->waitForStateChange(
+     *                                   currentState, &nextState, timeoutNanos);
+     *     currentState = nextState;
+     * }
+     * 
+ * + * If the state does not change within the timeout period then it will + * return ErrorTimeout. This is true even if timeoutNanoseconds is zero. + * + * @param inputState The state we want to change away from. + * @param nextState Pointer to a variable that will be set to the new state. + * @param timeoutNanoseconds The maximum time to wait in nanoseconds. + * @return Result::OK or a Result::Error. + */ + virtual Result waitForStateChange(StreamState inputState, + StreamState *nextState, + int64_t timeoutNanoseconds) = 0; + + /** + * This can be used to adjust the latency of the buffer by changing + * the threshold where blocking will occur. + * By combining this with getXRunCount(), the latency can be tuned + * at run-time for each device. + * + * This cannot be set higher than getBufferCapacity(). + * + * @param requestedFrames requested number of frames that can be filled without blocking + * @return the resulting buffer size in frames (obtained using value()) or an error (obtained + * using error()) + */ + virtual ResultWithValue setBufferSizeInFrames(int32_t /* requestedFrames */) { + return Result::ErrorUnimplemented; + } + + /** + * An XRun is an Underrun or an Overrun. + * During playing, an underrun will occur if the stream is not written in time + * and the system runs out of valid data. + * During recording, an overrun will occur if the stream is not read in time + * and there is no place to put the incoming data so it is discarded. + * + * An underrun or overrun can cause an audible "pop" or "glitch". + * + * @return a result which is either Result::OK with the xRun count as the value, or a + * Result::Error* code + */ + virtual ResultWithValue getXRunCount() { + return ResultWithValue(Result::ErrorUnimplemented); + } + + /** + * @return true if XRun counts are supported on the stream + */ + virtual bool isXRunCountSupported() const = 0; + + /** + * Query the number of frames that are read or written by the endpoint at one time. + * + * @return burst size + */ + int32_t getFramesPerBurst() const { + return mFramesPerBurst; + } + + /** + * Get the number of bytes in each audio frame. This is calculated using the channel count + * and the sample format. For example, a 2 channel floating point stream will have + * 2 * 4 = 8 bytes per frame. + * + * @return number of bytes in each audio frame. + */ + int32_t getBytesPerFrame() const { return mChannelCount * getBytesPerSample(); } + + /** + * Get the number of bytes per sample. This is calculated using the sample format. For example, + * a stream using 16-bit integer samples will have 2 bytes per sample. + * + * @return the number of bytes per sample. + */ + int32_t getBytesPerSample() const; + + /** + * The number of audio frames written into the stream. + * This monotonic counter will never get reset. + * + * @return the number of frames written so far + */ + virtual int64_t getFramesWritten(); + + /** + * The number of audio frames read from the stream. + * This monotonic counter will never get reset. + * + * @return the number of frames read so far + */ + virtual int64_t getFramesRead(); + + /** + * Calculate the latency of a stream based on getTimestamp(). + * + * Output latency is the time it takes for a given frame to travel from the + * app to some type of digital-to-analog converter. If the DAC is external, for example + * in a USB interface or a TV connected by HDMI, then there may be additional latency + * that the Android device is unaware of. + * + * Input latency is the time it takes to a given frame to travel from an analog-to-digital + * converter (ADC) to the app. + * + * Note that the latency of an OUTPUT stream will increase abruptly when you write data to it + * and then decrease slowly over time as the data is consumed. + * + * The latency of an INPUT stream will decrease abruptly when you read data from it + * and then increase slowly over time as more data arrives. + * + * The latency of an OUTPUT stream is generally higher than the INPUT latency + * because an app generally tries to keep the OUTPUT buffer full and the INPUT buffer empty. + * + * Note that due to issues in Android before R, we recommend NOT calling + * this method from a data callback. See this tech note for more details. + * https://github.com/google/oboe/blob/main/docs/notes/rlsbuffer.md + * + * @return a ResultWithValue which has a result of Result::OK and a value containing the latency + * in milliseconds, or a result of Result::Error*. + */ + virtual ResultWithValue calculateLatencyMillis() { + return ResultWithValue(Result::ErrorUnimplemented); + } + + /** + * Get the estimated time that the frame at `framePosition` entered or left the audio processing + * pipeline. + * + * This can be used to coordinate events and interactions with the external environment, and to + * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe + * sample (search for "calculateCurrentOutputLatencyMillis"). + * + * The time is based on the implementation's best effort, using whatever knowledge is available + * to the system, but cannot account for any delay unknown to the implementation. + * + * Note that due to issues in Android before R, we recommend NOT calling + * this method from a data callback. See this tech note for more details. + * https://github.com/google/oboe/blob/main/docs/notes/rlsbuffer.md + * + * @deprecated since 1.0, use AudioStream::getTimestamp(clockid_t clockId) instead, which + * returns ResultWithValue + * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC + * @param framePosition the frame number to query + * @param timeNanoseconds an output parameter which will contain the presentation timestamp + */ + virtual Result getTimestamp(clockid_t /* clockId */, + int64_t* /* framePosition */, + int64_t* /* timeNanoseconds */) { + return Result::ErrorUnimplemented; + } + + /** + * Get the estimated time that the frame at `framePosition` entered or left the audio processing + * pipeline. + * + * This can be used to coordinate events and interactions with the external environment, and to + * estimate the latency of an audio stream. An example of usage can be found in the hello-oboe + * sample (search for "calculateCurrentOutputLatencyMillis"). + * + * The time is based on the implementation's best effort, using whatever knowledge is available + * to the system, but cannot account for any delay unknown to the implementation. + * + * Note that due to issues in Android before R, we recommend NOT calling + * this method from a data callback. See this tech note for more details. + * https://github.com/google/oboe/blob/main/docs/notes/rlsbuffer.md + * + * See + * @param clockId the type of clock to use e.g. CLOCK_MONOTONIC + * @return a FrameTimestamp containing the position and time at which a particular audio frame + * entered or left the audio processing pipeline, or an error if the operation failed. + */ + virtual ResultWithValue getTimestamp(clockid_t /* clockId */); + + // ============== I/O =========================== + /** + * Write data from the supplied buffer into the stream. This method will block until the write + * is complete or it runs out of time. + * + * If `timeoutNanoseconds` is zero then this call will not wait. + * + * @param buffer The address of the first sample. + * @param numFrames Number of frames to write. Only complete frames will be written. + * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. + * @return a ResultWithValue which has a result of Result::OK and a value containing the number + * of frames actually written, or result of Result::Error*. + */ + virtual ResultWithValue write(const void* /* buffer */, + int32_t /* numFrames */, + int64_t /* timeoutNanoseconds */ ) { + return ResultWithValue(Result::ErrorUnimplemented); + } + + /** + * Read data into the supplied buffer from the stream. This method will block until the read + * is complete or it runs out of time. + * + * If `timeoutNanoseconds` is zero then this call will not wait. + * + * @param buffer The address of the first sample. + * @param numFrames Number of frames to read. Only complete frames will be read. + * @param timeoutNanoseconds Maximum number of nanoseconds to wait for completion. + * @return a ResultWithValue which has a result of Result::OK and a value containing the number + * of frames actually read, or result of Result::Error*. + */ + virtual ResultWithValue read(void* /* buffer */, + int32_t /* numFrames */, + int64_t /* timeoutNanoseconds */) { + return ResultWithValue(Result::ErrorUnimplemented); + } + + /** + * Get the underlying audio API which the stream uses. + * + * @return the API that this stream uses. + */ + virtual AudioApi getAudioApi() const = 0; + + /** + * Returns true if the underlying audio API is AAudio. + * + * @return true if this stream is implemented using the AAudio API. + */ + bool usesAAudio() const { + return getAudioApi() == AudioApi::AAudio; + } + + /** + * Only for debugging. Do not use in production. + * If you need to call this method something is wrong. + * If you think you need it for production then please let us know + * so we can modify Oboe so that you don't need this. + * + * @return nullptr or a pointer to a stream from the system API + */ + virtual void *getUnderlyingStream() const { + return nullptr; + } + + /** + * Update mFramesWritten. + * For internal use only. + */ + virtual void updateFramesWritten() = 0; + + /** + * Update mFramesRead. + * For internal use only. + */ + virtual void updateFramesRead() = 0; + + /* + * Swap old callback for new callback. + * This not atomic. + * This should only be used internally. + * @param dataCallback + * @return previous dataCallback + */ + AudioStreamDataCallback *swapDataCallback(AudioStreamDataCallback *dataCallback) { + AudioStreamDataCallback *previousCallback = mDataCallback; + mDataCallback = dataCallback; + return previousCallback; + } + + /* + * Swap old callback for new callback. + * This not atomic. + * This should only be used internally. + * @param errorCallback + * @return previous errorCallback + */ + AudioStreamErrorCallback *swapErrorCallback(AudioStreamErrorCallback *errorCallback) { + AudioStreamErrorCallback *previousCallback = mErrorCallback; + mErrorCallback = errorCallback; + return previousCallback; + } + + /** + * @return number of frames of data currently in the buffer + */ + ResultWithValue getAvailableFrames(); + + /** + * Wait until the stream has a minimum amount of data available in its buffer. + * This can be used with an EXCLUSIVE MMAP input stream to avoid reading data too close to + * the DSP write position, which may cause glitches. + * + * @param numFrames minimum frames available + * @param timeoutNanoseconds + * @return number of frames available, ErrorTimeout + */ + ResultWithValue waitForAvailableFrames(int32_t numFrames, + int64_t timeoutNanoseconds); + + /** + * @return last result passed from an error callback + */ + virtual oboe::Result getLastErrorCallbackResult() const { + return mErrorCallbackResult; + } + + + int32_t getDelayBeforeCloseMillis() const { + return mDelayBeforeCloseMillis; + } + + /** + * Set the time to sleep before closing the internal stream. + * + * Sometimes a callback can occur shortly after a stream has been stopped and + * even after a close! If the stream has been closed then the callback + * might access memory that has been freed, which could cause a crash. + * This seems to be more likely in Android P or earlier. + * But it can also occur in later versions. By sleeping, we give time for + * the callback threads to finish. + * + * Note that this only has an effect when OboeGlobals::areWorkaroundsEnabled() is true. + * + * @param delayBeforeCloseMillis time to sleep before close. + */ + void setDelayBeforeCloseMillis(int32_t delayBeforeCloseMillis) { + mDelayBeforeCloseMillis = delayBeforeCloseMillis; + } + +protected: + + /** + * This is used to detect more than one error callback from a stream. + * These were bugs in some versions of Android that caused multiple error callbacks. + * Internal bug b/63087953 + * + * Calling this sets an atomic true and returns the previous value. + * + * @return false on first call, true on subsequent calls + */ + bool wasErrorCallbackCalled() { + return mErrorCallbackCalled.exchange(true); + } + + /** + * Wait for a transition from one state to another. + * @return OK if the endingState was observed, or ErrorUnexpectedState + * if any state that was not the startingState or endingState was observed + * or ErrorTimeout. + */ + virtual Result waitForStateTransition(StreamState startingState, + StreamState endingState, + int64_t timeoutNanoseconds); + + /** + * Override this to provide a default for when the application did not specify a callback. + * + * @param audioData + * @param numFrames + * @return result + */ + virtual DataCallbackResult onDefaultCallback(void* /* audioData */, int /* numFrames */) { + return DataCallbackResult::Stop; + } + + /** + * Override this to provide your own behaviour for the audio callback + * + * @param audioData container array which audio frames will be written into or read from + * @param numFrames number of frames which were read/written + * @return the result of the callback: stop or continue + * + */ + DataCallbackResult fireDataCallback(void *audioData, int numFrames); + + /** + * @return true if callbacks may be called + */ + bool isDataCallbackEnabled() { + return mDataCallbackEnabled; + } + + /** + * This can be set false internally to prevent callbacks + * after DataCallbackResult::Stop has been returned. + */ + void setDataCallbackEnabled(bool enabled) { + mDataCallbackEnabled = enabled; + } + + /** + * This should only be called as a stream is being opened. + * Otherwise we might override setDelayBeforeCloseMillis(). + */ + void calculateDefaultDelayBeforeCloseMillis(); + + /** + * Try to avoid a race condition when closing. + */ + void sleepBeforeClose() { + if (mDelayBeforeCloseMillis > 0) { + usleep(mDelayBeforeCloseMillis * 1000); + } + } + + /* + * Set a weak_ptr to this stream from the shared_ptr so that we can + * later use a shared_ptr in the error callback. + */ + void setWeakThis(std::shared_ptr &sharedStream) { + mWeakThis = sharedStream; + } + + /* + * Make a shared_ptr that will prevent this stream from being deleted. + */ + std::shared_ptr lockWeakThis() { + return mWeakThis.lock(); + } + + std::weak_ptr mWeakThis; // weak pointer to this object + + /** + * Number of frames which have been written into the stream + * + * This is signed integer to match the counters in AAudio. + * At audio rates, the counter will overflow in about six million years. + */ + std::atomic mFramesWritten{}; + + /** + * Number of frames which have been read from the stream. + * + * This is signed integer to match the counters in AAudio. + * At audio rates, the counter will overflow in about six million years. + */ + std::atomic mFramesRead{}; + + std::mutex mLock; // for synchronizing start/stop/close + + oboe::Result mErrorCallbackResult = oboe::Result::OK; + + /** + * Number of frames which will be copied to/from the audio device in a single read/write + * operation + */ + int32_t mFramesPerBurst = kUnspecified; + + // Time to sleep in order to prevent a race condition with a callback after a close(). + // Two milliseconds may be enough but 10 msec is even safer. + static constexpr int kMinDelayBeforeCloseMillis = 10; + int32_t mDelayBeforeCloseMillis = kMinDelayBeforeCloseMillis; + +private: + + // Log the scheduler if it changes. + void checkScheduler(); + int mPreviousScheduler = -1; + + std::atomic mDataCallbackEnabled{false}; + std::atomic mErrorCallbackCalled{false}; +}; + +/** + * This struct is a stateless functor which closes an AudioStream prior to its deletion. + * This means it can be used to safely delete a smart pointer referring to an open stream. + */ + struct StreamDeleterFunctor { + void operator()(AudioStream *audioStream) { + if (audioStream) { + audioStream->close(); + } + delete audioStream; + } + }; +} // namespace oboe + +#endif /* OBOE_STREAM_H_ */ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Definitions_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Definitions_android.h new file mode 100644 index 0000000..be65c84 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Definitions_android.h @@ -0,0 +1,711 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_DEFINITIONS_H +#define OBOE_DEFINITIONS_H + +#include +#include + +// Oboe needs to be able to build on old NDKs so we use hard coded constants. +// The correctness of these constants is verified in "aaudio/AAudioLoader.cpp". + +namespace oboe { + + /** + * Represents any attribute, property or value which hasn't been specified. + */ + constexpr int32_t kUnspecified = 0; + + // TODO: Investigate using std::chrono + /** + * The number of nanoseconds in a microsecond. 1,000. + */ + constexpr int64_t kNanosPerMicrosecond = 1000; + + /** + * The number of nanoseconds in a millisecond. 1,000,000. + */ + constexpr int64_t kNanosPerMillisecond = kNanosPerMicrosecond * 1000; + + /** + * The number of milliseconds in a second. 1,000. + */ + constexpr int64_t kMillisPerSecond = 1000; + + /** + * The number of nanoseconds in a second. 1,000,000,000. + */ + constexpr int64_t kNanosPerSecond = kNanosPerMillisecond * kMillisPerSecond; + + /** + * The state of the audio stream. + */ + enum class StreamState : int32_t { // aaudio_stream_state_t + Uninitialized = 0, // AAUDIO_STREAM_STATE_UNINITIALIZED, + Unknown = 1, // AAUDIO_STREAM_STATE_UNKNOWN, + Open = 2, // AAUDIO_STREAM_STATE_OPEN, + Starting = 3, // AAUDIO_STREAM_STATE_STARTING, + Started = 4, // AAUDIO_STREAM_STATE_STARTED, + Pausing = 5, // AAUDIO_STREAM_STATE_PAUSING, + Paused = 6, // AAUDIO_STREAM_STATE_PAUSED, + Flushing = 7, // AAUDIO_STREAM_STATE_FLUSHING, + Flushed = 8, // AAUDIO_STREAM_STATE_FLUSHED, + Stopping = 9, // AAUDIO_STREAM_STATE_STOPPING, + Stopped = 10, // AAUDIO_STREAM_STATE_STOPPED, + Closing = 11, // AAUDIO_STREAM_STATE_CLOSING, + Closed = 12, // AAUDIO_STREAM_STATE_CLOSED, + Disconnected = 13, // AAUDIO_STREAM_STATE_DISCONNECTED, + }; + + /** + * The direction of the stream. + */ + enum class Direction : int32_t { // aaudio_direction_t + + /** + * Used for playback. + */ + Output = 0, // AAUDIO_DIRECTION_OUTPUT, + + /** + * Used for recording. + */ + Input = 1, // AAUDIO_DIRECTION_INPUT, + }; + + /** + * The format of audio samples. + */ + enum class AudioFormat : int32_t { // aaudio_format_t + /** + * Invalid format. + */ + Invalid = -1, // AAUDIO_FORMAT_INVALID, + + /** + * Unspecified format. Format will be decided by Oboe. + */ + Unspecified = 0, // AAUDIO_FORMAT_UNSPECIFIED, + + /** + * Signed 16-bit integers. + */ + I16 = 1, // AAUDIO_FORMAT_PCM_I16, + + /** + * Single precision floating point. + * + * This is the recommended format for most applications. + * But note that the use of Float may prevent the opening of + * a low-latency input path on OpenSL ES or Legacy AAudio streams. + */ + Float = 2, // AAUDIO_FORMAT_PCM_FLOAT, + + /** + * Signed 24-bit integers, packed into 3 bytes. + * + * Note that the use of this format does not guarantee that + * the full precision will be provided. The underlying device may + * be using I16 format. + * + * Added in API 31 (S). + */ + I24 = 3, // AAUDIO_FORMAT_PCM_I24_PACKED + + /** + * Signed 32-bit integers. + * + * Note that the use of this format does not guarantee that + * the full precision will be provided. The underlying device may + * be using I16 format. + * + * Added in API 31 (S). + */ + I32 = 4, // AAUDIO_FORMAT_PCM_I32 + + }; + + /** + * The result of an audio callback. + */ + enum class DataCallbackResult : int32_t { // aaudio_data_callback_result_t + // Indicates to the caller that the callbacks should continue. + Continue = 0, // AAUDIO_CALLBACK_RESULT_CONTINUE, + + // Indicates to the caller that the callbacks should stop immediately. + Stop = 1, // AAUDIO_CALLBACK_RESULT_STOP, + }; + + /** + * The result of an operation. All except the `OK` result indicates that an error occurred. + * The `Result` can be converted into a human readable string using `convertToText`. + */ + enum class Result : int32_t { // aaudio_result_t + OK = 0, // AAUDIO_OK + ErrorBase = -900, // AAUDIO_ERROR_BASE, + ErrorDisconnected = -899, // AAUDIO_ERROR_DISCONNECTED, + ErrorIllegalArgument = -898, // AAUDIO_ERROR_ILLEGAL_ARGUMENT, + ErrorInternal = -896, // AAUDIO_ERROR_INTERNAL, + ErrorInvalidState = -895, // AAUDIO_ERROR_INVALID_STATE, + ErrorInvalidHandle = -892, // AAUDIO_ERROR_INVALID_HANDLE, + ErrorUnimplemented = -890, // AAUDIO_ERROR_UNIMPLEMENTED, + ErrorUnavailable = -889, // AAUDIO_ERROR_UNAVAILABLE, + ErrorNoFreeHandles = -888, // AAUDIO_ERROR_NO_FREE_HANDLES, + ErrorNoMemory = -887, // AAUDIO_ERROR_NO_MEMORY, + ErrorNull = -886, // AAUDIO_ERROR_NULL, + ErrorTimeout = -885, // AAUDIO_ERROR_TIMEOUT, + ErrorWouldBlock = -884, // AAUDIO_ERROR_WOULD_BLOCK, + ErrorInvalidFormat = -883, // AAUDIO_ERROR_INVALID_FORMAT, + ErrorOutOfRange = -882, // AAUDIO_ERROR_OUT_OF_RANGE, + ErrorNoService = -881, // AAUDIO_ERROR_NO_SERVICE, + ErrorInvalidRate = -880, // AAUDIO_ERROR_INVALID_RATE, + // Reserved for future AAudio result types + Reserved1, + Reserved2, + Reserved3, + Reserved4, + Reserved5, + Reserved6, + Reserved7, + Reserved8, + Reserved9, + Reserved10, + ErrorClosed = -869, + }; + + /** + * The sharing mode of the audio stream. + */ + enum class SharingMode : int32_t { // aaudio_sharing_mode_t + + /** + * This will be the only stream using a particular source or sink. + * This mode will provide the lowest possible latency. + * You should close EXCLUSIVE streams immediately when you are not using them. + * + * If you do not need the lowest possible latency then we recommend using Shared, + * which is the default. + */ + Exclusive = 0, // AAUDIO_SHARING_MODE_EXCLUSIVE, + + /** + * Multiple applications can share the same device. + * The data from output streams will be mixed by the audio service. + * The data for input streams will be distributed by the audio service. + * + * This will have higher latency than the EXCLUSIVE mode. + */ + Shared = 1, // AAUDIO_SHARING_MODE_SHARED, + }; + + /** + * The performance mode of the audio stream. + */ + enum class PerformanceMode : int32_t { // aaudio_performance_mode_t + + /** + * No particular performance needs. Default. + */ + None = 10, // AAUDIO_PERFORMANCE_MODE_NONE, + + /** + * Extending battery life is most important. + */ + PowerSaving = 11, // AAUDIO_PERFORMANCE_MODE_POWER_SAVING, + + /** + * Reducing latency is most important. + */ + LowLatency = 12, // AAUDIO_PERFORMANCE_MODE_LOW_LATENCY + }; + + /** + * The underlying audio API used by the audio stream. + */ + enum class AudioApi : int32_t { + /** + * Try to use AAudio. If not available then use OpenSL ES. + */ + Unspecified = kUnspecified, + + /** + * Use OpenSL ES. + * Note that OpenSL ES is deprecated in Android 13, API 30 and above. + */ + OpenSLES, + + /** + * Try to use AAudio. Fail if unavailable. + * AAudio was first supported in Android 8, API 26 and above. + * It is only recommended for API 27 and above. + */ + AAudio + }; + + /** + * Specifies the quality of the sample rate conversion performed by Oboe. + * Higher quality will require more CPU load. + * Higher quality conversion will probably be implemented using a sinc based resampler. + */ + enum class SampleRateConversionQuality : int32_t { + /** + * No conversion by Oboe. Underlying APIs may still do conversion. + */ + None, + /** + * Fastest conversion but may not sound great. + * This may be implemented using bilinear interpolation. + */ + Fastest, + /** + * Low quality conversion with 8 taps. + */ + Low, + /** + * Medium quality conversion with 16 taps. + */ + Medium, + /** + * High quality conversion with 32 taps. + */ + High, + /** + * Highest quality conversion, which may be expensive in terms of CPU. + */ + Best, + }; + + /** + * The Usage attribute expresses *why* you are playing a sound, what is this sound used for. + * This information is used by certain platforms or routing policies + * to make more refined volume or routing decisions. + * + * Note that these match the equivalent values in AudioAttributes in the Android Java API. + * + * This attribute only has an effect on Android API 28+. + */ + enum class Usage : int32_t { // aaudio_usage_t + /** + * Use this for streaming media, music performance, video, podcasts, etcetera. + */ + Media = 1, // AAUDIO_USAGE_MEDIA + + /** + * Use this for voice over IP, telephony, etcetera. + */ + VoiceCommunication = 2, // AAUDIO_USAGE_VOICE_COMMUNICATION + + /** + * Use this for sounds associated with telephony such as busy tones, DTMF, etcetera. + */ + VoiceCommunicationSignalling = 3, // AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING + + /** + * Use this to demand the users attention. + */ + Alarm = 4, // AAUDIO_USAGE_ALARM + + /** + * Use this for notifying the user when a message has arrived or some + * other background event has occured. + */ + Notification = 5, // AAUDIO_USAGE_NOTIFICATION + + /** + * Use this when the phone rings. + */ + NotificationRingtone = 6, // AAUDIO_USAGE_NOTIFICATION_RINGTONE + + /** + * Use this to attract the users attention when, for example, the battery is low. + */ + NotificationEvent = 10, // AAUDIO_USAGE_NOTIFICATION_EVENT + + /** + * Use this for screen readers, etcetera. + */ + AssistanceAccessibility = 11, // AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY + + /** + * Use this for driving or navigation directions. + */ + AssistanceNavigationGuidance = 12, // AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE + + /** + * Use this for user interface sounds, beeps, etcetera. + */ + AssistanceSonification = 13, // AAUDIO_USAGE_ASSISTANCE_SONIFICATION + + /** + * Use this for game audio and sound effects. + */ + Game = 14, // AAUDIO_USAGE_GAME + + /** + * Use this for audio responses to user queries, audio instructions or help utterances. + */ + Assistant = 16, // AAUDIO_USAGE_ASSISTANT + }; + + + /** + * The ContentType attribute describes *what* you are playing. + * It expresses the general category of the content. This information is optional. + * But in case it is known (for instance {@link Movie} for a + * movie streaming service or {@link Speech} for + * an audio book application) this information might be used by the audio framework to + * enforce audio focus. + * + * Note that these match the equivalent values in AudioAttributes in the Android Java API. + * + * This attribute only has an effect on Android API 28+. + */ + enum ContentType : int32_t { // aaudio_content_type_t + + /** + * Use this for spoken voice, audio books, etcetera. + */ + Speech = 1, // AAUDIO_CONTENT_TYPE_SPEECH + + /** + * Use this for pre-recorded or live music. + */ + Music = 2, // AAUDIO_CONTENT_TYPE_MUSIC + + /** + * Use this for a movie or video soundtrack. + */ + Movie = 3, // AAUDIO_CONTENT_TYPE_MOVIE + + /** + * Use this for sound is designed to accompany a user action, + * such as a click or beep sound made when the user presses a button. + */ + Sonification = 4, // AAUDIO_CONTENT_TYPE_SONIFICATION + }; + + /** + * Defines the audio source. + * An audio source defines both a default physical source of audio signal, and a recording + * configuration. + * + * Note that these match the equivalent values in MediaRecorder.AudioSource in the Android Java API. + * + * This attribute only has an effect on Android API 28+. + */ + enum InputPreset : int32_t { // aaudio_input_preset_t + /** + * Use this preset when other presets do not apply. + */ + Generic = 1, // AAUDIO_INPUT_PRESET_GENERIC + + /** + * Use this preset when recording video. + */ + Camcorder = 5, // AAUDIO_INPUT_PRESET_CAMCORDER + + /** + * Use this preset when doing speech recognition. + */ + VoiceRecognition = 6, // AAUDIO_INPUT_PRESET_VOICE_RECOGNITION + + /** + * Use this preset when doing telephony or voice messaging. + */ + VoiceCommunication = 7, // AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION + + /** + * Use this preset to obtain an input with no effects. + * Note that this input will not have automatic gain control + * so the recorded volume may be very low. + */ + Unprocessed = 9, // AAUDIO_INPUT_PRESET_UNPROCESSED + + /** + * Use this preset for capturing audio meant to be processed in real time + * and played back for live performance (e.g karaoke). + * The capture path will minimize latency and coupling with playback path. + */ + VoicePerformance = 10, // AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE + + }; + + /** + * This attribute can be used to allocate a session ID to the audio stream. + * + * This attribute only has an effect on Android API 28+. + */ + enum SessionId { + /** + * Do not allocate a session ID. + * Effects cannot be used with this stream. + * Default. + */ + None = -1, // AAUDIO_SESSION_ID_NONE + + /** + * Allocate a session ID that can be used to attach and control + * effects using the Java AudioEffects API. + * Note that the use of this flag may result in higher latency. + * + * Note that this matches the value of AudioManager.AUDIO_SESSION_ID_GENERATE. + */ + Allocate = 0, // AAUDIO_SESSION_ID_ALLOCATE + }; + + /** + * The channel count of the audio stream. The underlying type is `int32_t`. + * Use of this enum is convenient to avoid "magic" + * numbers when specifying the channel count. + * + * For example, you can write + * `builder.setChannelCount(ChannelCount::Stereo)` + * rather than `builder.setChannelCount(2)` + * + */ + enum ChannelCount : int32_t { + /** + * Audio channel count definition, use Mono or Stereo + */ + Unspecified = kUnspecified, + + /** + * Use this for mono audio + */ + Mono = 1, + + /** + * Use this for stereo audio. + */ + Stereo = 2, + }; + + /** + * The channel mask of the audio stream. The underlying type is `uint32_t`. + * Use of this enum is convenient. + * + * ChannelMask::Unspecified means this is not specified. + * The rest of the enums are channel position masks. + * Use the combinations of the channel position masks defined below instead of + * using those values directly. + */ + enum class ChannelMask : uint32_t { // aaudio_channel_mask_t + Unspecified = kUnspecified, + FrontLeft = 1 << 0, + FrontRight = 1 << 1, + FrontCenter = 1 << 2, + LowFrequency = 1 << 3, + BackLeft = 1 << 4, + BackRight = 1 << 5, + FrontLeftOfCenter = 1 << 6, + FrontRightOfCenter = 1 << 7, + BackCenter = 1 << 8, + SideLeft = 1 << 9, + SideRight = 1 << 10, + TopCenter = 1 << 11, + TopFrontLeft = 1 << 12, + TopFrontCenter = 1 << 13, + TopFrontRight = 1 << 14, + TopBackLeft = 1 << 15, + TopBackCenter = 1 << 16, + TopBackRight = 1 << 17, + TopSideLeft = 1 << 18, + TopSideRight = 1 << 19, + BottomFrontLeft = 1 << 20, + BottomFrontCenter = 1 << 21, + BottomFrontRight = 1 << 22, + LowFrequency2 = 1 << 23, + FrontWideLeft = 1 << 24, + FrontWideRight = 1 << 25, + + Mono = FrontLeft, + + Stereo = FrontLeft | + FrontRight, + + CM2Point1 = FrontLeft | + FrontRight | + LowFrequency, + + Tri = FrontLeft | + FrontRight | + FrontCenter, + + TriBack = FrontLeft | + FrontRight | + BackCenter, + + CM3Point1 = FrontLeft | + FrontRight | + FrontCenter | + LowFrequency, + + CM2Point0Point2 = FrontLeft | + FrontRight | + TopSideLeft | + TopSideRight, + + CM2Point1Point2 = CM2Point0Point2 | + LowFrequency, + + CM3Point0Point2 = FrontLeft | + FrontRight | + FrontCenter | + TopSideLeft | + TopSideRight, + + CM3Point1Point2 = CM3Point0Point2 | + LowFrequency, + + Quad = FrontLeft | + FrontRight | + BackLeft | + BackRight, + + QuadSide = FrontLeft | + FrontRight | + SideLeft | + SideRight, + + Surround = FrontLeft | + FrontRight | + FrontCenter | + BackCenter, + + Penta = Quad | + FrontCenter, + + // aka 5Point1Back + CM5Point1 = FrontLeft | + FrontRight | + FrontCenter | + LowFrequency | + BackLeft | + BackRight, + + CM5Point1Side = FrontLeft | + FrontRight | + FrontCenter | + LowFrequency | + SideLeft | + SideRight, + + CM6Point1 = FrontLeft | + FrontRight | + FrontCenter | + LowFrequency | + BackLeft | + BackRight | + BackCenter, + + CM7Point1 = CM5Point1 | + SideLeft | + SideRight, + + CM5Point1Point2 = CM5Point1 | + TopSideLeft | + TopSideRight, + + CM5Point1Point4 = CM5Point1 | + TopFrontLeft | + TopFrontRight | + TopBackLeft | + TopBackRight, + + CM7Point1Point2 = CM7Point1 | + TopSideLeft | + TopSideRight, + + CM7Point1Point4 = CM7Point1 | + TopFrontLeft | + TopFrontRight | + TopBackLeft | + TopBackRight, + + CM9Point1Point4 = CM7Point1Point4 | + FrontWideLeft | + FrontWideRight, + + CM9Point1Point6 = CM9Point1Point4 | + TopSideLeft | + TopSideRight, + + FrontBack = FrontCenter | + BackCenter, + }; + + /** + * On API 16 to 26 OpenSL ES will be used. When using OpenSL ES the optimal values for sampleRate and + * framesPerBurst are not known by the native code. + * On API 17+ these values should be obtained from the AudioManager using this code: + * + *

+     * // Note that this technique only works for built-in speakers and headphones.
+     * AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+     * String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
+     * int defaultSampleRate = Integer.parseInt(sampleRateStr);
+     * String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
+     * int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr);
+     * 
+ * + * It can then be passed down to Oboe through JNI. + * + * AAudio will get the optimal framesPerBurst from the HAL and will ignore this value. + */ + class DefaultStreamValues { + + public: + + /** The default sample rate to use when opening new audio streams */ + static int32_t SampleRate; + /** The default frames per burst to use when opening new audio streams */ + static int32_t FramesPerBurst; + /** The default channel count to use when opening new audio streams */ + static int32_t ChannelCount; + + }; + + /** + * The time at which the frame at `position` was presented + */ + struct FrameTimestamp { + int64_t position; // in frames + int64_t timestamp; // in nanoseconds + }; + + class OboeGlobals { + public: + + static bool areWorkaroundsEnabled() { + return mWorkaroundsEnabled; + } + + /** + * Disable this when writing tests to reproduce bugs in AAudio or OpenSL ES + * that have workarounds in Oboe. + * @param enabled + */ + static void setWorkaroundsEnabled(bool enabled) { + mWorkaroundsEnabled = enabled; + } + + private: + static bool mWorkaroundsEnabled; + }; +} // namespace oboe + +#endif // OBOE_DEFINITIONS_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_FifoBuffer_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_FifoBuffer_android.h new file mode 100644 index 0000000..e7c389e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_FifoBuffer_android.h @@ -0,0 +1,164 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_FIFOPROCESSOR_H +#define OBOE_FIFOPROCESSOR_H + +#include +#include + +#include "oboe_oboe_Definitions_android.h" + +#include "oboe_oboe_FifoControllerBase_android.h" + +namespace oboe { + +class FifoBuffer { +public: + /** + * Construct a `FifoBuffer`. + * + * @param bytesPerFrame amount of bytes for one frame + * @param capacityInFrames the capacity of frames in fifo + */ + FifoBuffer(uint32_t bytesPerFrame, uint32_t capacityInFrames); + + /** + * Construct a `FifoBuffer`. + * To be used if the storage allocation is done outside of FifoBuffer. + * + * @param bytesPerFrame amount of bytes for one frame + * @param capacityInFrames capacity of frames in fifo + * @param readCounterAddress address of read counter + * @param writeCounterAddress address of write counter + * @param dataStorageAddress address of storage + */ + FifoBuffer(uint32_t bytesPerFrame, + uint32_t capacityInFrames, + std::atomic *readCounterAddress, + std::atomic *writeCounterAddress, + uint8_t *dataStorageAddress); + + ~FifoBuffer(); + + /** + * Convert a number of frames in bytes. + * + * @return number of bytes + */ + int32_t convertFramesToBytes(int32_t frames); + + /** + * Read framesToRead or, if not enough, then read as many as are available. + * + * @param destination + * @param framesToRead number of frames requested + * @return number of frames actually read + */ + int32_t read(void *destination, int32_t framesToRead); + + /** + * Write framesToWrite or, if too enough, then write as many as the fifo are not empty. + * + * @param destination + * @param framesToWrite number of frames requested + * @return number of frames actually write + */ + int32_t write(const void *source, int32_t framesToWrite); + + /** + * Get the buffer capacity in frames. + * + * @return number of frames + */ + uint32_t getBufferCapacityInFrames() const; + + /** + * Calls read(). If all of the frames cannot be read then the remainder of the buffer + * is set to zero. + * + * @param destination + * @param framesToRead number of frames requested + * @return number of frames actually read + */ + int32_t readNow(void *destination, int32_t numFrames); + + /** + * Get the number of frames in the fifo. + * + * @return number of frames actually in the buffer + */ + uint32_t getFullFramesAvailable() { + return mFifo->getFullFramesAvailable(); + } + + /** + * Get the amount of bytes per frame. + * + * @return number of bytes per frame + */ + uint32_t getBytesPerFrame() const { + return mBytesPerFrame; + } + + /** + * Get the position of read counter. + * + * @return position of read counter + */ + uint64_t getReadCounter() const { + return mFifo->getReadCounter(); + } + + /** + * Set the position of read counter. + * + * @param n position of read counter + */ + void setReadCounter(uint64_t n) { + mFifo->setReadCounter(n); + } + + /** + * Get the position of write counter. + * + * @return position of write counter + */ + uint64_t getWriteCounter() { + return mFifo->getWriteCounter(); + } + + /** + * Set the position of write counter. + * + * @param n position of write counter + */ + void setWriteCounter(uint64_t n) { + mFifo->setWriteCounter(n); + } + +private: + uint32_t mBytesPerFrame; + uint8_t* mStorage; + bool mStorageOwned; // did this object allocate the storage? + std::unique_ptr mFifo; + uint64_t mFramesReadCount; + uint64_t mFramesUnderrunCount; +}; + +} // namespace oboe + +#endif //OBOE_FIFOPROCESSOR_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_FifoControllerBase_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_FifoControllerBase_android.h new file mode 100644 index 0000000..6c12b75 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_FifoControllerBase_android.h @@ -0,0 +1,112 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NATIVEOBOE_FIFOCONTROLLERBASE_H +#define NATIVEOBOE_FIFOCONTROLLERBASE_H + +#include + +namespace oboe { + +/** + * Manage the read/write indices of a circular buffer. + * + * The caller is responsible for reading and writing the actual data. + * Note that the span of available frames may not be contiguous. They + * may wrap around from the end to the beginning of the buffer. In that + * case the data must be read or written in at least two blocks of frames. + * + */ + +class FifoControllerBase { + +public: + /** + * Construct a `FifoControllerBase`. + * + * @param totalFrames capacity of the circular buffer in frames + */ + FifoControllerBase(uint32_t totalFrames); + + virtual ~FifoControllerBase() = default; + + /** + * The frames available to read will be calculated from the read and write counters. + * The result will be clipped to the capacity of the buffer. + * If the buffer has underflowed then this will return zero. + * + * @return number of valid frames available to read. + */ + uint32_t getFullFramesAvailable() const; + + /** + * The index in a circular buffer of the next frame to read. + * + * @return read index position + */ + uint32_t getReadIndex() const; + + /** + * Advance read index from a number of frames. + * Equivalent of incrementReadCounter(numFrames). + * + * @param numFrames number of frames to advance the read index + */ + void advanceReadIndex(uint32_t numFrames); + + /** + * Get the number of frame that are not written yet. + * + * @return maximum number of frames that can be written without exceeding the threshold + */ + uint32_t getEmptyFramesAvailable() const; + + /** + * The index in a circular buffer of the next frame to write. + * + * @return index of the next frame to write + */ + uint32_t getWriteIndex() const; + + /** + * Advance write index from a number of frames. + * Equivalent of incrementWriteCounter(numFrames). + * + * @param numFrames number of frames to advance the write index + */ + void advanceWriteIndex(uint32_t numFrames); + + /** + * Get the frame capacity of the fifo. + * + * @return frame capacity + */ + uint32_t getFrameCapacity() const { return mTotalFrames; } + + virtual uint64_t getReadCounter() const = 0; + virtual void setReadCounter(uint64_t n) = 0; + virtual void incrementReadCounter(uint64_t n) = 0; + virtual uint64_t getWriteCounter() const = 0; + virtual void setWriteCounter(uint64_t n) = 0; + virtual void incrementWriteCounter(uint64_t n) = 0; + +private: + uint32_t mTotalFrames; +}; + +} // namespace oboe + +#endif //NATIVEOBOE_FIFOCONTROLLERBASE_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_LatencyTuner_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_LatencyTuner_android.h new file mode 100644 index 0000000..efff393 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_LatencyTuner_android.h @@ -0,0 +1,150 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_LATENCY_TUNER_ +#define OBOE_LATENCY_TUNER_ + +#include +#include +#include "oboe_oboe_Definitions_android.h" +#include "oboe_oboe_AudioStream_android.h" + +namespace oboe { + +/** + * LatencyTuner can be used to dynamically tune the latency of an output stream. + * It adjusts the stream's bufferSize by monitoring the number of underruns. + * + * This only affects the latency associated with the first level of buffering that is closest + * to the application. It does not affect low latency in the HAL, or touch latency in the UI. + * + * Call tune() right before returning from your data callback function if using callbacks. + * Call tune() right before calling write() if using blocking writes. + * + * If you want to see the ongoing results of this tuning process then call + * stream->getBufferSize() periodically. + * + */ +class LatencyTuner { +public: + + /** + * Construct a new LatencyTuner object which will act on the given audio stream + * + * @param stream the stream who's latency will be tuned + */ + explicit LatencyTuner(AudioStream &stream); + + /** + * Construct a new LatencyTuner object which will act on the given audio stream. + * + * @param stream the stream who's latency will be tuned + * @param the maximum buffer size which the tune() operation will set the buffer size to + */ + explicit LatencyTuner(AudioStream &stream, int32_t maximumBufferSize); + + /** + * Adjust the bufferSizeInFrames to optimize latency. + * It will start with a low latency and then raise it if an underrun occurs. + * + * Latency tuning is only supported for AAudio. + * + * @return OK or negative error, ErrorUnimplemented for OpenSL ES + */ + Result tune(); + + /** + * This may be called from another thread. Then tune() will call reset(), + * which will lower the latency to the minimum and then allow it to rise back up + * if there are glitches. + * + * This is typically called in response to a user decision to minimize latency. In other words, + * call this from a button handler. + */ + void requestReset(); + + /** + * @return true if the audio stream's buffer size is at the maximum value. If no maximum value + * was specified when constructing the LatencyTuner then the value of + * stream->getBufferCapacityInFrames is used + */ + bool isAtMaximumBufferSize(); + + /** + * Set the minimum bufferSize in frames that is used when the tuner is reset. + * You may wish to call requestReset() after calling this. + * @param bufferSize + */ + void setMinimumBufferSize(int32_t bufferSize) { + mMinimumBufferSize = bufferSize; + } + + int32_t getMinimumBufferSize() const { + return mMinimumBufferSize; + } + + /** + * Set the amount the bufferSize will be incremented while tuning. + * By default, this will be one burst. + * + * Note that AAudio will quantize the buffer size to a multiple of the burstSize. + * So the final buffer sizes may not be a multiple of this increment. + * + * @param sizeIncrement + */ + void setBufferSizeIncrement(int32_t sizeIncrement) { + mBufferSizeIncrement = sizeIncrement; + } + + int32_t getBufferSizeIncrement() const { + return mBufferSizeIncrement; + } + +private: + + /** + * Drop the latency down to the minimum and then let it rise back up. + * This is useful if a glitch caused the latency to increase and it hasn't gone back down. + * + * This should only be called in the same thread as tune(). + */ + void reset(); + + enum class State { + Idle, + Active, + AtMax, + Unsupported + } ; + + // arbitrary number of calls to wait before bumping up the latency + static constexpr int32_t kIdleCount = 8; + static constexpr int32_t kDefaultNumBursts = 2; + + AudioStream &mStream; + State mState = State::Idle; + int32_t mMaxBufferSize = 0; + int32_t mPreviousXRuns = 0; + int32_t mIdleCountDown = 0; + int32_t mMinimumBufferSize; + int32_t mBufferSizeIncrement; + std::atomic mLatencyTriggerRequests{0}; // TODO user atomic requester from AAudio + std::atomic mLatencyTriggerResponses{0}; +}; + +} // namespace oboe + +#endif // OBOE_LATENCY_TUNER_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_OboeExtensions_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_OboeExtensions_android.h new file mode 100644 index 0000000..b03dbbe --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_OboeExtensions_android.h @@ -0,0 +1,64 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_EXTENSIONS_ +#define OBOE_EXTENSIONS_ + +#include + +#include "oboe_oboe_Definitions_android.h" +#include "oboe_oboe_AudioStream_android.h" + +namespace oboe { + +/** + * The definitions below are only for testing. + * They are not recommended for use in an application. + * They may change or be removed at any time. + */ +class OboeExtensions { +public: + + /** + * @returns true if the device supports AAudio MMAP + */ + static bool isMMapSupported(); + + /** + * @returns true if the AAudio MMAP data path can be selected + */ + static bool isMMapEnabled(); + + /** + * Controls whether the AAudio MMAP data path can be selected when opening a stream. + * It has no effect after the stream has been opened. + * It only affects the application that calls it. Other apps are not affected. + * + * @param enabled + * @return 0 or a negative error code + */ + static int32_t setMMapEnabled(bool enabled); + + /** + * @param oboeStream + * @return true if the AAudio MMAP data path is used on the stream + */ + static bool isMMapUsed(oboe::AudioStream *oboeStream); +}; + +} // namespace oboe + +#endif // OBOE_LATENCY_TUNER_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Oboe_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Oboe_android.h new file mode 100644 index 0000000..84bc1ac --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Oboe_android.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_OBOE_H +#define OBOE_OBOE_H + +/** + * \mainpage API reference + * + * All documentation is found in the oboe namespace section + * + */ + +#include "oboe_oboe_Definitions_android.h" +#include "oboe_oboe_ResultWithValue_android.h" +#include "oboe_oboe_LatencyTuner_android.h" +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_oboe_AudioStreamBase_android.h" +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_oboe_Utilities_android.h" +#include "oboe_oboe_Version_android.h" +#include "oboe_oboe_StabilizedCallback_android.h" +#include "oboe_oboe_FifoBuffer_android.h" +#include "oboe_oboe_OboeExtensions_android.h" + +#endif //OBOE_OBOE_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_ResultWithValue_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_ResultWithValue_android.h new file mode 100644 index 0000000..5e5c952 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_ResultWithValue_android.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_RESULT_WITH_VALUE_H +#define OBOE_RESULT_WITH_VALUE_H + +#include "oboe_oboe_Definitions_android.h" +#include +#include + +namespace oboe { + +/** + * A ResultWithValue can store both the result of an operation (either OK or an error) and a value. + * + * It has been designed for cases where the caller needs to know whether an operation succeeded and, + * if it did, a value which was obtained during the operation. + * + * For example, when reading from a stream the caller needs to know the result of the read operation + * and, if it was successful, how many frames were read. Note that ResultWithValue can be evaluated + * as a boolean so it's simple to check whether the result is OK. + * + * + * ResultWithValue resultOfRead = myStream.read(&buffer, numFrames, timeoutNanoseconds); + * + * if (resultOfRead) { + * LOGD("Frames read: %d", resultOfRead.value()); + * } else { + * LOGD("Error reading from stream: %s", resultOfRead.error()); + * } + * + */ +template +class ResultWithValue { +public: + + /** + * Construct a ResultWithValue containing an error result. + * + * @param error The error + */ + ResultWithValue(oboe::Result error) + : mValue{} + , mError(error) {} + + /** + * Construct a ResultWithValue containing an OK result and a value. + * + * @param value the value to store + */ + explicit ResultWithValue(T value) + : mValue(value) + , mError(oboe::Result::OK) {} + + /** + * Get the result. + * + * @return the result + */ + oboe::Result error() const { + return mError; + } + + /** + * Get the value + * @return + */ + T value() const { + return mValue; + } + + /** + * @return true if OK + */ + explicit operator bool() const { return mError == oboe::Result::OK; } + + /** + * Quick way to check for an error. + * + * The caller could write something like this: + * + * if (!result) { printf("Got error %s\n", convertToText(result.error())); } + * + * + * @return true if an error occurred + */ + bool operator !() const { return mError != oboe::Result::OK; } + + /** + * Implicitly convert to a Result. This enables easy comparison with Result values. Example: + * + * + * ResultWithValue result = openStream(); + * if (result == Result::ErrorNoMemory){ // tell user they're out of memory } + * + */ + operator Result() const { + return mError; + } + + /** + * Create a ResultWithValue from a number. If the number is positive the ResultWithValue will + * have a result of Result::OK and the value will contain the number. If the number is negative + * the result will be obtained from the negative number (numeric error codes can be found in + * AAudio.h) and the value will be null. + * + */ + static ResultWithValue createBasedOnSign(T numericResult){ + + // Ensure that the type is either an integer or float + static_assert(std::is_arithmetic::value, + "createBasedOnSign can only be called for numeric types (int or float)"); + + if (numericResult >= 0){ + return ResultWithValue(numericResult); + } else { + return ResultWithValue(static_cast(numericResult)); + } + } + +private: + const T mValue; + const oboe::Result mError; +}; + +/** + * If the result is `OK` then return the value, otherwise return a human-readable error message. + */ +template +std::ostream& operator<<(std::ostream &strm, const ResultWithValue &result) { + if (!result) { + strm << convertToText(result.error()); + } else { + strm << result.value(); + } + return strm; +} + +} // namespace oboe + + +#endif //OBOE_RESULT_WITH_VALUE_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_StabilizedCallback_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_StabilizedCallback_android.h new file mode 100644 index 0000000..1e84343 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_StabilizedCallback_android.h @@ -0,0 +1,75 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STABILIZEDCALLBACK_H +#define OBOE_STABILIZEDCALLBACK_H + +#include +#include "oboe_oboe_AudioStream_android.h" + +namespace oboe { + +class StabilizedCallback : public AudioStreamCallback { + +public: + explicit StabilizedCallback(AudioStreamCallback *callback); + + DataCallbackResult + onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override; + + void onErrorBeforeClose(AudioStream *oboeStream, Result error) override { + return mCallback->onErrorBeforeClose(oboeStream, error); + } + + void onErrorAfterClose(AudioStream *oboeStream, Result error) override { + + // Reset all fields now that the stream has been closed + mFrameCount = 0; + mEpochTimeNanos = 0; + mOpsPerNano = 1; + return mCallback->onErrorAfterClose(oboeStream, error); + } + +private: + + AudioStreamCallback *mCallback = nullptr; + int64_t mFrameCount = 0; + int64_t mEpochTimeNanos = 0; + double mOpsPerNano = 1; + + void generateLoad(int64_t durationNanos); +}; + +/** + * cpu_relax is an architecture specific method of telling the CPU that you don't want it to + * do much work. asm volatile keeps the compiler from optimising these instructions out. + */ +#if defined(__i386__) || defined(__x86_64__) +#define cpu_relax() asm volatile("rep; nop" ::: "memory"); + +#elif defined(__arm__) || defined(__mips__) || defined(__riscv) + #define cpu_relax() asm volatile("":::"memory") + +#elif defined(__aarch64__) +#define cpu_relax() asm volatile("yield" ::: "memory") + +#else +#error "cpu_relax is not defined for this architecture" +#endif + +} + +#endif //OBOE_STABILIZEDCALLBACK_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Utilities_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Utilities_android.h new file mode 100644 index 0000000..b32e8d9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Utilities_android.h @@ -0,0 +1,89 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_UTILITIES_H +#define OBOE_UTILITIES_H + +#include +#include +#include +#include "oboe_oboe_Definitions_android.h" + +namespace oboe { + +/** + * Convert an array of floats to an array of 16-bit integers. + * + * @param source the input array. + * @param destination the output array. + * @param numSamples the number of values to convert. + */ +void convertFloatToPcm16(const float *source, int16_t *destination, int32_t numSamples); + +/** + * Convert an array of 16-bit integers to an array of floats. + * + * @param source the input array. + * @param destination the output array. + * @param numSamples the number of values to convert. + */ +void convertPcm16ToFloat(const int16_t *source, float *destination, int32_t numSamples); + +/** + * @return the size of a sample of the given format in bytes or 0 if format is invalid + */ +int32_t convertFormatToSizeInBytes(AudioFormat format); + +/** + * The text is the ASCII symbol corresponding to the supplied Oboe enum value, + * or an English message saying the value is unrecognized. + * This is intended for developers to use when debugging. + * It is not for displaying to users. + * + * @param input object to convert from. @see common/Utilities.cpp for concrete implementations + * @return text representation of an Oboe enum value. There is no need to call free on this. + */ +template +const char * convertToText(FromType input); + +/** + * @param name + * @return the value of a named system property in a string or empty string + */ +std::string getPropertyString(const char * name); + +/** + * @param name + * @param defaultValue + * @return integer value associated with a property or the default value + */ +int getPropertyInteger(const char * name, int defaultValue); + +/** + * Return the version of the SDK that is currently running. + * + * For example, on Android, this would return 27 for Oreo 8.1. + * If the version number cannot be determined then this will return -1. + * + * @return version number or -1 + */ +int getSdkVersion(); + +int getChannelCountFromChannelMask(ChannelMask channelMask); + +} // namespace oboe + +#endif //OBOE_UTILITIES_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Version_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Version_android.h new file mode 100644 index 0000000..68c3fe9 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_oboe_Version_android.h @@ -0,0 +1,92 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_VERSIONINFO_H +#define OBOE_VERSIONINFO_H + +#include + +/** + * A note on use of preprocessor defines: + * + * This is one of the few times when it's suitable to use preprocessor defines rather than constexpr + * Why? Because C++11 requires a lot of boilerplate code to convert integers into compile-time + * string literals. The preprocessor, despite it's lack of type checking, is more suited to the task + * + * See: https://stackoverflow.com/questions/6713420/c-convert-integer-to-string-at-compile-time/26824971#26824971 + * + */ + +// Type: 8-bit unsigned int. Min value: 0 Max value: 255. See below for description. +#define OBOE_VERSION_MAJOR 1 + +// Type: 8-bit unsigned int. Min value: 0 Max value: 255. See below for description. +#define OBOE_VERSION_MINOR 7 + +// Type: 16-bit unsigned int. Min value: 0 Max value: 65535. See below for description. +#define OBOE_VERSION_PATCH 0 + +#define OBOE_STRINGIFY(x) #x +#define OBOE_TOSTRING(x) OBOE_STRINGIFY(x) + +// Type: String literal. See below for description. +#define OBOE_VERSION_TEXT \ + OBOE_TOSTRING(OBOE_VERSION_MAJOR) "." \ + OBOE_TOSTRING(OBOE_VERSION_MINOR) "." \ + OBOE_TOSTRING(OBOE_VERSION_PATCH) + +// Type: 32-bit unsigned int. See below for description. +#define OBOE_VERSION_NUMBER ((OBOE_VERSION_MAJOR << 24) | (OBOE_VERSION_MINOR << 16) | OBOE_VERSION_PATCH) + +namespace oboe { + +const char * getVersionText(); + +/** + * Oboe versioning object + */ +struct Version { + /** + * This is incremented when we make breaking API changes. Based loosely on https://semver.org/. + */ + static constexpr uint8_t Major = OBOE_VERSION_MAJOR; + + /** + * This is incremented when we add backwards compatible functionality. Or set to zero when MAJOR is + * incremented. + */ + static constexpr uint8_t Minor = OBOE_VERSION_MINOR; + + /** + * This is incremented when we make backwards compatible bug fixes. Or set to zero when MINOR is + * incremented. + */ + static constexpr uint16_t Patch = OBOE_VERSION_PATCH; + + /** + * Version string in the form MAJOR.MINOR.PATCH. + */ + static constexpr const char * Text = OBOE_VERSION_TEXT; + + /** + * Integer representation of the current Oboe library version. This will always increase when the + * version number changes so can be compared using integer comparison. + */ + static constexpr uint32_t Number = OBOE_VERSION_NUMBER; +}; + +} // namespace oboe +#endif //OBOE_VERSIONINFO_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioInputStreamOpenSLES_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioInputStreamOpenSLES_android.cpp new file mode 100644 index 0000000..2aa734c --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioInputStreamOpenSLES_android.cpp @@ -0,0 +1,358 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_opensles_AudioInputStreamOpenSLES_android.h" +#include "oboe_opensles_AudioStreamOpenSLES_android.h" +#include "oboe_opensles_OpenSLESUtilities_android.h" + +using namespace oboe; + +static SLuint32 OpenSLES_convertInputPreset(InputPreset oboePreset) { + SLuint32 openslPreset = SL_ANDROID_RECORDING_PRESET_NONE; + switch(oboePreset) { + case InputPreset::Generic: + openslPreset = SL_ANDROID_RECORDING_PRESET_GENERIC; + break; + case InputPreset::Camcorder: + openslPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER; + break; + case InputPreset::VoiceRecognition: + case InputPreset::VoicePerformance: + openslPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION; + break; + case InputPreset::VoiceCommunication: + openslPreset = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION; + break; + case InputPreset::Unprocessed: + openslPreset = SL_ANDROID_RECORDING_PRESET_UNPROCESSED; + break; + default: + break; + } + return openslPreset; +} + +AudioInputStreamOpenSLES::AudioInputStreamOpenSLES(const AudioStreamBuilder &builder) + : AudioStreamOpenSLES(builder) { +} + +AudioInputStreamOpenSLES::~AudioInputStreamOpenSLES() { +} + +// Calculate masks specific to INPUT streams. +SLuint32 AudioInputStreamOpenSLES::channelCountToChannelMask(int channelCount) const { + // Derived from internal sles_channel_in_mask_from_count(chanCount); + // in "frameworks/wilhelm/src/android/channels.cpp". + // Yes, it seems strange to use SPEAKER constants to describe inputs. + // But that is how OpenSL ES does it internally. + switch (channelCount) { + case 1: + return SL_SPEAKER_FRONT_LEFT; + case 2: + return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + default: + return channelCountToChannelMaskDefault(channelCount); + } +} + +Result AudioInputStreamOpenSLES::open() { + logUnsupportedAttributes(); + + SLAndroidConfigurationItf configItf = nullptr; + + if (getSdkVersion() < __ANDROID_API_M__ && mFormat == AudioFormat::Float){ + // TODO: Allow floating point format on API <23 using float->int16 converter + return Result::ErrorInvalidFormat; + } + + // If audio format is unspecified then choose a suitable default. + // API 23+: FLOAT + // API <23: INT16 + if (mFormat == AudioFormat::Unspecified){ + mFormat = (getSdkVersion() < __ANDROID_API_M__) ? + AudioFormat::I16 : AudioFormat::Float; + } + + Result oboeResult = AudioStreamOpenSLES::open(); + if (Result::OK != oboeResult) return oboeResult; + + SLuint32 bitsPerSample = static_cast(getBytesPerSample() * kBitsPerByte); + + // configure audio sink + mBufferQueueLength = calculateOptimalBufferQueueLength(); + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { + SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType + static_cast(mBufferQueueLength)}; // numBuffers + + // Define the audio data format. + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, // formatType + static_cast(mChannelCount), // numChannels + static_cast(mSampleRate * kMillisPerSecond), // milliSamplesPerSec + bitsPerSample, // bitsPerSample + bitsPerSample, // containerSize; + channelCountToChannelMask(mChannelCount), // channelMask + getDefaultByteOrder(), + }; + + SLDataSink audioSink = {&loc_bufq, &format_pcm}; + + /** + * API 23 (Marshmallow) introduced support for floating-point data representation and an + * extended data format type: SLAndroidDataFormat_PCM_EX for recording streams (playback streams + * got this in API 21). If running on API 23+ use this newer format type, creating it from our + * original format. + */ + SLAndroidDataFormat_PCM_EX format_pcm_ex; + if (getSdkVersion() >= __ANDROID_API_M__) { + SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat()); + // Fill in the format structure. + format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation); + // Use in place of the previous format. + audioSink.pFormat = &format_pcm_ex; + } + + + // configure audio source + SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, + SL_IODEVICE_AUDIOINPUT, + SL_DEFAULTDEVICEID_AUDIOINPUT, + NULL}; + SLDataSource audioSrc = {&loc_dev, NULL}; + + SLresult result = EngineOpenSLES::getInstance().createAudioRecorder(&mObjectInterface, + &audioSrc, + &audioSink); + + if (SL_RESULT_SUCCESS != result) { + LOGE("createAudioRecorder() result:%s", getSLErrStr(result)); + goto error; + } + + // Configure the stream. + result = (*mObjectInterface)->GetInterface(mObjectInterface, + SL_IID_ANDROIDCONFIGURATION, + &configItf); + + if (SL_RESULT_SUCCESS != result) { + LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s", + __func__, getSLErrStr(result)); + } else { + if (getInputPreset() == InputPreset::VoicePerformance) { + LOGD("OpenSL ES does not support InputPreset::VoicePerformance. Use VoiceRecognition."); + mInputPreset = InputPreset::VoiceRecognition; + } + SLuint32 presetValue = OpenSLES_convertInputPreset(getInputPreset()); + result = (*configItf)->SetConfiguration(configItf, + SL_ANDROID_KEY_RECORDING_PRESET, + &presetValue, + sizeof(SLuint32)); + if (SL_RESULT_SUCCESS != result + && presetValue != SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION) { + presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION; + LOGD("Setting InputPreset %d failed. Using VoiceRecognition instead.", getInputPreset()); + mInputPreset = InputPreset::VoiceRecognition; + (*configItf)->SetConfiguration(configItf, + SL_ANDROID_KEY_RECORDING_PRESET, + &presetValue, + sizeof(SLuint32)); + } + + result = configurePerformanceMode(configItf); + if (SL_RESULT_SUCCESS != result) { + goto error; + } + } + + result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE); + if (SL_RESULT_SUCCESS != result) { + LOGE("Realize recorder object result:%s", getSLErrStr(result)); + goto error; + } + + result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_RECORD, &mRecordInterface); + if (SL_RESULT_SUCCESS != result) { + LOGE("GetInterface RECORD result:%s", getSLErrStr(result)); + goto error; + } + + result = finishCommonOpen(configItf); + if (SL_RESULT_SUCCESS != result) { + goto error; + } + + setState(StreamState::Open); + return Result::OK; + +error: + close(); // Clean up various OpenSL objects and prevent resource leaks. + return Result::ErrorInternal; // TODO convert error from SLES to OBOE +} + +Result AudioInputStreamOpenSLES::close() { + LOGD("AudioInputStreamOpenSLES::%s()", __func__); + std::lock_guard lock(mLock); + Result result = Result::OK; + if (getState() == StreamState::Closed){ + result = Result::ErrorClosed; + } else { + (void) requestStop_l(); + if (OboeGlobals::areWorkaroundsEnabled()) { + sleepBeforeClose(); + } + // invalidate any interfaces + mRecordInterface = nullptr; + result = AudioStreamOpenSLES::close_l(); + } + return result; +} + +Result AudioInputStreamOpenSLES::setRecordState_l(SLuint32 newState) { + LOGD("AudioInputStreamOpenSLES::%s(%u)", __func__, newState); + Result result = Result::OK; + + if (mRecordInterface == nullptr) { + LOGW("AudioInputStreamOpenSLES::%s() mRecordInterface is null", __func__); + return Result::ErrorInvalidState; + } + SLresult slResult = (*mRecordInterface)->SetRecordState(mRecordInterface, newState); + //LOGD("AudioInputStreamOpenSLES::%s(%u) returned %u", __func__, newState, slResult); + if (SL_RESULT_SUCCESS != slResult) { + LOGE("AudioInputStreamOpenSLES::%s(%u) returned error %s", + __func__, newState, getSLErrStr(slResult)); + result = Result::ErrorInternal; // TODO review + } + return result; +} + +Result AudioInputStreamOpenSLES::requestStart() { + LOGD("AudioInputStreamOpenSLES(): %s() called", __func__); + std::lock_guard lock(mLock); + StreamState initialState = getState(); + switch (initialState) { + case StreamState::Starting: + case StreamState::Started: + return Result::OK; + case StreamState::Closed: + return Result::ErrorClosed; + default: + break; + } + + // We use a callback if the user requests one + // OR if we have an internal callback to fill the blocking IO buffer. + setDataCallbackEnabled(true); + + setState(StreamState::Starting); + + if (getBufferDepth(mSimpleBufferQueueInterface) == 0) { + // Enqueue the first buffer to start the streaming. + // This does not call the callback function. + enqueueCallbackBuffer(mSimpleBufferQueueInterface); + } + + Result result = setRecordState_l(SL_RECORDSTATE_RECORDING); + if (result == Result::OK) { + setState(StreamState::Started); + } else { + setState(initialState); + } + return result; +} + + +Result AudioInputStreamOpenSLES::requestPause() { + LOGW("AudioInputStreamOpenSLES::%s() is intentionally not implemented for input " + "streams", __func__); + return Result::ErrorUnimplemented; // Matches AAudio behavior. +} + +Result AudioInputStreamOpenSLES::requestFlush() { + LOGW("AudioInputStreamOpenSLES::%s() is intentionally not implemented for input " + "streams", __func__); + return Result::ErrorUnimplemented; // Matches AAudio behavior. +} + +Result AudioInputStreamOpenSLES::requestStop() { + LOGD("AudioInputStreamOpenSLES(): %s() called", __func__); + std::lock_guard lock(mLock); + return requestStop_l(); +} + +// Call under mLock +Result AudioInputStreamOpenSLES::requestStop_l() { + StreamState initialState = getState(); + switch (initialState) { + case StreamState::Stopping: + case StreamState::Stopped: + return Result::OK; + case StreamState::Uninitialized: + case StreamState::Closed: + return Result::ErrorClosed; + default: + break; + } + + setState(StreamState::Stopping); + + Result result = setRecordState_l(SL_RECORDSTATE_STOPPED); + if (result == Result::OK) { + mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped. + setState(StreamState::Stopped); + } else { + setState(initialState); + } + return result; +} + +void AudioInputStreamOpenSLES::updateFramesWritten() { + if (usingFIFO()) { + AudioStreamBuffered::updateFramesWritten(); + } else { + mFramesWritten = getFramesProcessedByServer(); + } +} + +Result AudioInputStreamOpenSLES::updateServiceFrameCounter() { + Result result = Result::OK; + // Avoid deadlock if another thread is trying to stop or close this stream + // and this is being called from a callback. + if (mLock.try_lock()) { + + if (mRecordInterface == nullptr) { + mLock.unlock(); + return Result::ErrorNull; + } + SLmillisecond msec = 0; + SLresult slResult = (*mRecordInterface)->GetPosition(mRecordInterface, &msec); + if (SL_RESULT_SUCCESS != slResult) { + LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult)); + // set result based on SLresult + result = Result::ErrorInternal; + } else { + mPositionMillis.update32(msec); + } + mLock.unlock(); + } + return result; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioInputStreamOpenSLES_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioInputStreamOpenSLES_android.h new file mode 100644 index 0000000..8141b9b --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioInputStreamOpenSLES_android.h @@ -0,0 +1,66 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUDIO_INPUT_STREAM_OPENSL_ES_H_ +#define AUDIO_INPUT_STREAM_OPENSL_ES_H_ + + +#include +#include + +#include "oboe_oboe_Oboe_android.h" +#include "oboe_opensles_AudioStreamOpenSLES_android.h" + +namespace oboe { + +/** + * INTERNAL USE ONLY + */ + +class AudioInputStreamOpenSLES : public AudioStreamOpenSLES { +public: + AudioInputStreamOpenSLES(); + explicit AudioInputStreamOpenSLES(const AudioStreamBuilder &builder); + + virtual ~AudioInputStreamOpenSLES(); + + Result open() override; + Result close() override; + + Result requestStart() override; + Result requestPause() override; + Result requestFlush() override; + Result requestStop() override; + +protected: + Result requestStop_l(); + + Result updateServiceFrameCounter() override; + + void updateFramesWritten() override; + +private: + + SLuint32 channelCountToChannelMask(int chanCount) const; + + Result setRecordState_l(SLuint32 newState); + + SLRecordItf mRecordInterface = nullptr; +}; + +} // namespace oboe + +#endif //AUDIO_INPUT_STREAM_OPENSL_ES_H_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioOutputStreamOpenSLES_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioOutputStreamOpenSLES_android.cpp new file mode 100644 index 0000000..3b5ffdd --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioOutputStreamOpenSLES_android.cpp @@ -0,0 +1,461 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include "oboe_common_AudioClock_android.h" + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_opensles_AudioOutputStreamOpenSLES_android.h" +#include "oboe_opensles_AudioStreamOpenSLES_android.h" +#include "oboe_opensles_OpenSLESUtilities_android.h" +#include "oboe_opensles_OutputMixerOpenSLES_android.h" + +using namespace oboe; + +static SLuint32 OpenSLES_convertOutputUsage(Usage oboeUsage) { + SLuint32 openslStream = SL_ANDROID_STREAM_MEDIA; + switch(oboeUsage) { + case Usage::Media: + openslStream = SL_ANDROID_STREAM_MEDIA; + break; + case Usage::VoiceCommunication: + case Usage::VoiceCommunicationSignalling: + openslStream = SL_ANDROID_STREAM_VOICE; + break; + case Usage::Alarm: + openslStream = SL_ANDROID_STREAM_ALARM; + break; + case Usage::Notification: + case Usage::NotificationRingtone: + case Usage::NotificationEvent: + openslStream = SL_ANDROID_STREAM_NOTIFICATION; + break; + case Usage::AssistanceAccessibility: + case Usage::AssistanceNavigationGuidance: + case Usage::AssistanceSonification: + openslStream = SL_ANDROID_STREAM_SYSTEM; + break; + case Usage::Game: + openslStream = SL_ANDROID_STREAM_MEDIA; + break; + case Usage::Assistant: + default: + openslStream = SL_ANDROID_STREAM_SYSTEM; + break; + } + return openslStream; +} + +AudioOutputStreamOpenSLES::AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder) + : AudioStreamOpenSLES(builder) { +} + +// These will wind up in +constexpr int SL_ANDROID_SPEAKER_STEREO = (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); + +constexpr int SL_ANDROID_SPEAKER_QUAD = (SL_ANDROID_SPEAKER_STEREO + | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT); + +constexpr int SL_ANDROID_SPEAKER_5DOT1 = (SL_ANDROID_SPEAKER_QUAD + | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY); + +constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT + | SL_SPEAKER_SIDE_RIGHT); + +SLuint32 AudioOutputStreamOpenSLES::channelCountToChannelMask(int channelCount) const { + SLuint32 channelMask = 0; + + switch (channelCount) { + case 1: + channelMask = SL_SPEAKER_FRONT_CENTER; + break; + + case 2: + channelMask = SL_ANDROID_SPEAKER_STEREO; + break; + + case 4: // Quad + channelMask = SL_ANDROID_SPEAKER_QUAD; + break; + + case 6: // 5.1 + channelMask = SL_ANDROID_SPEAKER_5DOT1; + break; + + case 8: // 7.1 + channelMask = SL_ANDROID_SPEAKER_7DOT1; + break; + + default: + channelMask = channelCountToChannelMaskDefault(channelCount); + break; + } + return channelMask; +} + +Result AudioOutputStreamOpenSLES::open() { + logUnsupportedAttributes(); + + SLAndroidConfigurationItf configItf = nullptr; + + + if (getSdkVersion() < __ANDROID_API_L__ && mFormat == AudioFormat::Float){ + // TODO: Allow floating point format on API <21 using float->int16 converter + return Result::ErrorInvalidFormat; + } + + // If audio format is unspecified then choose a suitable default. + // API 21+: FLOAT + // API <21: INT16 + if (mFormat == AudioFormat::Unspecified){ + mFormat = (getSdkVersion() < __ANDROID_API_L__) ? + AudioFormat::I16 : AudioFormat::Float; + } + + Result oboeResult = AudioStreamOpenSLES::open(); + if (Result::OK != oboeResult) return oboeResult; + + SLresult result = OutputMixerOpenSL::getInstance().open(); + if (SL_RESULT_SUCCESS != result) { + AudioStreamOpenSLES::close(); + return Result::ErrorInternal; + } + + SLuint32 bitsPerSample = static_cast(getBytesPerSample() * kBitsPerByte); + + // configure audio source + mBufferQueueLength = calculateOptimalBufferQueueLength(); + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { + SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType + static_cast(mBufferQueueLength)}; // numBuffers + + // Define the audio data format. + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, // formatType + static_cast(mChannelCount), // numChannels + static_cast(mSampleRate * kMillisPerSecond), // milliSamplesPerSec + bitsPerSample, // bitsPerSample + bitsPerSample, // containerSize; + channelCountToChannelMask(mChannelCount), // channelMask + getDefaultByteOrder(), + }; + + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + + /** + * API 21 (Lollipop) introduced support for floating-point data representation and an extended + * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format + * type, creating it from our original format. + */ + SLAndroidDataFormat_PCM_EX format_pcm_ex; + if (getSdkVersion() >= __ANDROID_API_L__) { + SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat()); + // Fill in the format structure. + format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation); + // Use in place of the previous format. + audioSrc.pFormat = &format_pcm_ex; + } + + result = OutputMixerOpenSL::getInstance().createAudioPlayer(&mObjectInterface, + &audioSrc); + if (SL_RESULT_SUCCESS != result) { + LOGE("createAudioPlayer() result:%s", getSLErrStr(result)); + goto error; + } + + // Configure the stream. + result = (*mObjectInterface)->GetInterface(mObjectInterface, + SL_IID_ANDROIDCONFIGURATION, + (void *)&configItf); + if (SL_RESULT_SUCCESS != result) { + LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s", + __func__, getSLErrStr(result)); + } else { + result = configurePerformanceMode(configItf); + if (SL_RESULT_SUCCESS != result) { + goto error; + } + + SLuint32 presetValue = OpenSLES_convertOutputUsage(getUsage()); + result = (*configItf)->SetConfiguration(configItf, + SL_ANDROID_KEY_STREAM_TYPE, + &presetValue, + sizeof(presetValue)); + if (SL_RESULT_SUCCESS != result) { + goto error; + } + } + + result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE); + if (SL_RESULT_SUCCESS != result) { + LOGE("Realize player object result:%s", getSLErrStr(result)); + goto error; + } + + result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_PLAY, &mPlayInterface); + if (SL_RESULT_SUCCESS != result) { + LOGE("GetInterface PLAY result:%s", getSLErrStr(result)); + goto error; + } + + result = finishCommonOpen(configItf); + if (SL_RESULT_SUCCESS != result) { + goto error; + } + + setState(StreamState::Open); + return Result::OK; + +error: + close(); // Clean up various OpenSL objects and prevent resource leaks. + return Result::ErrorInternal; // TODO convert error from SLES to OBOE +} + +Result AudioOutputStreamOpenSLES::onAfterDestroy() { + OutputMixerOpenSL::getInstance().close(); + return Result::OK; +} + +Result AudioOutputStreamOpenSLES::close() { + LOGD("AudioOutputStreamOpenSLES::%s()", __func__); + std::lock_guard lock(mLock); + Result result = Result::OK; + if (getState() == StreamState::Closed){ + result = Result::ErrorClosed; + } else { + (void) requestPause_l(); + if (OboeGlobals::areWorkaroundsEnabled()) { + sleepBeforeClose(); + } + // invalidate any interfaces + mPlayInterface = nullptr; + result = AudioStreamOpenSLES::close_l(); + } + return result; +} + +Result AudioOutputStreamOpenSLES::setPlayState_l(SLuint32 newState) { + + LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__); + Result result = Result::OK; + + if (mPlayInterface == nullptr){ + LOGE("AudioOutputStreamOpenSLES::%s() mPlayInterface is null", __func__); + return Result::ErrorInvalidState; + } + + SLresult slResult = (*mPlayInterface)->SetPlayState(mPlayInterface, newState); + if (SL_RESULT_SUCCESS != slResult) { + LOGW("AudioOutputStreamOpenSLES(): %s() returned %s", __func__, getSLErrStr(slResult)); + result = Result::ErrorInternal; // TODO convert slResult to Result::Error + } + return result; +} + +Result AudioOutputStreamOpenSLES::requestStart() { + LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__); + + mLock.lock(); + StreamState initialState = getState(); + switch (initialState) { + case StreamState::Starting: + case StreamState::Started: + mLock.unlock(); + return Result::OK; + case StreamState::Closed: + mLock.unlock(); + return Result::ErrorClosed; + default: + break; + } + + // We use a callback if the user requests one + // OR if we have an internal callback to read the blocking IO buffer. + setDataCallbackEnabled(true); + + setState(StreamState::Starting); + + if (getBufferDepth(mSimpleBufferQueueInterface) == 0) { + // Enqueue the first buffer if needed to start the streaming. + // We may need to stop the current stream. + bool shouldStopStream = processBufferCallback(mSimpleBufferQueueInterface); + if (shouldStopStream) { + LOGD("Stopping the current stream."); + if (requestStop_l() != Result::OK) { + LOGW("Failed to flush the stream. Error %s", convertToText(flush())); + } + setState(initialState); + mLock.unlock(); + return Result::ErrorClosed; + } + } + + Result result = setPlayState_l(SL_PLAYSTATE_PLAYING); + if (result == Result::OK) { + setState(StreamState::Started); + mLock.unlock(); + } else { + setState(initialState); + mLock.unlock(); + } + return result; +} + +Result AudioOutputStreamOpenSLES::requestPause() { + LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__); + std::lock_guard lock(mLock); + return requestPause_l(); +} + +// Call under mLock +Result AudioOutputStreamOpenSLES::requestPause_l() { + StreamState initialState = getState(); + switch (initialState) { + case StreamState::Pausing: + case StreamState::Paused: + return Result::OK; + case StreamState::Uninitialized: + case StreamState::Closed: + return Result::ErrorClosed; + default: + break; + } + + setState(StreamState::Pausing); + Result result = setPlayState_l(SL_PLAYSTATE_PAUSED); + if (result == Result::OK) { + // Note that OpenSL ES does NOT reset its millisecond position when OUTPUT is paused. + int64_t framesWritten = getFramesWritten(); + if (framesWritten >= 0) { + setFramesRead(framesWritten); + } + setState(StreamState::Paused); + } else { + setState(initialState); + } + return result; +} + +/** + * Flush/clear the queue buffers + */ +Result AudioOutputStreamOpenSLES::requestFlush() { + std::lock_guard lock(mLock); + return requestFlush_l(); +} + +Result AudioOutputStreamOpenSLES::requestFlush_l() { + LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__); + if (getState() == StreamState::Closed) { + return Result::ErrorClosed; + } + + Result result = Result::OK; + if (mPlayInterface == nullptr || mSimpleBufferQueueInterface == nullptr) { + result = Result::ErrorInvalidState; + } else { + SLresult slResult = (*mSimpleBufferQueueInterface)->Clear(mSimpleBufferQueueInterface); + if (slResult != SL_RESULT_SUCCESS){ + LOGW("Failed to clear buffer queue. OpenSLES error: %d", result); + result = Result::ErrorInternal; + } + } + return result; +} + +Result AudioOutputStreamOpenSLES::requestStop() { + std::lock_guard lock(mLock); + return requestStop_l(); +} + +Result AudioOutputStreamOpenSLES::requestStop_l() { + LOGD("AudioOutputStreamOpenSLES(): %s() called", __func__); + + StreamState initialState = getState(); + switch (initialState) { + case StreamState::Stopping: + case StreamState::Stopped: + return Result::OK; + case StreamState::Uninitialized: + case StreamState::Closed: + return Result::ErrorClosed; + default: + break; + } + + setState(StreamState::Stopping); + + Result result = setPlayState_l(SL_PLAYSTATE_STOPPED); + if (result == Result::OK) { + + // Also clear the buffer queue so the old data won't be played if the stream is restarted. + // Call the _l function that expects to already be under a lock. + if (requestFlush_l() != Result::OK) { + LOGW("Failed to flush the stream. Error %s", convertToText(flush())); + } + + mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped. + int64_t framesWritten = getFramesWritten(); + if (framesWritten >= 0) { + setFramesRead(framesWritten); + } + setState(StreamState::Stopped); + } else { + setState(initialState); + } + return result; +} + +void AudioOutputStreamOpenSLES::setFramesRead(int64_t framesRead) { + int64_t millisWritten = framesRead * kMillisPerSecond / getSampleRate(); + mPositionMillis.set(millisWritten); +} + +void AudioOutputStreamOpenSLES::updateFramesRead() { + if (usingFIFO()) { + AudioStreamBuffered::updateFramesRead(); + } else { + mFramesRead = getFramesProcessedByServer(); + } +} + +Result AudioOutputStreamOpenSLES::updateServiceFrameCounter() { + Result result = Result::OK; + // Avoid deadlock if another thread is trying to stop or close this stream + // and this is being called from a callback. + if (mLock.try_lock()) { + + if (mPlayInterface == nullptr) { + mLock.unlock(); + return Result::ErrorNull; + } + SLmillisecond msec = 0; + SLresult slResult = (*mPlayInterface)->GetPosition(mPlayInterface, &msec); + if (SL_RESULT_SUCCESS != slResult) { + LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult)); + // set result based on SLresult + result = Result::ErrorInternal; + } else { + mPositionMillis.update32(msec); + } + mLock.unlock(); + } + return result; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioOutputStreamOpenSLES_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioOutputStreamOpenSLES_android.h new file mode 100644 index 0000000..1faaefa --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioOutputStreamOpenSLES_android.h @@ -0,0 +1,80 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUDIO_OUTPUT_STREAM_OPENSL_ES_H_ +#define AUDIO_OUTPUT_STREAM_OPENSL_ES_H_ + + +#include +#include + +#include "oboe_oboe_Oboe_android.h" +#include "oboe_opensles_AudioStreamOpenSLES_android.h" + +namespace oboe { + +/** + * INTERNAL USE ONLY + */ +class AudioOutputStreamOpenSLES : public AudioStreamOpenSLES { +public: + AudioOutputStreamOpenSLES(); + explicit AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder); + + virtual ~AudioOutputStreamOpenSLES() = default; + + Result open() override; + Result close() override; + + Result requestStart() override; + Result requestPause() override; + Result requestFlush() override; + Result requestStop() override; + +protected: + Result requestPause_l(); + + void setFramesRead(int64_t framesRead); + + Result updateServiceFrameCounter() override; + + void updateFramesRead() override; + +private: + + SLuint32 channelCountToChannelMask(int chanCount) const; + + Result onAfterDestroy() override; + + Result requestFlush_l(); + + Result requestStop_l(); + + /** + * Set OpenSL ES PLAYSTATE. + * + * @param newState SL_PLAYSTATE_PAUSED, SL_PLAYSTATE_PLAYING, SL_PLAYSTATE_STOPPED + * @return + */ + Result setPlayState_l(SLuint32 newState); + + SLPlayItf mPlayInterface = nullptr; + +}; + +} // namespace oboe + +#endif //AUDIO_OUTPUT_STREAM_OPENSL_ES_H_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamBuffered_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamBuffered_android.cpp new file mode 100644 index 0000000..f1a9f2e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamBuffered_android.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "oboe_oboe_Oboe_android.h" + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_opensles_AudioStreamBuffered_android.h" +#include "oboe_common_AudioClock_android.h" + +namespace oboe { + +constexpr int kDefaultBurstsPerBuffer = 16; // arbitrary, allows dynamic latency tuning +constexpr int kMinBurstsPerBuffer = 4; // arbitrary, allows dynamic latency tuning +constexpr int kMinFramesPerBuffer = 48 * 32; // arbitrary + +/* + * AudioStream with a FifoBuffer + */ +AudioStreamBuffered::AudioStreamBuffered(const AudioStreamBuilder &builder) + : AudioStream(builder) { +} + +void AudioStreamBuffered::allocateFifo() { + // If the caller does not provide a callback use our own internal + // callback that reads data from the FIFO. + if (usingFIFO()) { + // FIFO is configured with the same format and channels as the stream. + int32_t capacityFrames = getBufferCapacityInFrames(); + if (capacityFrames == oboe::kUnspecified) { + capacityFrames = getFramesPerBurst() * kDefaultBurstsPerBuffer; + } else { + int32_t minFramesPerBufferByBursts = getFramesPerBurst() * kMinBurstsPerBuffer; + if (capacityFrames <= minFramesPerBufferByBursts) { + capacityFrames = minFramesPerBufferByBursts; + } else { + capacityFrames = std::max(kMinFramesPerBuffer, capacityFrames); + // round up to nearest burst + int32_t numBursts = (capacityFrames + getFramesPerBurst() - 1) + / getFramesPerBurst(); + capacityFrames = numBursts * getFramesPerBurst(); + } + } + + mFifoBuffer = std::make_unique(getBytesPerFrame(), capacityFrames); + mBufferCapacityInFrames = capacityFrames; + mBufferSizeInFrames = mBufferCapacityInFrames; + } +} + +void AudioStreamBuffered::updateFramesWritten() { + if (mFifoBuffer) { + mFramesWritten = static_cast(mFifoBuffer->getWriteCounter()); + } // or else it will get updated by processBufferCallback() +} + +void AudioStreamBuffered::updateFramesRead() { + if (mFifoBuffer) { + mFramesRead = static_cast(mFifoBuffer->getReadCounter()); + } // or else it will get updated by processBufferCallback() +} + +// This is called by the OpenSL ES callback to read or write the back end of the FIFO. +DataCallbackResult AudioStreamBuffered::onDefaultCallback(void *audioData, int numFrames) { + int32_t framesTransferred = 0; + + if (getDirection() == oboe::Direction::Output) { + // Read from the FIFO and write to audioData, clear part of buffer if not enough data. + framesTransferred = mFifoBuffer->readNow(audioData, numFrames); + } else { + // Read from audioData and write to the FIFO + framesTransferred = mFifoBuffer->write(audioData, numFrames); // There is no writeNow() + } + + if (framesTransferred < numFrames) { + LOGD("AudioStreamBuffered::%s(): xrun! framesTransferred = %d, numFrames = %d", + __func__, framesTransferred, numFrames); + // TODO If we do not allow FIFO to wrap then our timestamps will drift when there is an XRun! + incrementXRunCount(); + } + markCallbackTime(static_cast(numFrames)); // so foreground knows how long to wait. + return DataCallbackResult::Continue; +} + +void AudioStreamBuffered::markCallbackTime(int32_t numFrames) { + mLastBackgroundSize = numFrames; + mBackgroundRanAtNanoseconds = AudioClock::getNanoseconds(); +} + +int64_t AudioStreamBuffered::predictNextCallbackTime() { + if (mBackgroundRanAtNanoseconds == 0) { + return 0; + } + int64_t nanosPerBuffer = (kNanosPerSecond * mLastBackgroundSize) / getSampleRate(); + const int64_t margin = 200 * kNanosPerMicrosecond; // arbitrary delay so we wake up just after + return mBackgroundRanAtNanoseconds + nanosPerBuffer + margin; +} + +// Common code for read/write. +// @return Result::OK with frames read/written, or Result::Error* +ResultWithValue AudioStreamBuffered::transfer( + void *readBuffer, + const void *writeBuffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + // Validate arguments. + if (readBuffer != nullptr && writeBuffer != nullptr) { + LOGE("AudioStreamBuffered::%s(): both buffers are not NULL", __func__); + return ResultWithValue(Result::ErrorInternal); + } + if (getDirection() == Direction::Input && readBuffer == nullptr) { + LOGE("AudioStreamBuffered::%s(): readBuffer is NULL", __func__); + return ResultWithValue(Result::ErrorNull); + } + if (getDirection() == Direction::Output && writeBuffer == nullptr) { + LOGE("AudioStreamBuffered::%s(): writeBuffer is NULL", __func__); + return ResultWithValue(Result::ErrorNull); + } + if (numFrames < 0) { + LOGE("AudioStreamBuffered::%s(): numFrames is negative", __func__); + return ResultWithValue(Result::ErrorOutOfRange); + } else if (numFrames == 0) { + return ResultWithValue(numFrames); + } + if (timeoutNanoseconds < 0) { + LOGE("AudioStreamBuffered::%s(): timeoutNanoseconds is negative", __func__); + return ResultWithValue(Result::ErrorOutOfRange); + } + + int32_t result = 0; + uint8_t *readData = reinterpret_cast(readBuffer); + const uint8_t *writeData = reinterpret_cast(writeBuffer); + int32_t framesLeft = numFrames; + int64_t timeToQuit = 0; + bool repeat = true; + + // Calculate when to timeout. + if (timeoutNanoseconds > 0) { + timeToQuit = AudioClock::getNanoseconds() + timeoutNanoseconds; + } + + // Loop until we get the data, or we have an error, or we timeout. + do { + // read or write + if (getDirection() == Direction::Input) { + result = mFifoBuffer->read(readData, framesLeft); + if (result > 0) { + readData += mFifoBuffer->convertFramesToBytes(result); + framesLeft -= result; + } + } else { + // between zero and capacity + uint32_t fullFrames = mFifoBuffer->getFullFramesAvailable(); + // Do not write above threshold size. + int32_t emptyFrames = getBufferSizeInFrames() - static_cast(fullFrames); + int32_t framesToWrite = std::max(0, std::min(framesLeft, emptyFrames)); + result = mFifoBuffer->write(writeData, framesToWrite); + if (result > 0) { + writeData += mFifoBuffer->convertFramesToBytes(result); + framesLeft -= result; + } + } + + // If we need more data then sleep and try again. + if (framesLeft > 0 && result >= 0 && timeoutNanoseconds > 0) { + int64_t timeNow = AudioClock::getNanoseconds(); + if (timeNow >= timeToQuit) { + LOGE("AudioStreamBuffered::%s(): TIMEOUT", __func__); + repeat = false; // TIMEOUT + } else { + // Figure out how long to sleep. + int64_t sleepForNanos; + int64_t wakeTimeNanos = predictNextCallbackTime(); + if (wakeTimeNanos <= 0) { + // No estimate available. Sleep for one burst. + sleepForNanos = (getFramesPerBurst() * kNanosPerSecond) / getSampleRate(); + } else { + // Don't sleep past timeout. + if (wakeTimeNanos > timeToQuit) { + wakeTimeNanos = timeToQuit; + } + sleepForNanos = wakeTimeNanos - timeNow; + // Avoid rapid loop with no sleep. + const int64_t minSleepTime = kNanosPerMillisecond; // arbitrary + if (sleepForNanos < minSleepTime) { + sleepForNanos = minSleepTime; + } + } + + AudioClock::sleepForNanos(sleepForNanos); + } + + } else { + repeat = false; + } + } while(repeat); + + if (result < 0) { + return ResultWithValue(static_cast(result)); + } else { + int32_t framesWritten = numFrames - framesLeft; + return ResultWithValue(framesWritten); + } +} + +// Write to the FIFO so the callback can read from it. +ResultWithValue AudioStreamBuffered::write(const void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + if (getState() == StreamState::Closed){ + return ResultWithValue(Result::ErrorClosed); + } + + if (getDirection() == Direction::Input) { + return ResultWithValue(Result::ErrorUnavailable); // TODO review, better error code? + } + Result result = updateServiceFrameCounter(); + if (result != Result::OK) return ResultWithValue(static_cast(result)); + return transfer(nullptr, buffer, numFrames, timeoutNanoseconds); +} + +// Read data from the FIFO that was written by the callback. +ResultWithValue AudioStreamBuffered::read(void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) { + if (getState() == StreamState::Closed){ + return ResultWithValue(Result::ErrorClosed); + } + + if (getDirection() == Direction::Output) { + return ResultWithValue(Result::ErrorUnavailable); // TODO review, better error code? + } + Result result = updateServiceFrameCounter(); + if (result != Result::OK) return ResultWithValue(static_cast(result)); + return transfer(buffer, nullptr, numFrames, timeoutNanoseconds); +} + +// Only supported when we are not using a callback. +ResultWithValue AudioStreamBuffered::setBufferSizeInFrames(int32_t requestedFrames) +{ + if (getState() == StreamState::Closed){ + return ResultWithValue(Result::ErrorClosed); + } + + if (!mFifoBuffer) { + return ResultWithValue(Result::ErrorUnimplemented); + } + + if (requestedFrames > mFifoBuffer->getBufferCapacityInFrames()) { + requestedFrames = mFifoBuffer->getBufferCapacityInFrames(); + } else if (requestedFrames < getFramesPerBurst()) { + requestedFrames = getFramesPerBurst(); + } + mBufferSizeInFrames = requestedFrames; + return ResultWithValue(requestedFrames); +} + +int32_t AudioStreamBuffered::getBufferCapacityInFrames() const { + if (mFifoBuffer) { + return mFifoBuffer->getBufferCapacityInFrames(); + } else { + return AudioStream::getBufferCapacityInFrames(); + } +} + +bool AudioStreamBuffered::isXRunCountSupported() const { + // XRun count is only supported if we're using blocking I/O (not callbacks) + return (!isDataCallbackSpecified()); +} + +} // namespace oboe \ No newline at end of file diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamBuffered_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamBuffered_android.h new file mode 100644 index 0000000..0fc9651 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamBuffered_android.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_STREAM_BUFFERED_H +#define OBOE_STREAM_BUFFERED_H + +#include +#include +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_oboe_AudioStreamCallback_android.h" +#include "oboe_oboe_FifoBuffer_android.h" + +namespace oboe { + +// A stream that contains a FIFO buffer. +// This is used to implement blocking reads and writes. +class AudioStreamBuffered : public AudioStream { +public: + + AudioStreamBuffered(); + explicit AudioStreamBuffered(const AudioStreamBuilder &builder); + + void allocateFifo(); + + + ResultWithValue write(const void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) override; + + ResultWithValue read(void *buffer, + int32_t numFrames, + int64_t timeoutNanoseconds) override; + + ResultWithValue setBufferSizeInFrames(int32_t requestedFrames) override; + + int32_t getBufferCapacityInFrames() const override; + + ResultWithValue getXRunCount() override { + return ResultWithValue(mXRunCount); + } + + bool isXRunCountSupported() const override; + +protected: + + DataCallbackResult onDefaultCallback(void *audioData, int numFrames) override; + + // If there is no callback then we need a FIFO between the App and OpenSL ES. + bool usingFIFO() const { return !isDataCallbackSpecified(); } + + virtual Result updateServiceFrameCounter() = 0; + + void updateFramesRead() override; + void updateFramesWritten() override; + +private: + + int64_t predictNextCallbackTime(); + + void markCallbackTime(int32_t numFrames); + + // Read or write to the FIFO. + // Only pass one pointer and set the other to nullptr. + ResultWithValue transfer(void *readBuffer, + const void *writeBuffer, + int32_t numFrames, + int64_t timeoutNanoseconds); + + void incrementXRunCount() { + ++mXRunCount; + } + + std::unique_ptr mFifoBuffer{}; + + int64_t mBackgroundRanAtNanoseconds = 0; + int32_t mLastBackgroundSize = 0; + int32_t mXRunCount = 0; +}; + +} // namespace oboe + +#endif //OBOE_STREAM_BUFFERED_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamOpenSLES_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamOpenSLES_android.cpp new file mode 100644 index 0000000..60adf8d --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamOpenSLES_android.cpp @@ -0,0 +1,473 @@ +/* Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +#include +#include +#include "oboe_oboe_AudioStream_android.h" +#include "oboe_common_AudioClock_android.h" + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_oboe_AudioStreamBuilder_android.h" +#include "oboe_opensles_AudioStreamOpenSLES_android.h" +#include "oboe_opensles_OpenSLESUtilities_android.h" + +using namespace oboe; + +AudioStreamOpenSLES::AudioStreamOpenSLES(const AudioStreamBuilder &builder) + : AudioStreamBuffered(builder) { + // OpenSL ES does not support device IDs. So overwrite value from builder. + mDeviceId = kUnspecified; + // OpenSL ES does not support session IDs. So overwrite value from builder. + mSessionId = SessionId::None; +} + +static constexpr int32_t kHighLatencyBufferSizeMillis = 20; // typical Android period +static constexpr SLuint32 kAudioChannelCountMax = 30; // TODO Why 30? +static constexpr SLuint32 SL_ANDROID_UNKNOWN_CHANNELMASK = 0; // Matches name used internally. + +SLuint32 AudioStreamOpenSLES::channelCountToChannelMaskDefault(int channelCount) const { + if (channelCount > kAudioChannelCountMax) { + return SL_ANDROID_UNKNOWN_CHANNELMASK; + } + + SLuint32 bitfield = (1 << channelCount) - 1; + + // Check for OS at run-time. + if(getSdkVersion() >= __ANDROID_API_N__) { + return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield); + } + + // Indexed channels masks were added in N. + // For before N, the best we can do is use a positional channel mask. + return bitfield; +} + +static bool s_isLittleEndian() { + static uint32_t value = 1; + return (*reinterpret_cast(&value) == 1); // Does address point to LSB? +} + +SLuint32 AudioStreamOpenSLES::getDefaultByteOrder() { + return s_isLittleEndian() ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; +} + +Result AudioStreamOpenSLES::open() { + + LOGI("AudioStreamOpenSLES::open() chans=%d, rate=%d", mChannelCount, mSampleRate); + + // OpenSL ES only supports I16 and Float + if (mFormat != AudioFormat::I16 && mFormat != AudioFormat::Float) { + LOGW("%s() Android's OpenSL ES implementation only supports I16 and Float. Format: %d", + __func__, mFormat); + return Result::ErrorInvalidFormat; + } + + SLresult result = EngineOpenSLES::getInstance().open(); + if (SL_RESULT_SUCCESS != result) { + return Result::ErrorInternal; + } + + Result oboeResult = AudioStreamBuffered::open(); + if (oboeResult != Result::OK) { + EngineOpenSLES::getInstance().close(); + return oboeResult; + } + // Convert to defaults if UNSPECIFIED + if (mSampleRate == kUnspecified) { + mSampleRate = DefaultStreamValues::SampleRate; + } + if (mChannelCount == kUnspecified) { + mChannelCount = DefaultStreamValues::ChannelCount; + } + if (mContentType == kUnspecified) { + mContentType = ContentType::Music; + } + if (static_cast(mUsage) == kUnspecified) { + mUsage = Usage::Media; + } + + mSharingMode = SharingMode::Shared; + + return Result::OK; +} + + +SLresult AudioStreamOpenSLES::finishCommonOpen(SLAndroidConfigurationItf configItf) { + SLresult result = registerBufferQueueCallback(); + if (SL_RESULT_SUCCESS != result) { + return result; + } + + result = updateStreamParameters(configItf); + if (SL_RESULT_SUCCESS != result) { + return result; + } + + Result oboeResult = configureBufferSizes(mSampleRate); + if (Result::OK != oboeResult) { + return (SLresult) oboeResult; + } + + allocateFifo(); + + calculateDefaultDelayBeforeCloseMillis(); + + return SL_RESULT_SUCCESS; +} + +static int32_t roundUpDivideByN(int32_t x, int32_t n) { + return (x + n - 1) / n; +} + +int32_t AudioStreamOpenSLES::calculateOptimalBufferQueueLength() { + int32_t queueLength = kBufferQueueLengthDefault; + int32_t likelyFramesPerBurst = estimateNativeFramesPerBurst(); + int32_t minCapacity = mBufferCapacityInFrames; // specified by app or zero + // The buffer capacity needs to be at least twice the size of the requested callbackSize + // so that we can have double buffering. + minCapacity = std::max(minCapacity, kDoubleBufferCount * mFramesPerCallback); + if (minCapacity > 0) { + int32_t queueLengthFromCapacity = roundUpDivideByN(minCapacity, likelyFramesPerBurst); + queueLength = std::max(queueLength, queueLengthFromCapacity); + } + queueLength = std::min(queueLength, kBufferQueueLengthMax); // clip to max + // TODO Investigate the effect of queueLength on latency for normal streams. (not low latency) + return queueLength; +} + +/** + * The best information we have is if DefaultStreamValues::FramesPerBurst + * was set by the app based on AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER. + * Without that we just have to guess. + * @return + */ +int32_t AudioStreamOpenSLES::estimateNativeFramesPerBurst() { + int32_t framesPerBurst = DefaultStreamValues::FramesPerBurst; + LOGD("AudioStreamOpenSLES:%s() DefaultStreamValues::FramesPerBurst = %d", + __func__, DefaultStreamValues::FramesPerBurst); + framesPerBurst = std::max(framesPerBurst, 16); + // Calculate the size of a fixed duration high latency buffer based on sample rate. + // Estimate sample based on default options in order of priority. + int32_t sampleRate = 48000; + sampleRate = (DefaultStreamValues::SampleRate > 0) + ? DefaultStreamValues::SampleRate : sampleRate; + sampleRate = (mSampleRate > 0) ? mSampleRate : sampleRate; + int32_t framesPerHighLatencyBuffer = + (kHighLatencyBufferSizeMillis * sampleRate) / kMillisPerSecond; + // For high latency streams, use a larger buffer size. + // Performance Mode support was added in N_MR1 (7.1) + if (getSdkVersion() >= __ANDROID_API_N_MR1__ + && mPerformanceMode != PerformanceMode::LowLatency + && framesPerBurst < framesPerHighLatencyBuffer) { + // Find a multiple of framesPerBurst >= framesPerHighLatencyBuffer. + int32_t numBursts = roundUpDivideByN(framesPerHighLatencyBuffer, framesPerBurst); + framesPerBurst *= numBursts; + LOGD("AudioStreamOpenSLES:%s() NOT low latency, numBursts = %d, mSampleRate = %d, set framesPerBurst = %d", + __func__, numBursts, mSampleRate, framesPerBurst); + } + return framesPerBurst; +} + +Result AudioStreamOpenSLES::configureBufferSizes(int32_t sampleRate) { + LOGD("AudioStreamOpenSLES:%s(%d) initial mFramesPerBurst = %d, mFramesPerCallback = %d", + __func__, mSampleRate, mFramesPerBurst, mFramesPerCallback); + mFramesPerBurst = estimateNativeFramesPerBurst(); + mFramesPerCallback = (mFramesPerCallback > 0) ? mFramesPerCallback : mFramesPerBurst; + LOGD("AudioStreamOpenSLES:%s(%d) final mFramesPerBurst = %d, mFramesPerCallback = %d", + __func__, mSampleRate, mFramesPerBurst, mFramesPerCallback); + + mBytesPerCallback = mFramesPerCallback * getBytesPerFrame(); + if (mBytesPerCallback <= 0) { + LOGE("AudioStreamOpenSLES::open() bytesPerCallback < 0 = %d, bad format?", + mBytesPerCallback); + return Result::ErrorInvalidFormat; // causing bytesPerFrame == 0 + } + + for (int i = 0; i < mBufferQueueLength; ++i) { + mCallbackBuffer[i] = std::make_unique(mBytesPerCallback); + } + + if (!usingFIFO()) { + mBufferCapacityInFrames = mFramesPerBurst * mBufferQueueLength; + // Check for overflow. + if (mBufferCapacityInFrames <= 0) { + mBufferCapacityInFrames = 0; + LOGE("AudioStreamOpenSLES::open() numeric overflow because mFramesPerBurst = %d", + mFramesPerBurst); + return Result::ErrorOutOfRange; + } + mBufferSizeInFrames = mBufferCapacityInFrames; + } + + return Result::OK; +} + +SLuint32 AudioStreamOpenSLES::convertPerformanceMode(PerformanceMode oboeMode) const { + SLuint32 openslMode = SL_ANDROID_PERFORMANCE_NONE; + switch(oboeMode) { + case PerformanceMode::None: + openslMode = SL_ANDROID_PERFORMANCE_NONE; + break; + case PerformanceMode::LowLatency: + openslMode = (getSessionId() == SessionId::None) ? SL_ANDROID_PERFORMANCE_LATENCY : SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS; + break; + case PerformanceMode::PowerSaving: + openslMode = SL_ANDROID_PERFORMANCE_POWER_SAVING; + break; + default: + break; + } + return openslMode; +} + +PerformanceMode AudioStreamOpenSLES::convertPerformanceMode(SLuint32 openslMode) const { + PerformanceMode oboeMode = PerformanceMode::None; + switch(openslMode) { + case SL_ANDROID_PERFORMANCE_NONE: + oboeMode = PerformanceMode::None; + break; + case SL_ANDROID_PERFORMANCE_LATENCY: + case SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS: + oboeMode = PerformanceMode::LowLatency; + break; + case SL_ANDROID_PERFORMANCE_POWER_SAVING: + oboeMode = PerformanceMode::PowerSaving; + break; + default: + break; + } + return oboeMode; +} + +void AudioStreamOpenSLES::logUnsupportedAttributes() { + // Log unsupported attributes + // only report if changed from the default + + // Device ID + if (mDeviceId != kUnspecified) { + LOGW("Device ID [AudioStreamBuilder::setDeviceId()] " + "is not supported on OpenSLES streams."); + } + // Sharing Mode + if (mSharingMode != SharingMode::Shared) { + LOGW("SharingMode [AudioStreamBuilder::setSharingMode()] " + "is not supported on OpenSLES streams."); + } + // Performance Mode + int sdkVersion = getSdkVersion(); + if (mPerformanceMode != PerformanceMode::None && sdkVersion < __ANDROID_API_N_MR1__) { + LOGW("PerformanceMode [AudioStreamBuilder::setPerformanceMode()] " + "is not supported on OpenSLES streams running on pre-Android N-MR1 versions."); + } + // Content Type + if (mContentType != ContentType::Music) { + LOGW("ContentType [AudioStreamBuilder::setContentType()] " + "is not supported on OpenSLES streams."); + } + + // Session Id + if (mSessionId != SessionId::None) { + LOGW("SessionId [AudioStreamBuilder::setSessionId()] " + "is not supported on OpenSLES streams."); + } +} + +SLresult AudioStreamOpenSLES::configurePerformanceMode(SLAndroidConfigurationItf configItf) { + + if (configItf == nullptr) { + LOGW("%s() called with NULL configuration", __func__); + mPerformanceMode = PerformanceMode::None; + return SL_RESULT_INTERNAL_ERROR; + } + if (getSdkVersion() < __ANDROID_API_N_MR1__) { + LOGW("%s() not supported until N_MR1", __func__); + mPerformanceMode = PerformanceMode::None; + return SL_RESULT_SUCCESS; + } + + SLresult result = SL_RESULT_SUCCESS; + SLuint32 performanceMode = convertPerformanceMode(getPerformanceMode()); + result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, + &performanceMode, sizeof(performanceMode)); + if (SL_RESULT_SUCCESS != result) { + LOGW("SetConfiguration(PERFORMANCE_MODE, SL %u) returned %s", + performanceMode, getSLErrStr(result)); + mPerformanceMode = PerformanceMode::None; + } + + return result; +} + +SLresult AudioStreamOpenSLES::updateStreamParameters(SLAndroidConfigurationItf configItf) { + SLresult result = SL_RESULT_SUCCESS; + if(getSdkVersion() >= __ANDROID_API_N_MR1__ && configItf != nullptr) { + SLuint32 performanceMode = 0; + SLuint32 performanceModeSize = sizeof(performanceMode); + result = (*configItf)->GetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, + &performanceModeSize, &performanceMode); + // A bug in GetConfiguration() before P caused a wrong result code to be returned. + if (getSdkVersion() <= __ANDROID_API_O_MR1__) { + result = SL_RESULT_SUCCESS; // Ignore actual result before P. + } + + if (SL_RESULT_SUCCESS != result) { + LOGW("GetConfiguration(SL_ANDROID_KEY_PERFORMANCE_MODE) returned %d", result); + mPerformanceMode = PerformanceMode::None; // If we can't query it then assume None. + } else { + mPerformanceMode = convertPerformanceMode(performanceMode); // convert SL to Oboe mode + } + } else { + mPerformanceMode = PerformanceMode::None; // If we can't query it then assume None. + } + return result; +} + +// This is called under mLock. +Result AudioStreamOpenSLES::close_l() { + if (mState == StreamState::Closed) { + return Result::ErrorClosed; + } + + AudioStreamBuffered::close(); + + onBeforeDestroy(); + + if (mObjectInterface != nullptr) { + (*mObjectInterface)->Destroy(mObjectInterface); + mObjectInterface = nullptr; + } + + onAfterDestroy(); + + mSimpleBufferQueueInterface = nullptr; + EngineOpenSLES::getInstance().close(); + + setState(StreamState::Closed); + return Result::OK; +} + +SLresult AudioStreamOpenSLES::enqueueCallbackBuffer(SLAndroidSimpleBufferQueueItf bq) { + SLresult result = (*bq)->Enqueue( + bq, mCallbackBuffer[mCallbackBufferIndex].get(), mBytesPerCallback); + mCallbackBufferIndex = (mCallbackBufferIndex + 1) % mBufferQueueLength; + return result; +} + +int32_t AudioStreamOpenSLES::getBufferDepth(SLAndroidSimpleBufferQueueItf bq) { + SLAndroidSimpleBufferQueueState queueState; + SLresult result = (*bq)->GetState(bq, &queueState); + return (result == SL_RESULT_SUCCESS) ? queueState.count : -1; +} + +bool AudioStreamOpenSLES::processBufferCallback(SLAndroidSimpleBufferQueueItf bq) { + bool shouldStopStream = false; + // Ask the app callback to process the buffer. + DataCallbackResult result = + fireDataCallback(mCallbackBuffer[mCallbackBufferIndex].get(), mFramesPerCallback); + if (result == DataCallbackResult::Continue) { + // Pass the buffer to OpenSLES. + SLresult enqueueResult = enqueueCallbackBuffer(bq); + if (enqueueResult != SL_RESULT_SUCCESS) { + LOGE("%s() returned %d", __func__, enqueueResult); + shouldStopStream = true; + } + // Update Oboe client position with frames handled by the callback. + if (getDirection() == Direction::Input) { + mFramesRead += mFramesPerCallback; + } else { + mFramesWritten += mFramesPerCallback; + } + } else if (result == DataCallbackResult::Stop) { + LOGD("Oboe callback returned Stop"); + shouldStopStream = true; + } else { + LOGW("Oboe callback returned unexpected value = %d", result); + shouldStopStream = true; + } + if (shouldStopStream) { + mCallbackBufferIndex = 0; + } + return shouldStopStream; +} + +// This callback handler is called every time a buffer has been processed by OpenSL ES. +static void bqCallbackGlue(SLAndroidSimpleBufferQueueItf bq, void *context) { + bool shouldStopStream = (reinterpret_cast(context)) + ->processBufferCallback(bq); + if (shouldStopStream) { + (reinterpret_cast(context))->requestStop(); + } +} + +SLresult AudioStreamOpenSLES::registerBufferQueueCallback() { + // The BufferQueue + SLresult result = (*mObjectInterface)->GetInterface(mObjectInterface, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &mSimpleBufferQueueInterface); + if (SL_RESULT_SUCCESS != result) { + LOGE("get buffer queue interface:%p result:%s", + mSimpleBufferQueueInterface, + getSLErrStr(result)); + } else { + // Register the BufferQueue callback + result = (*mSimpleBufferQueueInterface)->RegisterCallback(mSimpleBufferQueueInterface, + bqCallbackGlue, this); + if (SL_RESULT_SUCCESS != result) { + LOGE("RegisterCallback result:%s", getSLErrStr(result)); + } + } + return result; +} + +int64_t AudioStreamOpenSLES::getFramesProcessedByServer() { + updateServiceFrameCounter(); + int64_t millis64 = mPositionMillis.get(); + int64_t framesProcessed = millis64 * getSampleRate() / kMillisPerSecond; + return framesProcessed; +} + +Result AudioStreamOpenSLES::waitForStateChange(StreamState currentState, + StreamState *nextState, + int64_t timeoutNanoseconds) { + Result oboeResult = Result::ErrorTimeout; + int64_t sleepTimeNanos = 20 * kNanosPerMillisecond; // arbitrary + int64_t timeLeftNanos = timeoutNanoseconds; + + while (true) { + const StreamState state = getState(); // this does not require a lock + if (nextState != nullptr) { + *nextState = state; + } + if (currentState != state) { // state changed? + oboeResult = Result::OK; + break; + } + + // Did we timeout or did user ask for non-blocking? + if (timeLeftNanos <= 0) { + break; + } + + if (sleepTimeNanos > timeLeftNanos){ + sleepTimeNanos = timeLeftNanos; + } + AudioClock::sleepForNanos(sleepTimeNanos); + timeLeftNanos -= sleepTimeNanos; + } + + return oboeResult; +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamOpenSLES_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamOpenSLES_android.h new file mode 100644 index 0000000..541d045 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_AudioStreamOpenSLES_android.h @@ -0,0 +1,148 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_AUDIO_STREAM_OPENSL_ES_H_ +#define OBOE_AUDIO_STREAM_OPENSL_ES_H_ + +#include + +#include +#include + +#include "oboe_oboe_Oboe_android.h" +#include "oboe_common_MonotonicCounter_android.h" +#include "oboe_opensles_AudioStreamBuffered_android.h" +#include "oboe_opensles_EngineOpenSLES_android.h" + +namespace oboe { + +constexpr int kBitsPerByte = 8; +constexpr int kBufferQueueLengthDefault = 2; // double buffered for callbacks +constexpr int kBufferQueueLengthMax = 8; // AudioFlinger won't use more than 8 + +/** + * INTERNAL USE ONLY + * + * A stream that wraps OpenSL ES. + * + * Do not instantiate this class directly. + * Use an OboeStreamBuilder to create one. + */ + +class AudioStreamOpenSLES : public AudioStreamBuffered { +public: + + AudioStreamOpenSLES(); + explicit AudioStreamOpenSLES(const AudioStreamBuilder &builder); + + virtual ~AudioStreamOpenSLES() = default; + + virtual Result open() override; + + /** + * Query the current state, eg. OBOE_STREAM_STATE_PAUSING + * + * @return state or a negative error. + */ + StreamState getState() override { return mState.load(); } + + AudioApi getAudioApi() const override { + return AudioApi::OpenSLES; + } + + /** + * Process next OpenSL ES buffer. + * Called by by OpenSL ES framework. + * + * This is public, but don't call it directly. + * + * @return whether the current stream should be stopped. + */ + bool processBufferCallback(SLAndroidSimpleBufferQueueItf bq); + + Result waitForStateChange(StreamState currentState, + StreamState *nextState, + int64_t timeoutNanoseconds) override; + +protected: + + /** + * Finish setting up the stream. Common for INPUT and OUTPUT. + * + * @param configItf + * @return SL_RESULT_SUCCESS if OK. + */ + SLresult finishCommonOpen(SLAndroidConfigurationItf configItf); + + // This must be called under mLock. + Result close_l(); + + SLuint32 channelCountToChannelMaskDefault(int channelCount) const; + + virtual Result onBeforeDestroy() { return Result::OK; } + virtual Result onAfterDestroy() { return Result::OK; } + + static SLuint32 getDefaultByteOrder(); + + int32_t getBufferDepth(SLAndroidSimpleBufferQueueItf bq); + + int32_t calculateOptimalBufferQueueLength(); + int32_t estimateNativeFramesPerBurst(); + + SLresult enqueueCallbackBuffer(SLAndroidSimpleBufferQueueItf bq); + + SLresult configurePerformanceMode(SLAndroidConfigurationItf configItf); + + PerformanceMode convertPerformanceMode(SLuint32 openslMode) const; + SLuint32 convertPerformanceMode(PerformanceMode oboeMode) const; + + void logUnsupportedAttributes(); + + /** + * Internal use only. + * Use this instead of directly setting the internal state variable. + */ + void setState(StreamState state) { + mState.store(state); + } + + int64_t getFramesProcessedByServer(); + + // OpenSLES stuff + SLObjectItf mObjectInterface = nullptr; + SLAndroidSimpleBufferQueueItf mSimpleBufferQueueInterface = nullptr; + int mBufferQueueLength = 0; + + int32_t mBytesPerCallback = oboe::kUnspecified; + MonotonicCounter mPositionMillis; // for tracking OpenSL ES service position + +private: + + constexpr static int kDoubleBufferCount = 2; + + SLresult registerBufferQueueCallback(); + SLresult updateStreamParameters(SLAndroidConfigurationItf configItf); + Result configureBufferSizes(int32_t sampleRate); + + std::unique_ptr mCallbackBuffer[kBufferQueueLengthMax]; + int mCallbackBufferIndex = 0; + std::atomic mState{StreamState::Uninitialized}; + +}; + +} // namespace oboe + +#endif // OBOE_AUDIO_STREAM_OPENSL_ES_H_ diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_EngineOpenSLES_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_EngineOpenSLES_android.cpp new file mode 100644 index 0000000..93a0e7e --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_EngineOpenSLES_android.cpp @@ -0,0 +1,141 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "oboe_common_OboeDebug_android.h" +#include "oboe_opensles_EngineOpenSLES_android.h" +#include "oboe_opensles_OpenSLESUtilities_android.h" + +using namespace oboe; + +// OpenSL ES is deprecated in SDK 30. +// So we use custom dynamic linking to access the library. +#define LIB_OPENSLES_NAME "libOpenSLES.so" +typedef SLresult (*prototype_slCreateEngine)( + SLObjectItf *pEngine, + SLuint32 numOptions, + const SLEngineOption *pEngineOptions, + SLuint32 numInterfaces, + const SLInterfaceID *pInterfaceIds, + const SLboolean *pInterfaceRequired +); +static prototype_slCreateEngine gFunction_slCreateEngine = nullptr; +static void *gLibOpenSlesLibraryHandle = nullptr; + +// Load the OpenSL ES library and the one primary entry point. +// @return true if linked OK +static bool linkOpenSLES() { + if (gLibOpenSlesLibraryHandle == nullptr && gFunction_slCreateEngine == nullptr) { + // Use RTLD_NOW to avoid the unpredictable behavior that RTLD_LAZY can cause. + // Also resolving all the links now will prevent a run-time penalty later. + gLibOpenSlesLibraryHandle = dlopen(LIB_OPENSLES_NAME, RTLD_NOW); + if (gLibOpenSlesLibraryHandle == nullptr) { + LOGE("linkOpenSLES() could not find " LIB_OPENSLES_NAME); + } else { + gFunction_slCreateEngine = (prototype_slCreateEngine) dlsym( + gLibOpenSlesLibraryHandle, + "slCreateEngine"); + LOGD("linkOpenSLES(): dlsym(%s) returned %p", "slCreateEngine", + gFunction_slCreateEngine); + } + } + return gFunction_slCreateEngine != nullptr; +} + +EngineOpenSLES &EngineOpenSLES::getInstance() { + static EngineOpenSLES sInstance; + return sInstance; +} + +SLresult EngineOpenSLES::open() { + std::lock_guard lock(mLock); + + SLresult result = SL_RESULT_SUCCESS; + if (mOpenCount++ == 0) { + // load the library and link to it + if (!linkOpenSLES()) { + result = SL_RESULT_FEATURE_UNSUPPORTED; + goto error; + }; + + // create engine + result = (*gFunction_slCreateEngine)(&mEngineObject, 0, NULL, 0, NULL, NULL); + if (SL_RESULT_SUCCESS != result) { + LOGE("EngineOpenSLES - slCreateEngine() result:%s", getSLErrStr(result)); + goto error; + } + + // realize the engine + result = (*mEngineObject)->Realize(mEngineObject, SL_BOOLEAN_FALSE); + if (SL_RESULT_SUCCESS != result) { + LOGE("EngineOpenSLES - Realize() engine result:%s", getSLErrStr(result)); + goto error; + } + + // get the engine interface, which is needed in order to create other objects + result = (*mEngineObject)->GetInterface(mEngineObject, SL_IID_ENGINE, &mEngineInterface); + if (SL_RESULT_SUCCESS != result) { + LOGE("EngineOpenSLES - GetInterface() engine result:%s", getSLErrStr(result)); + goto error; + } + } + + return result; + +error: + close(); + return result; +} + +void EngineOpenSLES::close() { + std::lock_guard lock(mLock); + if (--mOpenCount == 0) { + if (mEngineObject != nullptr) { + (*mEngineObject)->Destroy(mEngineObject); + mEngineObject = nullptr; + mEngineInterface = nullptr; + } + } +} + +SLresult EngineOpenSLES::createOutputMix(SLObjectItf *objectItf) { + return (*mEngineInterface)->CreateOutputMix(mEngineInterface, objectItf, 0, 0, 0); +} + +SLresult EngineOpenSLES::createAudioPlayer(SLObjectItf *objectItf, + SLDataSource *audioSource, + SLDataSink *audioSink) { + + const SLInterfaceID ids[] = {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION}; + const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + + return (*mEngineInterface)->CreateAudioPlayer(mEngineInterface, objectItf, audioSource, + audioSink, + sizeof(ids) / sizeof(ids[0]), ids, reqs); +} + +SLresult EngineOpenSLES::createAudioRecorder(SLObjectItf *objectItf, + SLDataSource *audioSource, + SLDataSink *audioSink) { + + const SLInterfaceID ids[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; + const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + + return (*mEngineInterface)->CreateAudioRecorder(mEngineInterface, objectItf, audioSource, + audioSink, + sizeof(ids) / sizeof(ids[0]), ids, reqs); +} + diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_EngineOpenSLES_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_EngineOpenSLES_android.h new file mode 100644 index 0000000..3d238a8 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_EngineOpenSLES_android.h @@ -0,0 +1,65 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_ENGINE_OPENSLES_H +#define OBOE_ENGINE_OPENSLES_H + +#include +#include + +#include +#include + +namespace oboe { + +/** + * INTERNAL USE ONLY + */ +class EngineOpenSLES { +public: + static EngineOpenSLES &getInstance(); + + SLresult open(); + + void close(); + + SLresult createOutputMix(SLObjectItf *objectItf); + + SLresult createAudioPlayer(SLObjectItf *objectItf, + SLDataSource *audioSource, + SLDataSink *audioSink); + SLresult createAudioRecorder(SLObjectItf *objectItf, + SLDataSource *audioSource, + SLDataSink *audioSink); + +private: + // Make this a safe Singleton + EngineOpenSLES()= default; + ~EngineOpenSLES()= default; + EngineOpenSLES(const EngineOpenSLES&)= delete; + EngineOpenSLES& operator=(const EngineOpenSLES&)= delete; + + std::mutex mLock; + int32_t mOpenCount = 0; + + SLObjectItf mEngineObject = nullptr; + SLEngineItf mEngineInterface = nullptr; +}; + +} // namespace oboe + + +#endif //OBOE_ENGINE_OPENSLES_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OpenSLESUtilities_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OpenSLESUtilities_android.cpp new file mode 100644 index 0000000..e0e701a --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OpenSLESUtilities_android.cpp @@ -0,0 +1,95 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "oboe_opensles_OpenSLESUtilities_android.h" + +namespace oboe { + +/* + * OSLES Helpers + */ + +const char *getSLErrStr(SLresult code) { + switch (code) { + case SL_RESULT_SUCCESS: + return "SL_RESULT_SUCCESS"; + case SL_RESULT_PRECONDITIONS_VIOLATED: + return "SL_RESULT_PRECONDITIONS_VIOLATED"; + case SL_RESULT_PARAMETER_INVALID: + return "SL_RESULT_PARAMETER_INVALID"; + case SL_RESULT_MEMORY_FAILURE: + return "SL_RESULT_MEMORY_FAILURE"; + case SL_RESULT_RESOURCE_ERROR: + return "SL_RESULT_RESOURCE_ERROR"; + case SL_RESULT_RESOURCE_LOST: + return "SL_RESULT_RESOURCE_LOST"; + case SL_RESULT_IO_ERROR: + return "SL_RESULT_IO_ERROR"; + case SL_RESULT_BUFFER_INSUFFICIENT: + return "SL_RESULT_BUFFER_INSUFFICIENT"; + case SL_RESULT_CONTENT_CORRUPTED: + return "SL_RESULT_CONTENT_CORRUPTED"; + case SL_RESULT_CONTENT_UNSUPPORTED: + return "SL_RESULT_CONTENT_UNSUPPORTED"; + case SL_RESULT_CONTENT_NOT_FOUND: + return "SL_RESULT_CONTENT_NOT_FOUND"; + case SL_RESULT_PERMISSION_DENIED: + return "SL_RESULT_PERMISSION_DENIED"; + case SL_RESULT_FEATURE_UNSUPPORTED: + return "SL_RESULT_FEATURE_UNSUPPORTED"; + case SL_RESULT_INTERNAL_ERROR: + return "SL_RESULT_INTERNAL_ERROR"; + case SL_RESULT_UNKNOWN_ERROR: + return "SL_RESULT_UNKNOWN_ERROR"; + case SL_RESULT_OPERATION_ABORTED: + return "SL_RESULT_OPERATION_ABORTED"; + case SL_RESULT_CONTROL_LOST: + return "SL_RESULT_CONTROL_LOST"; + default: + return "Unknown SL error"; + } +} + +SLAndroidDataFormat_PCM_EX OpenSLES_createExtendedFormat( + SLDataFormat_PCM format, SLuint32 representation) { + SLAndroidDataFormat_PCM_EX format_pcm_ex; + format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; + format_pcm_ex.numChannels = format.numChannels; + format_pcm_ex.sampleRate = format.samplesPerSec; + format_pcm_ex.bitsPerSample = format.bitsPerSample; + format_pcm_ex.containerSize = format.containerSize; + format_pcm_ex.channelMask = format.channelMask; + format_pcm_ex.endianness = format.endianness; + format_pcm_ex.representation = representation; + return format_pcm_ex; +} + +SLuint32 OpenSLES_ConvertFormatToRepresentation(AudioFormat format) { + switch(format) { + case AudioFormat::I16: + return SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT; + case AudioFormat::Float: + return SL_ANDROID_PCM_REPRESENTATION_FLOAT; + case AudioFormat::I24: + case AudioFormat::I32: + case AudioFormat::Invalid: + case AudioFormat::Unspecified: + default: + return 0; + } +} + +} // namespace oboe diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OpenSLESUtilities_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OpenSLESUtilities_android.h new file mode 100644 index 0000000..7736d35 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OpenSLESUtilities_android.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_OPENSLES_OPENSLESUTILITIES_H +#define OBOE_OPENSLES_OPENSLESUTILITIES_H + +#include +#include "oboe_oboe_Oboe_android.h" + +namespace oboe { + +const char *getSLErrStr(SLresult code); + +/** + * Creates an extended PCM format from the supplied format and data representation. This method + * should only be called on Android devices with API level 21+. API 21 introduced the + * SLAndroidDataFormat_PCM_EX object which allows audio samples to be represented using + * single precision floating-point. + * + * @param format + * @param representation + * @return the extended PCM format + */ +SLAndroidDataFormat_PCM_EX OpenSLES_createExtendedFormat(SLDataFormat_PCM format, + SLuint32 representation); + +SLuint32 OpenSLES_ConvertFormatToRepresentation(AudioFormat format); + +} // namespace oboe + +#endif //OBOE_OPENSLES_OPENSLESUTILITIES_H diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OutputMixerOpenSLES_android.cpp b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OutputMixerOpenSLES_android.cpp new file mode 100644 index 0000000..b4c9e62 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OutputMixerOpenSLES_android.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "oboe_common_OboeDebug_android.h" +#include "oboe_opensles_EngineOpenSLES_android.h" +#include "oboe_opensles_OpenSLESUtilities_android.h" +#include "oboe_opensles_OutputMixerOpenSLES_android.h" + +using namespace oboe; + +OutputMixerOpenSL &OutputMixerOpenSL::getInstance() { + static OutputMixerOpenSL sInstance; + return sInstance; +} + +SLresult OutputMixerOpenSL::open() { + std::lock_guard lock(mLock); + + SLresult result = SL_RESULT_SUCCESS; + if (mOpenCount++ == 0) { + // get the output mixer + result = EngineOpenSLES::getInstance().createOutputMix(&mOutputMixObject); + if (SL_RESULT_SUCCESS != result) { + LOGE("OutputMixerOpenSL() - createOutputMix() result:%s", getSLErrStr(result)); + goto error; + } + + // realize the output mix + result = (*mOutputMixObject)->Realize(mOutputMixObject, SL_BOOLEAN_FALSE); + if (SL_RESULT_SUCCESS != result) { + LOGE("OutputMixerOpenSL() - Realize() mOutputMixObject result:%s", getSLErrStr(result)); + goto error; + } + } + + return result; + +error: + close(); + return result; +} + +void OutputMixerOpenSL::close() { + std::lock_guard lock(mLock); + + if (--mOpenCount == 0) { + // destroy output mix object, and invalidate all associated interfaces + if (mOutputMixObject != nullptr) { + (*mOutputMixObject)->Destroy(mOutputMixObject); + mOutputMixObject = nullptr; + } + } +} + +SLresult OutputMixerOpenSL::createAudioPlayer(SLObjectItf *objectItf, + SLDataSource *audioSource) { + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, mOutputMixObject}; + SLDataSink audioSink = {&loc_outmix, NULL}; + return EngineOpenSLES::getInstance().createAudioPlayer(objectItf, audioSource, &audioSink); +} diff --git a/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OutputMixerOpenSLES_android.h b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OutputMixerOpenSLES_android.h new file mode 100644 index 0000000..813fd01 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/internal/oboe/oboe_opensles_OutputMixerOpenSLES_android.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OBOE_OUTPUT_MIXER_OPENSLES_H +#define OBOE_OUTPUT_MIXER_OPENSLES_H + +#include +#include + +#include +#include + +namespace oboe { + +/** + * INTERNAL USE ONLY + */ + +class OutputMixerOpenSL { +public: + static OutputMixerOpenSL &getInstance(); + + SLresult open(); + + void close(); + + SLresult createAudioPlayer(SLObjectItf *objectItf, + SLDataSource *audioSource); + +private: + // Make this a safe Singleton + OutputMixerOpenSL()= default; + ~OutputMixerOpenSL()= default; + OutputMixerOpenSL(const OutputMixerOpenSL&)= delete; + OutputMixerOpenSL& operator=(const OutputMixerOpenSL&)= delete; + + std::mutex mLock; + int32_t mOpenCount = 0; + + SLObjectItf mOutputMixObject = nullptr; +}; + +} // namespace oboe + +#endif //OBOE_OUTPUT_MIXER_OPENSLES_H diff --git a/vendor/github.com/ebitengine/oto/v3/player.go b/vendor/github.com/ebitengine/oto/v3/player.go new file mode 100644 index 0000000..ad14860 --- /dev/null +++ b/vendor/github.com/ebitengine/oto/v3/player.go @@ -0,0 +1,85 @@ +// Copyright 2021 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package oto + +import ( + "github.com/ebitengine/oto/v3/internal/mux" +) + +// Player is a PCM (pulse-code modulation) audio player. +type Player struct { + player *mux.Player +} + +// Pause pauses its playing. +func (p *Player) Pause() { + p.player.Pause() +} + +// Play starts its playing if it doesn't play. +func (p *Player) Play() { + p.player.Play() +} + +// IsPlaying reports whether this player is playing. +func (p *Player) IsPlaying() bool { + return p.player.IsPlaying() +} + +// Reset clears the underyling buffer and pauses its playing. +// +// Deprecated: use Pause or Seek instead. +func (p *Player) Reset() { + p.player.Reset() +} + +// Volume returns the current volume in the range of [0, 1]. +// The default volume is 1. +func (p *Player) Volume() float64 { + return p.player.Volume() +} + +// SetVolume sets the current volume in the range of [0, 1]. +func (p *Player) SetVolume(volume float64) { + p.player.SetVolume(volume) +} + +// BufferedSize returns the byte size of the buffer data that is not sent to the audio hardware yet. +func (p *Player) BufferedSize() int { + return p.player.BufferedSize() +} + +// Err returns an error if this player has an error. +func (p *Player) Err() error { + return p.player.Err() +} + +// SetBufferSize sets the buffer size. +// If 0 is specified, the default buffer size is used. +func (p *Player) SetBufferSize(bufferSize int) { + p.player.SetBufferSize(bufferSize) +} + +// Seek implements io.Seeker. +// +// Seek returns an error when the underlying source doesn't implement io.Seeker. +func (p *Player) Seek(offset int64, whence int) (int64, error) { + return p.player.Seek(offset, whence) +} + +// Close implements io.Closer. +func (p *Player) Close() error { + return p.player.Close() +} diff --git a/vendor/github.com/ebitengine/purego/README.md b/vendor/github.com/ebitengine/purego/README.md index b8480f4..8f40f8b 100644 --- a/vendor/github.com/ebitengine/purego/README.md +++ b/vendor/github.com/ebitengine/purego/README.md @@ -3,6 +3,10 @@ A library for calling C functions from Go without Cgo. +> This is beta software so expect bugs and potentially API breaking changes +> but each release will be tagged to avoid breaking people's code. +> Bug reports are encouraged. + ## Motivation The [Ebitengine](https://github.com/hajimehoshi/ebiten) game engine was ported to use only Go on Windows. This enabled @@ -16,10 +20,22 @@ born to bring that same vision to the other platforms supported by Ebitengine. - **Smaller Binaries**: Using Cgo generates a C wrapper function for each C function called. Purego doesn't! - **Dynamic Linking**: Load symbols at runtime and use it as a plugin system. - **Foreign Function Interface**: Call into other languages that are compiled into shared objects. +- **Cgo Fallback**: Works even with CGO_ENABLED=1 so incremental porting is possible. +This also means unsupported GOARCHs (freebsd/riscv64, linux/mips, etc.) will still work +except for float arguments and return values. + +## Supported Platforms + +- **FreeBSD**: amd64, arm64 +- **Linux**: amd64, arm64 +- **macOS / iOS**: amd64, arm64 +- **Windows**: 386*, amd64, arm*, arm64 + +`*` These architectures only support SyscallN and NewCallback ## Example -This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows. +This example only works on macOS and Linux. For a complete example look at [libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports Windows and FreeBSD. ```go package main @@ -55,16 +71,26 @@ func main() { Then to run: `CGO_ENABLED=0 go run main.go` +## Questions + +If you have questions about how to incorporate purego in your project or want to discuss +how it works join the [Discord](https://discord.com/channels/842049801528016967/1123106378731487345)! + ### External Code Purego uses code that originates from the Go runtime. These files are under the BSD-3 License that can be found [in the Go Source](https://github.com/golang/go/blob/master/LICENSE). This is a list of the copied files: +* `abi_*.h` from package `runtime/cgo` * `zcallback_darwin_*.s` from package `runtime` -* `internal/abi/abi_*.h` from package `runtime/cgo` +* `internal/fakecgo/abi_*.h` from package `runtime/cgo` * `internal/fakecgo/asm_GOARCH.s` from package `runtime/cgo` * `internal/fakecgo/callbacks.go` from package `runtime/cgo` * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo` * `internal/fakecgo/iscgo.go` from package `runtime/cgo` * `internal/fakecgo/setenv.go` from package `runtime/cgo` +* `internal/fakecgo/freebsd.go` from package `runtime/cgo` + +The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of +`#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) diff --git a/vendor/github.com/ebitengine/purego/internal/abi/abi_amd64.h b/vendor/github.com/ebitengine/purego/abi_amd64.h similarity index 100% rename from vendor/github.com/ebitengine/purego/internal/abi/abi_amd64.h rename to vendor/github.com/ebitengine/purego/abi_amd64.h diff --git a/vendor/github.com/ebitengine/purego/internal/abi/abi_arm64.h b/vendor/github.com/ebitengine/purego/abi_arm64.h similarity index 100% rename from vendor/github.com/ebitengine/purego/internal/abi/abi_arm64.h rename to vendor/github.com/ebitengine/purego/abi_arm64.h diff --git a/vendor/github.com/ebitengine/purego/cgo.go b/vendor/github.com/ebitengine/purego/cgo.go index ebe6912..7d5abef 100644 --- a/vendor/github.com/ebitengine/purego/cgo.go +++ b/vendor/github.com/ebitengine/purego/cgo.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build cgo && (darwin || linux) +//go:build cgo && (darwin || freebsd || linux) package purego @@ -12,4 +12,8 @@ package purego // which will import this package automatically. Normally this isn't an issue since it // usually isn't possible to call into C without using that import. However, with purego // it is since we don't use `import "C"`! -import _ "runtime/cgo" +import ( + _ "runtime/cgo" + + _ "github.com/ebitengine/purego/internal/cgo" +) diff --git a/vendor/github.com/ebitengine/purego/dlerror.go b/vendor/github.com/ebitengine/purego/dlerror.go index e5ce708..cf4c050 100644 --- a/vendor/github.com/ebitengine/purego/dlerror.go +++ b/vendor/github.com/ebitengine/purego/dlerror.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package purego diff --git a/vendor/github.com/ebitengine/purego/dlfcn.go b/vendor/github.com/ebitengine/purego/dlfcn.go index 5b53560..2ee6f34 100644 --- a/vendor/github.com/ebitengine/purego/dlfcn.go +++ b/vendor/github.com/ebitengine/purego/dlfcn.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package purego diff --git a/vendor/github.com/ebitengine/purego/dlfcn_darwin.go b/vendor/github.com/ebitengine/purego/dlfcn_darwin.go index 66ccf16..b343f84 100644 --- a/vendor/github.com/ebitengine/purego/dlfcn_darwin.go +++ b/vendor/github.com/ebitengine/purego/dlfcn_darwin.go @@ -17,3 +17,8 @@ const ( //go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib" //go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib" + +//go:cgo_import_dynamic purego_dlopen dlopen "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib" +//go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib" diff --git a/vendor/github.com/ebitengine/purego/dlfcn_freebsd.go b/vendor/github.com/ebitengine/purego/dlfcn_freebsd.go new file mode 100644 index 0000000..38f0678 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/dlfcn_freebsd.go @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +package purego + +// Constants as defined in https://github.com/freebsd/freebsd-src/blob/main/include/dlfcn.h +const ( + RTLD_DEFAULT = ^uintptr(0) - 2 // Pseudo-handle for dlsym so search for any loaded symbol + RTLD_LAZY = 0x00001 // Relocations are performed at an implementation-dependent time. + RTLD_NOW = 0x00002 // Relocations are performed when the object is loaded. + RTLD_LOCAL = 0x00000 // All symbols are not made available for relocation processing by other modules. + RTLD_GLOBAL = 0x00100 // All symbols are available for relocation processing of other modules. +) diff --git a/vendor/github.com/ebitengine/purego/dlfcn_nocgo_freebsd.go b/vendor/github.com/ebitengine/purego/dlfcn_nocgo_freebsd.go new file mode 100644 index 0000000..1bd6612 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/dlfcn_nocgo_freebsd.go @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build !cgo + +package purego + +//go:cgo_import_dynamic purego_dlopen dlopen "libc.so.7" +//go:cgo_import_dynamic purego_dlsym dlsym "libc.so.7" +//go:cgo_import_dynamic purego_dlerror dlerror "libc.so.7" +//go:cgo_import_dynamic purego_dlclose dlclose "libc.so.7" diff --git a/vendor/github.com/ebitengine/purego/dlfcn_stubs.s b/vendor/github.com/ebitengine/purego/dlfcn_stubs.s index dca30f9..fa434bf 100644 --- a/vendor/github.com/ebitengine/purego/dlfcn_stubs.s +++ b/vendor/github.com/ebitengine/purego/dlfcn_stubs.s @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || (linux && !cgo) +//go:build darwin || !cgo && (freebsd || linux) #include "textflag.h" diff --git a/vendor/github.com/ebitengine/purego/dummy.go b/vendor/github.com/ebitengine/purego/dummy.go deleted file mode 100644 index 8ac52fc..0000000 --- a/vendor/github.com/ebitengine/purego/dummy.go +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2022 The Ebitengine Authors - -//go:build dummy - -// This file exists purely to prevent the Go toolchain from stripping -// away the C source directories and files when `go mod vendor` is used -// to populate a `vendor/` directory of a project depending on this package. - -package purego - -import ( - _ "github.com/ebitengine/purego/internal/abi" -) diff --git a/vendor/github.com/ebitengine/purego/func.go b/vendor/github.com/ebitengine/purego/func.go index 8ddf76d..b0be0c3 100644 --- a/vendor/github.com/ebitengine/purego/func.go +++ b/vendor/github.com/ebitengine/purego/func.go @@ -1,11 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux || windows +//go:build darwin || freebsd || linux || windows package purego import ( + "fmt" "math" "reflect" "runtime" @@ -35,7 +36,7 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) { // matches the C function. This also holds true for struct types where the padding // needs to be ensured to match that of C; RegisterFunc does not verify this. // -// Type Conversions (Go => C) +// # Type Conversions (Go <=> C) // // string <=> char* // bool <=> _Bool @@ -50,9 +51,9 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) { // int16 <=> int16_t // int32 <=> int32_t // int64 <=> int64_t -// float32 <=> float (WIP) -// float64 <=> double (WIP) -// struct <=> struct (WIP) +// float32 <=> float +// float64 <=> double +// struct <=> struct (WIP - darwin only) // func <=> C function // unsafe.Pointer, *T <=> void* // []T => void* @@ -62,9 +63,48 @@ func RegisterLibFunc(fptr interface{}, handle uintptr, name string) { // This means that using arg ...interface{} is like a cast to the function with the arguments inside arg. // This is not the same as C variadic. // -// There are some limitations when using RegisterFunc on Linux. First, there is no support for function arguments. -// Second, float32 and float64 arguments and return values do not work when CGO_ENABLED=1. Otherwise, Linux -// has the same feature parity as Darwin. +// # Memory +// +// In general it is not possible for purego to guarantee the lifetimes of objects returned or received from +// calling functions using RegisterFunc. For arguments to a C function it is important that the C function doesn't +// hold onto a reference to Go memory. This is the same as the [Cgo rules]. +// +// However, there are some special cases. When passing a string as an argument if the string does not end in a null +// terminated byte (\x00) then the string will be copied into memory maintained by purego. The memory is only valid for +// that specific call. Therefore, if the C code keeps a reference to that string it may become invalid at some +// undefined time. However, if the string does already contain a null-terminated byte then no copy is done. +// It is then the responsibility of the caller to ensure the string stays alive as long as it's needed in C memory. +// This can be done using runtime.KeepAlive or allocating the string in C memory using malloc. When a C function +// returns a null-terminated pointer to char a Go string can be used. Purego will allocate a new string in Go memory +// and copy the data over. This string will be garbage collected whenever Go decides it's no longer referenced. +// This C created string will not be freed by purego. If the pointer to char is not null-terminated or must continue +// to point to C memory (because it's a buffer for example) then use a pointer to byte and then convert that to a slice +// using unsafe.Slice. Doing this means that it becomes the responsibility of the caller to care about the lifetime +// of the pointer +// +// # Structs +// +// Purego can handle the most common structs that have fields of builtin types like int8, uint16, float32, etc. However, +// it does not support aligning fields properly. It is therefore the responsibility of the caller to ensure +// that all padding is added to the Go struct to match the C one. See `BoolStructFn` in struct_test.go for an example. +// +// # Example +// +// All functions below call this C function: +// +// char *foo(char *str); +// +// // Let purego convert types +// var foo func(s string) string +// goString := foo("copied") +// // Go will garbage collect this string +// +// // Manually, handle allocations +// var foo2 func(b string) *byte +// mustFree := foo2("not copied\x00") +// defer free(mustFree) +// +// [Cgo rules]: https://pkg.go.dev/cmd/cgo#hdr-Go_references_to_C func RegisterFunc(fptr interface{}, cfn uintptr) { fn := reflect.ValueOf(fptr).Elem() ty := fn.Type() @@ -95,15 +135,47 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { stack++ } case reflect.Float32, reflect.Float64: + if is32bit { + panic("purego: floats only supported on 64bit platforms") + } if floats < numOfFloats { floats++ } else { stack++ } + case reflect.Struct: + if runtime.GOOS != "darwin" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64") { + panic("purego: struct arguments are only supported on darwin amd64 & arm64") + } + if arg.Size() == 0 { + continue + } + addInt := func(u uintptr) { + ints++ + } + addFloat := func(u uintptr) { + floats++ + } + addStack := func(u uintptr) { + stack++ + } + _ = addStruct(reflect.New(arg).Elem(), &ints, &floats, &stack, addInt, addFloat, addStack, nil) default: panic("purego: unsupported kind " + arg.Kind().String()) } } + if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct { + if runtime.GOOS != "darwin" { + panic("purego: struct return values only supported on darwin arm64 & amd64") + } + outType := ty.Out(0) + checkStructFieldsSupported(outType) + if runtime.GOARCH == "amd64" && outType.Size() > maxRegAllocStructSize { + // on amd64 if struct is bigger than 16 bytes allocate the return struct + // and pass it in as a hidden first argument. + ints++ + } + } sizeOfStack := maxArgs - numOfIntegerRegisters() if stack > sizeOfStack { panic("purego: too many arguments") @@ -170,6 +242,21 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { runtime.KeepAlive(keepAlive) runtime.KeepAlive(args) }() + var syscall syscall15Args + if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct { + outType := ty.Out(0) + if runtime.GOARCH == "amd64" && outType.Size() > maxRegAllocStructSize { + val := reflect.New(outType) + keepAlive = append(keepAlive, val) + addInt(val.Pointer()) + } else if runtime.GOARCH == "arm64" && outType.Size() > maxRegAllocStructSize { + if !isAllSameFloat(outType) || outType.NumField() > 4 { + val := reflect.New(outType) + keepAlive = append(keepAlive, val) + syscall.arm64_r8 = val.Pointer() + } + } + } for _, v := range args { switch v.Kind() { case reflect.String: @@ -195,25 +282,29 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { addFloat(uintptr(math.Float32bits(float32(v.Float())))) case reflect.Float64: addFloat(uintptr(math.Float64bits(v.Float()))) + case reflect.Struct: + keepAlive = addStruct(v, &numInts, &numFloats, &numStack, addInt, addFloat, addStack, keepAlive) default: panic("purego: unsupported kind: " + v.Kind().String()) } } - // TODO: support structs - var r1, r2 uintptr if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" { // Use the normal arm64 calling convention even on Windows - syscall := syscall9Args{ + syscall = syscall15Args{ cfn, - sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], sysargs[6], sysargs[7], sysargs[8], + sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], + sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11], + sysargs[12], sysargs[13], sysargs[14], floats[0], floats[1], floats[2], floats[3], floats[4], floats[5], floats[6], floats[7], - 0, 0, 0, + syscall.arm64_r8, } - runtime_cgocall(syscall9XABI0, unsafe.Pointer(&syscall)) - r1, r2 = syscall.r1, syscall.r2 + runtime_cgocall(syscall15XABI0, unsafe.Pointer(&syscall)) } else { - // This is a fallback for amd64, 386, and arm. Note this may not support floats - r1, r2, _ = syscall_syscall9X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], sysargs[6], sysargs[7], sysargs[8]) + // This is a fallback for Windows amd64, 386, and arm. Note this may not support floats + syscall.a1, syscall.a2, _ = syscall_syscall15X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], + sysargs[5], sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11], + sysargs[12], sysargs[13], sysargs[14]) + syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support } if ty.NumOut() == 0 { return nil @@ -222,27 +313,33 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { v := reflect.New(outType).Elem() switch outType.Kind() { case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - v.SetUint(uint64(r1)) + v.SetUint(uint64(syscall.a1)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v.SetInt(int64(r1)) + v.SetInt(int64(syscall.a1)) case reflect.Bool: - v.SetBool(r1 != 0) + v.SetBool(byte(syscall.a1) != 0) case reflect.UnsafePointer: // We take the address and then dereference it to trick go vet from creating a possible miss-use of unsafe.Pointer - v.SetPointer(*(*unsafe.Pointer)(unsafe.Pointer(&r1))) + v.SetPointer(*(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))) case reflect.Ptr: - // It is safe to have the address of r1 not escape because it is immediately dereferenced with .Elem() - v = reflect.NewAt(outType, runtime_noescape(unsafe.Pointer(&r1))).Elem() + // It is safe to have the address of syscall.r1 not escape because it is immediately dereferenced with .Elem() + v = reflect.NewAt(outType, runtime_noescape(unsafe.Pointer(&syscall.a1))).Elem() case reflect.Func: // wrap this C function in a nicely typed Go function v = reflect.New(outType) - RegisterFunc(v.Interface(), r1) + RegisterFunc(v.Interface(), syscall.a1) case reflect.String: - v.SetString(strings.GoString(r1)) - case reflect.Float32, reflect.Float64: - // NOTE: r2 is only the floating return value on 64bit platforms. - // On 32bit platforms r2 is the upper part of a 64bit return. - v.SetFloat(math.Float64frombits(uint64(r2))) + v.SetString(strings.GoString(syscall.a1)) + case reflect.Float32: + // NOTE: syscall.r2 is only the floating return value on 64bit platforms. + // On 32bit platforms syscall.r2 is the upper part of a 64bit return. + v.SetFloat(float64(math.Float32frombits(uint32(syscall.f1)))) + case reflect.Float64: + // NOTE: syscall.r2 is only the floating return value on 64bit platforms. + // On 32bit platforms syscall.r2 is the upper part of a 64bit return. + v.SetFloat(math.Float64frombits(uint64(syscall.f1))) + case reflect.Struct: + v = getStruct(outType, syscall) default: panic("purego: unsupported return kind: " + outType.Kind().String()) } @@ -251,6 +348,50 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { fn.Set(v) } +// maxRegAllocStructSize is the biggest a struct can be while still fitting in registers. +// if it is bigger than this than enough space must be allocated on the heap and then passed into +// the function as the first parameter on amd64 or in R8 on arm64. +const maxRegAllocStructSize = 16 + +func isAllSameFloat(ty reflect.Type) bool { + first := ty.Field(0).Type.Kind() + if first != reflect.Float32 && first != reflect.Float64 { + return false + } + for i := 0; i < ty.NumField(); i++ { + f := ty.Field(i) + if f.Type.Kind() != first { + return false + } + } + return true +} + +func checkStructFieldsSupported(ty reflect.Type) { + for i := 0; i < ty.NumField(); i++ { + f := ty.Field(i).Type + if f.Kind() == reflect.Array { + f = f.Elem() + } else if f.Kind() == reflect.Struct { + checkStructFieldsSupported(f) + continue + } + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Uintptr, reflect.Ptr, reflect.UnsafePointer, reflect.Float64, reflect.Float32: + default: + panic(fmt.Sprintf("purego: struct field type %s is not supported", f)) + } + } +} + +const is32bit = unsafe.Sizeof(uintptr(0)) == 4 + +func roundUpTo8(val uintptr) uintptr { + return (val + 7) &^ 7 +} + func numOfIntegerRegisters() int { switch runtime.GOARCH { case "arm64": diff --git a/vendor/github.com/ebitengine/purego/go_runtime.go b/vendor/github.com/ebitengine/purego/go_runtime.go index d434740..9593dac 100644 --- a/vendor/github.com/ebitengine/purego/go_runtime.go +++ b/vendor/github.com/ebitengine/purego/go_runtime.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux || windows +//go:build darwin || freebsd || linux || windows package purego diff --git a/vendor/github.com/ebitengine/purego/internal/abi/dummy.go b/vendor/github.com/ebitengine/purego/internal/abi/dummy.go deleted file mode 100644 index 0f218f3..0000000 --- a/vendor/github.com/ebitengine/purego/internal/abi/dummy.go +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2022 The Ebitengine Authors - -//go:build dummy - -// Package abi is a dummy package that prevents go tooling from stripping the C dependencies. -package abi diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go b/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go new file mode 100644 index 0000000..7e4dd04 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +//go:build freebsd || linux + +package cgo + +/* + #cgo LDFLAGS: -ldl + +#include +*/ +import "C" + +// all that is needed is to assign each dl function because then its +// symbol will then be made available to the linker and linked to inside dlfcn.go +var ( + _ = C.dlopen + _ = C.dlsym + _ = C.dlerror + _ = C.dlclose +) diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/empty.go b/vendor/github.com/ebitengine/purego/internal/cgo/empty.go new file mode 100644 index 0000000..1d7cffe --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/cgo/empty.go @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +package cgo + +// Empty so that importing this package doesn't cause issue for certain platforms. diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_linux.go b/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_linux.go deleted file mode 100644 index 89b9fca..0000000 --- a/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_linux.go +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2022 The Ebitengine Authors - -package cgo - -// this file is placed inside internal/cgo and not package purego -// because Cgo and assembly files can't be in the same package. - -/* - #cgo LDFLAGS: -ldl - -#include -#include -#include -#include - -typedef struct syscall9Args { - uintptr_t fn; - uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9; - uintptr_t f1, f2, f3, f4, f5, f6, f7, f8; - uintptr_t r1, r2, err; -} syscall9Args; - -void syscall9(struct syscall9Args *args) { - assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0); - uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9); - *(void**)(&func_name) = (void*)(args->fn); - uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9); - args->r1 = r1; - args->err = errno; -} - -*/ -import "C" -import "unsafe" - -// assign purego.syscall9XABI0 to the C version of this function. -var Syscall9XABI0 = unsafe.Pointer(C.syscall9) - -// all that is needed is to assign each dl function because then its -// symbol will then be made available to the linker and linked to inside dlfcn.go -var ( - _ = C.dlopen - _ = C.dlsym - _ = C.dlerror - _ = C.dlclose -) - -//go:nosplit -func Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { - args := C.syscall9Args{C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3), - C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6), - C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - C.syscall9(&args) - return uintptr(args.r1), uintptr(args.r2), uintptr(args.err) -} diff --git a/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go b/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go new file mode 100644 index 0000000..029a259 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +//go:build freebsd || (linux && !(arm64 || amd64)) + +package cgo + +// this file is placed inside internal/cgo and not package purego +// because Cgo and assembly files can't be in the same package. + +/* + #cgo LDFLAGS: -ldl + +#include +#include +#include +#include + +typedef struct syscall15Args { + uintptr_t fn; + uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15; + uintptr_t f1, f2, f3, f4, f5, f6, f7, f8; + uintptr_t r1, r2, err; +} syscall15Args; + +void syscall15(struct syscall15Args *args) { + assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0); + uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, + uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, + uintptr_t a13, uintptr_t a14, uintptr_t a15); + *(void**)(&func_name) = (void*)(args->fn); + uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9, + args->a10,args->a11,args->a12,args->a13,args->a14,args->a15); + args->r1 = r1; + args->err = errno; +} + +*/ +import "C" +import "unsafe" + +// assign purego.syscall15XABI0 to the C version of this function. +var Syscall15XABI0 = unsafe.Pointer(C.syscall15) + +//go:nosplit +func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) { + args := C.syscall15Args{ + C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3), + C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6), + C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12), + C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + } + C.syscall15(&args) + return uintptr(args.r1), uintptr(args.r2), uintptr(args.err) +} diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h new file mode 100644 index 0000000..9949435 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h @@ -0,0 +1,99 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Macros for transitioning from the host ABI to Go ABI0. +// +// These save the frame pointer, so in general, functions that use +// these should have zero frame size to suppress the automatic frame +// pointer, though it's harmless to not do this. + +#ifdef GOOS_windows + +// REGS_HOST_TO_ABI0_STACK is the stack bytes used by +// PUSH_REGS_HOST_TO_ABI0. +#define REGS_HOST_TO_ABI0_STACK (28*8 + 8) + +// PUSH_REGS_HOST_TO_ABI0 prepares for transitioning from +// the host ABI to Go ABI0 code. It saves all registers that are +// callee-save in the host ABI and caller-save in Go ABI0 and prepares +// for entry to Go. +// +// Save DI SI BP BX R12 R13 R14 R15 X6-X15 registers and the DF flag. +// Clear the DF flag for the Go ABI. +// MXCSR matches the Go ABI, so we don't have to set that, +// and Go doesn't modify it, so we don't have to save it. +#define PUSH_REGS_HOST_TO_ABI0() \ + PUSHFQ \ + CLD \ + ADJSP $(REGS_HOST_TO_ABI0_STACK - 8) \ + MOVQ DI, (0*0)(SP) \ + MOVQ SI, (1*8)(SP) \ + MOVQ BP, (2*8)(SP) \ + MOVQ BX, (3*8)(SP) \ + MOVQ R12, (4*8)(SP) \ + MOVQ R13, (5*8)(SP) \ + MOVQ R14, (6*8)(SP) \ + MOVQ R15, (7*8)(SP) \ + MOVUPS X6, (8*8)(SP) \ + MOVUPS X7, (10*8)(SP) \ + MOVUPS X8, (12*8)(SP) \ + MOVUPS X9, (14*8)(SP) \ + MOVUPS X10, (16*8)(SP) \ + MOVUPS X11, (18*8)(SP) \ + MOVUPS X12, (20*8)(SP) \ + MOVUPS X13, (22*8)(SP) \ + MOVUPS X14, (24*8)(SP) \ + MOVUPS X15, (26*8)(SP) + +#define POP_REGS_HOST_TO_ABI0() \ + MOVQ (0*0)(SP), DI \ + MOVQ (1*8)(SP), SI \ + MOVQ (2*8)(SP), BP \ + MOVQ (3*8)(SP), BX \ + MOVQ (4*8)(SP), R12 \ + MOVQ (5*8)(SP), R13 \ + MOVQ (6*8)(SP), R14 \ + MOVQ (7*8)(SP), R15 \ + MOVUPS (8*8)(SP), X6 \ + MOVUPS (10*8)(SP), X7 \ + MOVUPS (12*8)(SP), X8 \ + MOVUPS (14*8)(SP), X9 \ + MOVUPS (16*8)(SP), X10 \ + MOVUPS (18*8)(SP), X11 \ + MOVUPS (20*8)(SP), X12 \ + MOVUPS (22*8)(SP), X13 \ + MOVUPS (24*8)(SP), X14 \ + MOVUPS (26*8)(SP), X15 \ + ADJSP $-(REGS_HOST_TO_ABI0_STACK - 8) \ + POPFQ + +#else +// SysV ABI + +#define REGS_HOST_TO_ABI0_STACK (6*8) + +// SysV MXCSR matches the Go ABI, so we don't have to set that, +// and Go doesn't modify it, so we don't have to save it. +// Both SysV and Go require DF to be cleared, so that's already clear. +// The SysV and Go frame pointer conventions are compatible. +#define PUSH_REGS_HOST_TO_ABI0() \ + ADJSP $(REGS_HOST_TO_ABI0_STACK) \ + MOVQ BP, (5*8)(SP) \ + LEAQ (5*8)(SP), BP \ + MOVQ BX, (0*8)(SP) \ + MOVQ R12, (1*8)(SP) \ + MOVQ R13, (2*8)(SP) \ + MOVQ R14, (3*8)(SP) \ + MOVQ R15, (4*8)(SP) + +#define POP_REGS_HOST_TO_ABI0() \ + MOVQ (0*8)(SP), BX \ + MOVQ (1*8)(SP), R12 \ + MOVQ (2*8)(SP), R13 \ + MOVQ (3*8)(SP), R14 \ + MOVQ (4*8)(SP), R15 \ + MOVQ (5*8)(SP), BP \ + ADJSP $-(REGS_HOST_TO_ABI0_STACK) + +#endif diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h new file mode 100644 index 0000000..5d5061e --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h @@ -0,0 +1,39 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Macros for transitioning from the host ABI to Go ABI0. +// +// These macros save and restore the callee-saved registers +// from the stack, but they don't adjust stack pointer, so +// the user should prepare stack space in advance. +// SAVE_R19_TO_R28(offset) saves R19 ~ R28 to the stack space +// of ((offset)+0*8)(RSP) ~ ((offset)+9*8)(RSP). +// +// SAVE_F8_TO_F15(offset) saves F8 ~ F15 to the stack space +// of ((offset)+0*8)(RSP) ~ ((offset)+7*8)(RSP). +// +// R29 is not saved because Go will save and restore it. + +#define SAVE_R19_TO_R28(offset) \ + STP (R19, R20), ((offset)+0*8)(RSP) \ + STP (R21, R22), ((offset)+2*8)(RSP) \ + STP (R23, R24), ((offset)+4*8)(RSP) \ + STP (R25, R26), ((offset)+6*8)(RSP) \ + STP (R27, g), ((offset)+8*8)(RSP) +#define RESTORE_R19_TO_R28(offset) \ + LDP ((offset)+0*8)(RSP), (R19, R20) \ + LDP ((offset)+2*8)(RSP), (R21, R22) \ + LDP ((offset)+4*8)(RSP), (R23, R24) \ + LDP ((offset)+6*8)(RSP), (R25, R26) \ + LDP ((offset)+8*8)(RSP), (R27, g) /* R28 */ +#define SAVE_F8_TO_F15(offset) \ + FSTPD (F8, F9), ((offset)+0*8)(RSP) \ + FSTPD (F10, F11), ((offset)+2*8)(RSP) \ + FSTPD (F12, F13), ((offset)+4*8)(RSP) \ + FSTPD (F14, F15), ((offset)+6*8)(RSP) +#define RESTORE_F8_TO_F15(offset) \ + FLDPD ((offset)+0*8)(RSP), (F8, F9) \ + FLDPD ((offset)+2*8)(RSP), (F10, F11) \ + FLDPD ((offset)+4*8)(RSP), (F12, F13) \ + FLDPD ((offset)+6*8)(RSP), (F14, F15) diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s index 6439f33..2b7eb57 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s @@ -3,14 +3,14 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "../abi/abi_amd64.h" +#include "abi_amd64.h" // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) // Saves C callee-saved registers and calls cgocallback with three arguments. // fn is the PC of a func(a unsafe.Pointer) function. // This signature is known to SWIG, so we can't change it. -TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0-0 +TEXT crosscall2(SB), NOSPLIT, $0-0 PUSH_REGS_HOST_TO_ABI0() // Make room for arguments to cgocallback. diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s index 3083b36..50e5261 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. #include "textflag.h" -#include "../abi/abi_arm64.h" +#include "abi_arm64.h" // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go index fe39f32..f6a079a 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go index 7309b86..efbe421 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin +//go:build darwin || freebsd // Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go. // This allows code that calls into C to function properly when CGO_ENABLED=0. diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go new file mode 100644 index 0000000..bb73a70 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go @@ -0,0 +1,27 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build freebsd && !cgo + +package fakecgo + +import _ "unsafe" // for go:linkname + +// Supply environ and __progname, because we don't +// link against the standard FreeBSD crt0.o and the +// libc dynamic library needs them. + +// Note: when building with cross-compiling or CGO_ENABLED=0, add +// the following argument to `go` so that these symbols are defined by +// making fakecgo the Cgo. +// -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" + +//go:linkname _environ environ +//go:linkname _progname __progname + +//go:cgo_export_dynamic environ +//go:cgo_export_dynamic __progname + +var _environ uintptr +var _progname uintptr diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go new file mode 100644 index 0000000..9aa57ef --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_amd64.go @@ -0,0 +1,93 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fakecgo + +import "unsafe" + +//go:nosplit +func _cgo_sys_thread_start(ts *ThreadStart) { + var attr pthread_attr_t + var ign, oset sigset_t + var p pthread_t + var size size_t + var err int + + //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug + sigfillset(&ign) + pthread_sigmask(SIG_SETMASK, &ign, &oset) + + pthread_attr_init(&attr) + pthread_attr_getstacksize(&attr, &size) + // Leave stacklo=0 and set stackhi=size; mstart will do the rest. + ts.g.stackhi = uintptr(size) + + err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) + + pthread_sigmask(SIG_SETMASK, &oset, nil) + + if err != 0 { + print("fakecgo: pthread_create failed: ") + println(err) + abort() + } +} + +// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function +// +//go:linkname x_threadentry_trampoline threadentry_trampoline +var x_threadentry_trampoline byte +var threadentry_trampolineABI0 = &x_threadentry_trampoline + +//go:nosplit +func threadentry(v unsafe.Pointer) unsafe.Pointer { + ts := *(*ThreadStart)(v) + free(v) + + setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) + + // faking funcs in go is a bit a... involved - but the following works :) + fn := uintptr(unsafe.Pointer(&ts.fn)) + (*(*func())(unsafe.Pointer(&fn)))() + + return nil +} + +// here we will store a pointer to the provided setg func +var setg_func uintptr + +//go:nosplit +func x_cgo_init(g *G, setg uintptr) { + var size size_t + var attr *pthread_attr_t + + /* The memory sanitizer distributed with versions of clang + before 3.8 has a bug: if you call mmap before malloc, mmap + may return an address that is later overwritten by the msan + library. Avoid this problem by forcing a call to malloc + here, before we ever call malloc. + + This is only required for the memory sanitizer, so it's + unfortunate that we always run it. It should be possible + to remove this when we no longer care about versions of + clang before 3.8. The test for this is + misc/cgo/testsanitizers. + + GCC works hard to eliminate a seemingly unnecessary call to + malloc, so we actually use the memory we allocate. */ + + setg_func = setg + attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) + if attr == nil { + println("fakecgo: malloc failed") + abort() + } + pthread_attr_init(attr) + pthread_attr_getstacksize(attr, &size) + // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` + // but this should be OK since we are taking the address of the first variable in this function. + g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 + pthread_attr_destroy(attr) + free(unsafe.Pointer(attr)) +} diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go new file mode 100644 index 0000000..1db518e --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd_arm64.go @@ -0,0 +1,96 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fakecgo + +import "unsafe" + +//go:nosplit +func _cgo_sys_thread_start(ts *ThreadStart) { + var attr pthread_attr_t + var ign, oset sigset_t + var p pthread_t + var size size_t + var err int + + //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug + sigfillset(&ign) + pthread_sigmask(SIG_SETMASK, &ign, &oset) + + pthread_attr_init(&attr) + pthread_attr_getstacksize(&attr, &size) + // Leave stacklo=0 and set stackhi=size; mstart will do the rest. + ts.g.stackhi = uintptr(size) + + err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) + + pthread_sigmask(SIG_SETMASK, &oset, nil) + + if err != 0 { + print("fakecgo: pthread_create failed: ") + println(err) + abort() + } +} + +// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function +// +//go:linkname x_threadentry_trampoline threadentry_trampoline +var x_threadentry_trampoline byte +var threadentry_trampolineABI0 = &x_threadentry_trampoline + +//go:nosplit +func threadentry(v unsafe.Pointer) unsafe.Pointer { + ts := *(*ThreadStart)(v) + free(v) + + setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) + + // faking funcs in go is a bit a... involved - but the following works :) + fn := uintptr(unsafe.Pointer(&ts.fn)) + (*(*func())(unsafe.Pointer(&fn)))() + + return nil +} + +// here we will store a pointer to the provided setg func +var setg_func uintptr + +// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c) +// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us +// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup +// This function can't be go:systemstack since go is not in a state where the systemcheck would work. +// +//go:nosplit +func x_cgo_init(g *G, setg uintptr) { + var size size_t + var attr *pthread_attr_t + + /* The memory sanitizer distributed with versions of clang + before 3.8 has a bug: if you call mmap before malloc, mmap + may return an address that is later overwritten by the msan + library. Avoid this problem by forcing a call to malloc + here, before we ever call malloc. + + This is only required for the memory sanitizer, so it's + unfortunate that we always run it. It should be possible + to remove this when we no longer care about versions of + clang before 3.8. The test for this is + misc/cgo/testsanitizers. + + GCC works hard to eliminate a seemingly unnecessary call to + malloc, so we actually use the memory we allocate. */ + + setg_func = setg + attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) + if attr == nil { + println("fakecgo: malloc failed") + abort() + } + pthread_attr_init(attr) + pthread_attr_getstacksize(attr, &size) + g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 + pthread_attr_destroy(attr) + free(unsafe.Pointer(attr)) +} diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go index c824e24..71da112 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go index 6ab42db..818372e 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go index daf1203..7a43b42 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go index d8493e1..ce17d18 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || linux +//go:build darwin || freebsd || linux // The runtime package contains an uninitialized definition // for runtime·iscgo. Override it to tell the runtime we're here. diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go index 432813f..c12d403 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go new file mode 100644 index 0000000..baf03fa --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +package fakecgo + +type ( + pthread_cond_t uintptr + pthread_mutex_t uintptr +) + +var ( + PTHREAD_COND_INITIALIZER = pthread_cond_t(0) + PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0) +) diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go index 8e01ee5..b69d4b3 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go index 56b9a52..d7401f7 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols.go @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux package fakecgo diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go new file mode 100644 index 0000000..bff096d --- /dev/null +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/symbols_freebsd.go @@ -0,0 +1,27 @@ +// Code generated by 'go generate' with gen.go. DO NOT EDIT. + +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2022 The Ebitengine Authors + +package fakecgo + +//go:cgo_import_dynamic purego_malloc malloc "libc.so.7" +//go:cgo_import_dynamic purego_free free "libc.so.7" +//go:cgo_import_dynamic purego_setenv setenv "libc.so.7" +//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.7" +//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.7" +//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.7" +//go:cgo_import_dynamic purego_abort abort "libc.so.7" +//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so" +//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so" +//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so" +//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so" +//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so" +//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so" +//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so" +//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so" +//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so" +//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so" +//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so" +//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so" +//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so" diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s index bbd101b..24b6206 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || linux || freebsd /* trampoline for emulating required C functions for cgo in go (see cgo.go) diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s index a71c2fe..9c80fe2 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux #include "textflag.h" #include "go_asm.h" diff --git a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s index e150708..e872637 100644 --- a/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s +++ b/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_stubs.s @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || linux +//go:build darwin || freebsd || linux #include "textflag.h" diff --git a/vendor/github.com/ebitengine/purego/internal/strings/strings.go b/vendor/github.com/ebitengine/purego/internal/strings/strings.go index e34b5a1..5b0d252 100644 --- a/vendor/github.com/ebitengine/purego/internal/strings/strings.go +++ b/vendor/github.com/ebitengine/purego/internal/strings/strings.go @@ -17,12 +17,12 @@ func CString(name string) *byte { if hasSuffix(name, "\x00") { return &(*(*[]byte)(unsafe.Pointer(&name)))[0] } - var b = make([]byte, len(name)+1) + b := make([]byte, len(name)+1) copy(b, name) return &b[0] } -// GoString copies a char* to a Go string. +// GoString copies a null-terminated char* to a Go string. func GoString(c uintptr) string { // We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer ptr := *(*unsafe.Pointer)(unsafe.Pointer(&c)) diff --git a/vendor/github.com/ebitengine/purego/nocgo.go b/vendor/github.com/ebitengine/purego/nocgo.go index c7ee865..5b989ea 100644 --- a/vendor/github.com/ebitengine/purego/nocgo.go +++ b/vendor/github.com/ebitengine/purego/nocgo.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build !cgo && (darwin || linux) +//go:build !cgo && (darwin || freebsd || linux) package purego diff --git a/vendor/github.com/ebitengine/purego/objc/objc_runtime_darwin.go b/vendor/github.com/ebitengine/purego/objc/objc_runtime_darwin.go index e14c73b..ed691e2 100644 --- a/vendor/github.com/ebitengine/purego/objc/objc_runtime_darwin.go +++ b/vendor/github.com/ebitengine/purego/objc/objc_runtime_darwin.go @@ -10,13 +10,15 @@ import ( "fmt" "math" "reflect" + "regexp" + "unicode" + "unsafe" "github.com/ebitengine/purego" ) -//TODO: support try/catch? -//https://stackoverflow.com/questions/7062599/example-of-how-objective-cs-try-catch-implementation-is-executed-at-runtime - +// TODO: support try/catch? +// https://stackoverflow.com/questions/7062599/example-of-how-objective-cs-try-catch-implementation-is-executed-at-runtime var ( objc_msgSend_fn uintptr objc_msgSend func(obj ID, cmd SEL, args ...interface{}) ID @@ -34,7 +36,12 @@ var ( class_addIvar func(class Class, name string, size uintptr, alignment uint8, types string) bool class_addProtocol func(class Class, protocol *Protocol) bool ivar_getOffset func(ivar Ivar) uintptr + ivar_getName func(ivar Ivar) string object_getClass func(obj ID) Class + object_getIvar func(obj ID, ivar Ivar) ID + object_setIvar func(obj ID, ivar Ivar, value ID) + protocol_getName func(protocol *Protocol) string + protocol_isEqual func(p *Protocol, p2 *Protocol) bool ) func init() { @@ -65,6 +72,11 @@ func init() { purego.RegisterLibFunc(&class_addProtocol, objc, "class_addProtocol") purego.RegisterLibFunc(&class_getInstanceSize, objc, "class_getInstanceSize") purego.RegisterLibFunc(&ivar_getOffset, objc, "ivar_getOffset") + purego.RegisterLibFunc(&ivar_getName, objc, "ivar_getName") + purego.RegisterLibFunc(&protocol_getName, objc, "protocol_getName") + purego.RegisterLibFunc(&protocol_isEqual, objc, "protocol_isEqual") + purego.RegisterLibFunc(&object_getIvar, objc, "object_getIvar") + purego.RegisterLibFunc(&object_setIvar, objc, "object_setIvar") } // ID is an opaque pointer to some Objective-C object @@ -82,6 +94,16 @@ func (id ID) Send(sel SEL, args ...interface{}) ID { return objc_msgSend(id, sel, args...) } +// GetIvar reads the value of an instance variable in an object. +func (id ID) GetIvar(ivar Ivar) ID { + return object_getIvar(id, ivar) +} + +// SetIvar sets the value of an instance variable in an object. +func (id ID) SetIvar(ivar Ivar, value ID) { + object_setIvar(id, ivar, value) +} + // Send is a convenience method for sending messages to objects that can return any type. // This function takes a SEL instead of a string since RegisterName grabs the global Objective-C lock. // It is best to cache the result of RegisterName. @@ -103,7 +125,7 @@ type objc_super struct { // instead of a string since RegisterName grabs the global Objective-C lock. It is best to cache the result // of RegisterName. func (id ID) SendSuper(sel SEL, args ...interface{}) ID { - var super = &objc_super{ + super := &objc_super{ receiver: id, superClass: id.Class(), } @@ -114,7 +136,7 @@ func (id ID) SendSuper(sel SEL, args ...interface{}) ID { // This function takes a SEL instead of a string since RegisterName grabs the global Objective-C lock. // It is best to cache the result of RegisterName. func SendSuper[T any](id ID, sel SEL, args ...any) T { - var super = &objc_super{ + super := &objc_super{ receiver: id, superClass: id.Class(), } @@ -148,203 +170,164 @@ func AllocateClassPair(super Class, name string, extraBytes uintptr) Class { return objc_allocateClassPair(super, name, extraBytes) } -// Selector is an interface that takes a Go method name -// and returns the selector equivalent name. -// If it returns a nil SEL then that method -// is not added to the class object. -type Selector interface { - Selector(string) SEL +// MethodDef represents the Go function and the selector that ObjC uses to access that function. +type MethodDef struct { + Cmd SEL + Fn any } -// TagFormatError occurs when the parser fails to parse the objc tag in a Selector object -var TagFormatError = errors.New(`objc tag doesn't match "ClassName : SuperClassName ""`) +// IvarAttrib is the attribute that an ivar has. It affects if and which methods are automatically +// generated when creating a class with RegisterClass. See [Apple Docs] for an understanding of these attributes. +// The fields are still accessible using objc.GetIvar and objc.SetIvar regardless of the value of IvarAttrib. +// +// Take for example this Objective-C code: +// +// @property (readwrite) float value; +// +// In Go, the functions can be accessed as followed: +// +// var value = purego.Send[float32](id, purego.RegisterName("value")) +// id.Send(purego.RegisterName("setValue:"), 3.46) +// +// [Apple Docs]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html +type IvarAttrib int -// MismatchError occurs when the Go struct definition doesn't match that of Objective-C -var MismatchError = errors.New("go struct doesn't match objective-c struct") +const ( + ReadOnly IvarAttrib = 1 << iota + ReadWrite +) -// RegisterClass takes a pointer to a struct that implements the Selector interface. -// It will register the structs fields and pointer receiver methods in the Objective-C -// runtime using the SEL returned from Selector. Any errors that occur trying to add -// a Method or Ivar is returned as an error. Such errors may occur in parsing or because -// the size of the struct does not match the size in Objective-C. If no errors occur -// then the returned Class has been registered successfully. -// -// The struct's first field must be of type Class and have a tag that matches the format -// `objc:"ClassName : SuperClassName `. This tag is equal to how the class -// would be defined in Objective-C. -func RegisterClass(object Selector) (Class, error) { - ptr := reflect.TypeOf(object) - strct := ptr.Elem() - if strct.NumField() == 0 || strct.Field(0).Type != reflect.TypeOf(Class(0)) { - return 0, fmt.Errorf("objc: need objc.Class as first field: %w", MismatchError) - } - isa := strct.Field(0) - tag := isa.Tag.Get("objc") - if tag == "" { - return 0, fmt.Errorf("objc: missing objc tag: %w", TagFormatError) - } - // split contains the class name and super class name followed by all the Protocols - // start with two for ClassName : SuperClassName - var split = make([]string, 2) - { - // This is a simple parser for the objc tag that looks for the format - // "ClassName : SuperClassName " - // It appends to the split variable with the [ClassName, SuperClassName, Protocol, ...] - - var i int // from tag[0:i] is whatever identifier is next - var r rune // r is the current rune - skipSpace := func() { - for _, c := range tag { - if c == ' ' { - tag = tag[1:] - continue - } - break - } - } - skipSpace() - // get ClassName - for i, r = range tag { - if r == ' ' || r == ':' { - break - } - } - split[0] = tag[0:i] // store ClassName - tag = tag[i:] +// FieldDef is a definition of a field to add to an Objective-C class. +// The name of the field is what will be used to access it through the Ivar. If the type is bool +// the name cannot start with `is` since a getter will be generated with the name `isBoolName`. +// The name also cannot contain any spaces. +// The type is the Go equivalent type of the Ivar. +// Attribute determines if a getter and or setter method is generated for this field. +type FieldDef struct { + Name string + Type reflect.Type + Attribute IvarAttrib +} - skipSpace() +// ivarRegex checks to make sure the Ivar is correctly formatted +var ivarRegex = regexp.MustCompile("[a-z_][a-zA-Z0-9_]*") - // check for ':' - if len(tag) > 0 && tag[0] != ':' { - return 0, fmt.Errorf("objc: missing ':': %w", TagFormatError) - } - tag = tag[1:] // skip ':' - skipSpace() - - // get SuperClassName - for i, r = range tag { - if r == ' ' { - break - } else if i+1 == len(tag) { - // if this is the last character in the string - // make sure to increment i so that tag[:i] - // includes the last character - i++ - break - } - } - if len(tag) < i { - return 0, fmt.Errorf("objc: missing SuperClassName: %w", TagFormatError) - } - split[1] = tag[:i] // store SuperClassName - tag = tag[i:] // drop SuperClassName - skipSpace() - if len(tag) > 0 { - if tag[0] != '<' { - return 0, fmt.Errorf("objc: expected '<': %w", TagFormatError) - } - tag = tag[1:] // drop '<' - // get Protocols - outer: - for { - skipSpace() - for i, r = range tag { - switch r { - case ' ': - split = append(split, tag[:i]) - tag = tag[i:] - continue outer - case ',': - // If there is actually an identifier - add it. - if i > 0 { - split = append(split, tag[:i]) - tag = tag[i:] - } else { - // Otherwise, drop ',' - tag = tag[1:] - } - continue outer - case '>': - // If there is actually an identifier - add it. - if i > 0 { - split = append(split, tag[:i]) - tag = tag[i:] - } - break outer - } - } - return 0, fmt.Errorf("objc: expected '>': %w", TagFormatError) - } - } - } - class := objc_allocateClassPair(GetClass(split[1]), split[0], 0) +// RegisterClass takes the name of the class to create, the superclass, a list of protocols this class +// implements, a list of fields this class has and a list of methods. It returns the created class or an error +// describing what went wrong. +func RegisterClass(name string, superClass Class, protocols []*Protocol, ivars []FieldDef, methods []MethodDef) (Class, error) { + class := objc_allocateClassPair(superClass, name, 0) if class == 0 { - return 0, fmt.Errorf("objc: failed to create class with name '%s'", split[0]) + return 0, fmt.Errorf("objc: failed to create class with name '%s'", name) } - if len(split) > 2 { - // Add Protocols - for _, n := range split[2:] { - if !class.AddProtocol(GetProtocol(n)) { - return 0, fmt.Errorf("objc: couldn't add Protocol %s", n) - } + // Add Protocols + for _, p := range protocols { + if !class.AddProtocol(p) { + return 0, fmt.Errorf("objc: couldn't add Protocol %s", protocol_getName(p)) } } - // Add exported methods based on the selectors returned from Selector(string) SEL - for i := 0; i < ptr.NumMethod(); i++ { - met := ptr.Method(i) - // we know this method is the interface one since RegisterClass - // requires that the struct implement Selector. - if met.Name == "Selector" { - continue - } - sel := object.Selector(met.Name) - if sel == 0 { - continue - } - fn := met.Func.Interface() + // Add exported methods based on the selectors returned from ClassDef(string) SEL + for idx, def := range methods { imp, err := func() (imp IMP, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("objc: failed to create IMP: %s", r) } }() - return NewIMP(fn), nil + return NewIMP(def.Fn), nil }() if err != nil { - return 0, fmt.Errorf("objc: couldn't add Method %s: %w", met.Name, err) + return 0, fmt.Errorf("objc: couldn't add Method at index %d: %w", idx, err) } - encoding, err := encodeFunc(fn) + encoding, err := encodeFunc(def.Fn) if err != nil { - return 0, fmt.Errorf("objc: couldn't add Method %s: %w", met.Name, err) + return 0, fmt.Errorf("objc: couldn't add Method at index %d: %w", idx, err) } - if !class.AddMethod(sel, imp, encoding) { - return 0, fmt.Errorf("objc: couldn't add Method %s", met.Name) + if !class.AddMethod(def.Cmd, imp, encoding) { + return 0, fmt.Errorf("objc: couldn't add Method at index %d", idx) } } // Add Ivars - // Start at 1 because we skip the class object which is first - for i := 1; i < strct.NumField(); i++ { - f := strct.Field(i) - if f.Name == "_" { - continue + for _, instVar := range ivars { + ivar := instVar + if !ivarRegex.MatchString(ivar.Name) { + return 0, fmt.Errorf("objc: Ivar must start with a lowercase letter and only contain ASCII letters and numbers: '%s'", ivar.Name) } - size := f.Type.Size() - alignment := uint8(math.Log2(float64(f.Type.Align()))) - enc, err := encodeType(f.Type, false) + size := ivar.Type.Size() + alignment := uint8(math.Log2(float64(ivar.Type.Align()))) + enc, err := encodeType(ivar.Type, false) if err != nil { - return 0, fmt.Errorf("objc: couldn't add Ivar %s: %w", f.Name, err) + return 0, fmt.Errorf("objc: couldn't add Ivar %s: %w", ivar.Name, err) } - if !class_addIvar(class, f.Name, size, alignment, enc) { - return 0, fmt.Errorf("objc: couldn't add Ivar %s", f.Name) + if !class_addIvar(class, ivar.Name, size, alignment, enc) { + return 0, fmt.Errorf("objc: couldn't add Ivar %s", ivar.Name) } - if offset := class.InstanceVariable(f.Name).Offset(); offset != f.Offset { - return 0, fmt.Errorf("objc: couldn't add Ivar %s because offset (%d != %d)", f.Name, offset, f.Offset) + offset := class.InstanceVariable(ivar.Name).Offset() + switch ivar.Attribute { + case ReadWrite: + ty := reflect.FuncOf( + []reflect.Type{ + reflect.TypeOf(ID(0)), reflect.TypeOf(SEL(0)), ivar.Type, + }, + nil, false, + ) + var encoding string + if encoding, err = encodeFunc(reflect.New(ty).Elem().Interface()); err != nil { + return 0, fmt.Errorf("objc: failed to create read method for '%s': %w", ivar.Name, err) + } + val := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) { + // on entry the first and second arguments are ID and SEL followed by the value + if len(args) != 3 { + panic(fmt.Sprintf("objc: incorrect number of args. expected 3 got %d", len(args))) + } + // The following reflect code does the equivalent of this: + // + // ((*struct { + // Padding [offset]byte + // Value int + // })(unsafe.Pointer(args[0].Interface().(ID)))).v = 123 + // + // However, since the type of the variable is unknown reflection is used to actually assign the value + id := args[0].Interface().(ID) + ptr := *(*unsafe.Pointer)(unsafe.Pointer(&id)) // circumvent go vet + reflect.NewAt(ivar.Type, unsafe.Add(ptr, offset)).Elem().Set(args[2]) + return nil + }).Interface() + // this code only works for ascii but that shouldn't be a problem + selector := "set" + string(unicode.ToUpper(rune(ivar.Name[0]))) + ivar.Name[1:] + ":\x00" + class.AddMethod(RegisterName(selector), NewIMP(val), encoding) + fallthrough // also implement the read method + case ReadOnly: + ty := reflect.FuncOf( + []reflect.Type{ + reflect.TypeOf(ID(0)), reflect.TypeOf(SEL(0)), + }, + []reflect.Type{ivar.Type}, false, + ) + var encoding string + if encoding, err = encodeFunc(reflect.New(ty).Elem().Interface()); err != nil { + return 0, fmt.Errorf("objc: failed to create read method for '%s': %w", ivar.Name, err) + } + val := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) { + // on entry the first and second arguments are ID and SEL + if len(args) != 2 { + panic(fmt.Sprintf("objc: incorrect number of args. expected 2 got %d", len(args))) + } + id := args[0].Interface().(ID) + ptr := *(*unsafe.Pointer)(unsafe.Pointer(&id)) // circumvent go vet + // the variable is located at an offset from the id + return []reflect.Value{reflect.NewAt(ivar.Type, unsafe.Add(ptr, offset)).Elem()} + }).Interface() + if ivar.Type.Kind() == reflect.Bool { + // this code only works for ascii but that shouldn't be a problem + ivar.Name = "is" + string(unicode.ToUpper(rune(ivar.Name[0]))) + ivar.Name[1:] + } + class.AddMethod(RegisterName(ivar.Name), NewIMP(val), encoding) + default: + return 0, fmt.Errorf("objc: unknown Ivar Attribute (%d)", ivar.Attribute) } } objc_registerClassPair(class) - if size1, size2 := class.InstanceSize(), strct.Size(); size1 != size2 { - return 0, fmt.Errorf("objc: sizes don't match %d != %d: %w", size1, size2, MismatchError) - } return class, nil } @@ -420,7 +403,7 @@ func encodeType(typ reflect.Type, insidePtr bool) (string, error) { if insidePtr { return encStructBegin + typ.Name() + encStructEnd, nil } - var encoding = encStructBegin + encoding := encStructBegin encoding += typ.Name() encoding += "=" for i := 0; i < typ.NumField(); i++ { @@ -543,20 +526,29 @@ func (i Ivar) Offset() uintptr { return ivar_getOffset(i) } +func (i Ivar) Name() string { + return ivar_getName(i) +} + // Protocol is a type that declares methods that can be implemented by any class. -type Protocol uintptr +type Protocol [0]func() // GetProtocol returns the protocol for the given name or nil if there is no protocol by that name. func GetProtocol(name string) *Protocol { return objc_getProtocol(name) } +// Equals return true if the two protocols are the same. +func (p *Protocol) Equals(p2 *Protocol) bool { + return protocol_isEqual(p, p2) +} + // IMP is a function pointer that can be called by Objective-C code. type IMP uintptr // NewIMP takes a Go function that takes (ID, SEL) as its first two arguments. -// ID may instead be a pointer to a struct whose first field has type Class. // It returns an IMP function pointer that can be called by Objective-C code. +// The function panics if an error occurs. // The function pointer is never deallocated. func NewIMP(fn interface{}) IMP { ty := reflect.TypeOf(fn) @@ -568,13 +560,9 @@ func NewIMP(fn interface{}) IMP { switch { case ty.NumIn() < 2: fallthrough - case ty.In(0).Kind() != reflect.Uintptr && // checks if it's objc.ID - // or that it's a pointer to a struct - (ty.In(0).Kind() != reflect.Pointer || ty.In(0).Elem().Kind() != reflect.Struct || - // and that the structs first field is an objc.Class - ty.In(0).Elem().Field(0).Type != reflect.TypeOf(Class(0))): + case ty.In(0) != reflect.TypeOf(ID(0)): fallthrough - case ty.In(1).Kind() != reflect.Uintptr: + case ty.In(1) != reflect.TypeOf(SEL(0)): panic("objc: NewIMP must take a (id, SEL) as its first two arguments; got " + ty.String()) } return IMP(purego.NewCallback(fn)) diff --git a/vendor/github.com/ebitengine/purego/struct_amd64.go b/vendor/github.com/ebitengine/purego/struct_amd64.go new file mode 100644 index 0000000..06a82dd --- /dev/null +++ b/vendor/github.com/ebitengine/purego/struct_amd64.go @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +package purego + +import ( + "math" + "reflect" + "unsafe" +) + +func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) { + outSize := outType.Size() + switch { + case outSize == 0: + return reflect.New(outType).Elem() + case outSize <= 8: + if isAllFloats(outType) { + // 2 float32s or 1 float64s are return in the float register + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.f1})).Elem() + } + // up to 8 bytes is returned in RAX + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.a1})).Elem() + case outSize <= 16: + r1, r2 := syscall.a1, syscall.a2 + if isAllFloats(outType) { + r1 = syscall.f1 + r2 = syscall.f2 + } else { + // check first 8 bytes if it's floats + hasFirstFloat := false + f1 := outType.Field(0).Type + if f1.Kind() == reflect.Float64 || f1.Kind() == reflect.Float32 && outType.Field(1).Type.Kind() == reflect.Float32 { + r1 = syscall.f1 + hasFirstFloat = true + } + + // find index of the field that starts the second 8 bytes + var i int + for i = 0; i < outType.NumField(); i++ { + if outType.Field(i).Offset == 8 { + break + } + } + + // check last 8 bytes if they are floats + f1 = outType.Field(i).Type + if f1.Kind() == reflect.Float64 || f1.Kind() == reflect.Float32 && i+1 == outType.NumField() { + r2 = syscall.f1 + } else if hasFirstFloat { + // if the first field was a float then that means the second integer field + // comes from the first integer register + r2 = syscall.a1 + } + } + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem() + default: + // create struct from the Go pointer created above + // weird pointer dereference to circumvent go vet + return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))).Elem() + } +} + +func isAllFloats(ty reflect.Type) bool { + for i := 0; i < ty.NumField(); i++ { + f := ty.Field(i) + switch f.Type.Kind() { + case reflect.Float64, reflect.Float32: + default: + return false + } + } + return true +} + +// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf +// https://gitlab.com/x86-psABIs/x86-64-ABI +// Class determines where the 8 byte value goes. +// Higher value classes win over lower value classes +const ( + _NO_CLASS = 0b0000 + _SSE = 0b0001 + _X87 = 0b0011 // long double not used in Go + _INTEGER = 0b0111 + _MEMORY = 0b1111 +) + +func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} { + if v.Type().Size() == 0 { + return keepAlive + } + + // if greater than 64 bytes place on stack + if v.Type().Size() > 8*8 { + placeStack(v, addStack) + return keepAlive + } + var ( + savedNumFloats = *numFloats + savedNumInts = *numInts + savedNumStack = *numStack + ) + placeOnStack := postMerger(v.Type()) || !tryPlaceRegister(v, addFloat, addInt) + if placeOnStack { + // reset any values placed in registers + *numFloats = savedNumFloats + *numInts = savedNumInts + *numStack = savedNumStack + placeStack(v, addStack) + } + return keepAlive +} + +func postMerger(t reflect.Type) bool { + // (c) If the size of the aggregate exceeds two eightbytes and the first eight- byte isn’t SSE or any other + // eightbyte isn’t SSEUP, the whole argument is passed in memory. + if t.Kind() != reflect.Struct { + return false + } + if t.Size() <= 2*8 { + return false + } + first := getFirst(t).Kind() + if first != reflect.Float32 && first != reflect.Float64 { + return false + } + return true +} + +func getFirst(t reflect.Type) reflect.Type { + first := t.Field(0).Type + if first.Kind() == reflect.Struct { + return getFirst(first) + } + return first +} + +func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) (ok bool) { + ok = true + var val uint64 + var shift byte // # of bits to shift + var flushed bool + class := _NO_CLASS + flushIfNeeded := func() { + if flushed { + return + } + flushed = true + if class == _SSE { + addFloat(uintptr(val)) + } else { + addInt(uintptr(val)) + } + val = 0 + shift = 0 + class = _NO_CLASS + } + var place func(v reflect.Value) + place = func(v reflect.Value) { + var numFields int + if v.Kind() == reflect.Struct { + numFields = v.Type().NumField() + } else { + numFields = v.Type().Len() + } + + for i := 0; i < numFields; i++ { + flushed = false + var f reflect.Value + if v.Kind() == reflect.Struct { + f = v.Field(i) + } else { + f = v.Index(i) + } + switch f.Kind() { + case reflect.Struct: + place(f) + case reflect.Bool: + if f.Bool() { + val |= 1 + } + shift += 8 + class |= _INTEGER + case reflect.Pointer: + ok = false + return + case reflect.Int8: + val |= uint64(f.Int()&0xFF) << shift + shift += 8 + class |= _INTEGER + case reflect.Int16: + val |= uint64(f.Int()&0xFFFF) << shift + shift += 16 + class |= _INTEGER + case reflect.Int32: + val |= uint64(f.Int()&0xFFFF_FFFF) << shift + shift += 32 + class |= _INTEGER + case reflect.Int64: + val = uint64(f.Int()) + shift = 64 + class = _INTEGER + case reflect.Uint8: + val |= f.Uint() << shift + shift += 8 + class |= _INTEGER + case reflect.Uint16: + val |= f.Uint() << shift + shift += 16 + class |= _INTEGER + case reflect.Uint32: + val |= f.Uint() << shift + shift += 32 + class |= _INTEGER + case reflect.Uint64: + val = f.Uint() + shift = 64 + class = _INTEGER + case reflect.Float32: + val |= uint64(math.Float32bits(float32(f.Float()))) << shift + shift += 32 + class |= _SSE + case reflect.Float64: + if v.Type().Size() > 16 { + ok = false + return + } + val = uint64(math.Float64bits(f.Float())) + shift = 64 + class = _SSE + case reflect.Array: + place(f) + default: + panic("purego: unsupported kind " + f.Kind().String()) + } + + if shift == 64 { + flushIfNeeded() + } else if shift > 64 { + // Should never happen, but may if we forget to reset shift after flush (or forget to flush), + // better fall apart here, than corrupt arguments. + panic("purego: tryPlaceRegisters shift > 64") + } + } + } + + place(v) + flushIfNeeded() + return ok +} + +func placeStack(v reflect.Value, addStack func(uintptr)) { + for i := 0; i < v.Type().NumField(); i++ { + f := v.Field(i) + switch f.Kind() { + case reflect.Pointer: + addStack(f.Pointer()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + addStack(uintptr(f.Int())) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + addStack(uintptr(f.Uint())) + case reflect.Float32: + addStack(uintptr(math.Float32bits(float32(f.Float())))) + case reflect.Float64: + addStack(uintptr(math.Float64bits(f.Float()))) + case reflect.Struct: + placeStack(f, addStack) + default: + panic("purego: unsupported kind " + f.Kind().String()) + } + } +} diff --git a/vendor/github.com/ebitengine/purego/struct_arm64.go b/vendor/github.com/ebitengine/purego/struct_arm64.go new file mode 100644 index 0000000..009d817 --- /dev/null +++ b/vendor/github.com/ebitengine/purego/struct_arm64.go @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +package purego + +import ( + "math" + "reflect" + "unsafe" +) + +func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) { + outSize := outType.Size() + switch { + case outSize == 0: + return reflect.New(outType).Elem() + case outSize <= 8: + r1 := syscall.a1 + if isAllSameFloat(outType) { + r1 = syscall.f1 + if outType.NumField() == 2 { + r1 = syscall.f2<<32 | syscall.f1 + } + } + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{r1})).Elem() + case outSize <= 16: + r1, r2 := syscall.a1, syscall.a2 + if isAllSameFloat(outType) { + switch outType.NumField() { + case 4: + r1 = syscall.f2<<32 | syscall.f1 + r2 = syscall.f4<<32 | syscall.f3 + case 3: + r1 = syscall.f2<<32 | syscall.f1 + r2 = syscall.f3 + case 2: + r1 = syscall.f1 + r2 = syscall.f2 + default: + panic("unreachable") + } + } + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem() + default: + if isAllSameFloat(outType) && outType.NumField() <= 4 { + switch outType.NumField() { + case 4: + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b, c, d uintptr }{syscall.f1, syscall.f2, syscall.f3, syscall.f4})).Elem() + case 3: + return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b, c uintptr }{syscall.f1, syscall.f2, syscall.f3})).Elem() + default: + panic("unreachable") + } + } + // create struct from the Go pointer created in arm64_r8 + // weird pointer dereference to circumvent go vet + return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.arm64_r8))).Elem() + } +} + +// https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst +const ( + _NO_CLASS = 0b00 + _FLOAT = 0b01 + _INT = 0b11 +) + +func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} { + if v.Type().Size() == 0 { + return keepAlive + } + + if hva, hfa, size := isHVA(v.Type()), isHFA(v.Type()), v.Type().Size(); hva || hfa || size <= 16 { + // if this doesn't fit entirely in registers then + // each element goes onto the stack + if hfa && *numFloats+v.NumField() > numOfFloats { + *numFloats = numOfFloats + } else if hva && *numInts+v.NumField() > numOfIntegerRegisters() { + *numInts = numOfIntegerRegisters() + } + + placeRegisters(v, addFloat, addInt) + } else { + keepAlive = placeStack(v, keepAlive, addInt) + } + return keepAlive // the struct was allocated so don't panic +} + +func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) { + var val uint64 + var shift byte + var flushed bool + class := _NO_CLASS + var place func(v reflect.Value) + place = func(v reflect.Value) { + var numFields int + if v.Kind() == reflect.Struct { + numFields = v.Type().NumField() + } else { + numFields = v.Type().Len() + } + for k := 0; k < numFields; k++ { + flushed = false + var f reflect.Value + if v.Kind() == reflect.Struct { + f = v.Field(k) + } else { + f = v.Index(k) + } + if shift >= 64 { + shift = 0 + flushed = true + if class == _FLOAT { + addFloat(uintptr(val)) + } else { + addInt(uintptr(val)) + } + } + switch f.Type().Kind() { + case reflect.Struct: + place(f) + case reflect.Bool: + if f.Bool() { + val |= 1 + } + shift += 8 + class |= _INT + case reflect.Uint8: + val |= f.Uint() << shift + shift += 8 + class |= _INT + case reflect.Uint16: + val |= f.Uint() << shift + shift += 16 + class |= _INT + case reflect.Uint32: + val |= f.Uint() << shift + shift += 32 + class |= _INT + case reflect.Uint64: + addInt(uintptr(f.Uint())) + shift = 0 + flushed = true + case reflect.Int8: + val |= uint64(f.Int()&0xFF) << shift + shift += 8 + class |= _INT + case reflect.Int16: + val |= uint64(f.Int()&0xFFFF) << shift + shift += 16 + class |= _INT + case reflect.Int32: + val |= uint64(f.Int()&0xFFFF_FFFF) << shift + shift += 32 + class |= _INT + case reflect.Int64: + addInt(uintptr(f.Int())) + shift = 0 + flushed = true + case reflect.Float32: + if class == _FLOAT { + addFloat(uintptr(val)) + val = 0 + shift = 0 + } + val |= uint64(math.Float32bits(float32(f.Float()))) << shift + shift += 32 + class |= _FLOAT + case reflect.Float64: + addFloat(uintptr(math.Float64bits(float64(f.Float())))) + shift = 0 + flushed = true + case reflect.Array: + place(f) + default: + panic("purego: unsupported kind " + f.Kind().String()) + } + } + } + place(v) + if !flushed { + if class == _FLOAT { + addFloat(uintptr(val)) + } else { + addInt(uintptr(val)) + } + } +} + +func placeStack(v reflect.Value, keepAlive []interface{}, addInt func(uintptr)) []interface{} { + // Struct is too big to be placed in registers. + // Copy to heap and place the pointer in register + ptrStruct := reflect.New(v.Type()) + ptrStruct.Elem().Set(v) + ptr := ptrStruct.Elem().Addr().UnsafePointer() + keepAlive = append(keepAlive, ptr) + addInt(uintptr(ptr)) + return keepAlive +} + +// isHFA reports a Homogeneous Floating-point Aggregate (HFA) which is a Fundamental Data Type that is a +// Floating-Point type and at most four uniquely addressable members (5.9.5.1 in [Arm64 Calling Convention]). +// This type of struct will be placed more compactly than the individual fields. +// +// [Arm64 Calling Convention]: https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst +func isHFA(t reflect.Type) bool { + // round up struct size to nearest 8 see section B.4 + structSize := roundUpTo8(t.Size()) + if structSize == 0 || t.NumField() > 4 { + return false + } + first := t.Field(0) + switch first.Type.Kind() { + case reflect.Float32, reflect.Float64: + firstKind := first.Type.Kind() + for i := 0; i < t.NumField(); i++ { + if t.Field(i).Type.Kind() != firstKind { + return false + } + } + return true + case reflect.Array: + switch first.Type.Elem().Kind() { + case reflect.Float32, reflect.Float64: + return true + default: + return false + } + case reflect.Struct: + for i := 0; i < first.Type.NumField(); i++ { + if !isHFA(first.Type) { + return false + } + } + return true + default: + return false + } +} + +// isHVA reports a Homogeneous Aggregate with a Fundamental Data Type that is a Short-Vector type +// and at most four uniquely addressable members (5.9.5.2 in [Arm64 Calling Convention]). +// A short vector is a machine type that is composed of repeated instances of one fundamental integral or +// floating-point type. It may be 8 or 16 bytes in total size (5.4 in [Arm64 Calling Convention]). +// This type of struct will be placed more compactly than the individual fields. +// +// [Arm64 Calling Convention]: https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst +func isHVA(t reflect.Type) bool { + // round up struct size to nearest 8 see section B.4 + structSize := roundUpTo8(t.Size()) + if structSize == 0 || (structSize != 8 && structSize != 16) { + return false + } + first := t.Field(0) + switch first.Type.Kind() { + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32: + firstKind := first.Type.Kind() + for i := 0; i < t.NumField(); i++ { + if t.Field(i).Type.Kind() != firstKind { + return false + } + } + return true + case reflect.Array: + switch first.Type.Elem().Kind() { + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32: + return true + default: + return false + } + default: + return false + } +} diff --git a/vendor/github.com/ebitengine/purego/struct_other.go b/vendor/github.com/ebitengine/purego/struct_other.go new file mode 100644 index 0000000..9d42ada --- /dev/null +++ b/vendor/github.com/ebitengine/purego/struct_other.go @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2024 The Ebitengine Authors + +//go:build !amd64 && !arm64 + +package purego + +import "reflect" + +func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []interface{}) []interface{} { + panic("purego: struct arguments are not supported") +} + +func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) { + panic("purego: struct returns are not supported") +} diff --git a/vendor/github.com/ebitengine/purego/sys_amd64.s b/vendor/github.com/ebitengine/purego/sys_amd64.s index 373046d..4eb26d6 100644 --- a/vendor/github.com/ebitengine/purego/sys_amd64.s +++ b/vendor/github.com/ebitengine/purego/sys_amd64.s @@ -1,15 +1,18 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || (!cgo && linux) +//go:build darwin || freebsd || linux #include "textflag.h" -#include "internal/abi/abi_amd64.h" +#include "abi_amd64.h" #include "go_asm.h" #include "funcdata.h" -// syscall9X calls a function in libc on behalf of the syscall package. -// syscall9X takes a pointer to a struct like: +#define STACK_SIZE 80 +#define PTR_ADDRESS (STACK_SIZE - 8) + +// syscall15X calls a function in libc on behalf of the syscall package. +// syscall15X takes a pointer to a struct like: // struct { // fn uintptr // a1 uintptr @@ -21,64 +24,83 @@ // a7 uintptr // a8 uintptr // a9 uintptr +// a10 uintptr +// a11 uintptr +// a12 uintptr +// a13 uintptr +// a14 uintptr +// a15 uintptr // r1 uintptr // r2 uintptr // err uintptr // } -// syscall9X must be called on the g0 stack with the +// syscall15X must be called on the g0 stack with the // C calling convention (use libcCall). -GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 -DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) -TEXT syscall9X(SB), NOSPLIT|NOFRAME, $0 +GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8 +DATA ·syscall15XABI0(SB)/8, $syscall15X(SB) +TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0 PUSHQ BP MOVQ SP, BP - SUBQ $32, SP - MOVQ DI, 24(BP) // save the pointer - - MOVQ syscall9Args_f1(DI), X0 // f1 - MOVQ syscall9Args_f2(DI), X1 // f2 - MOVQ syscall9Args_f3(DI), X2 // f3 - MOVQ syscall9Args_f4(DI), X3 // f4 - MOVQ syscall9Args_f5(DI), X4 // f5 - MOVQ syscall9Args_f6(DI), X5 // f6 - MOVQ syscall9Args_f7(DI), X6 // f7 - MOVQ syscall9Args_f8(DI), X7 // f8 - - MOVQ syscall9Args_fn(DI), R10 // fn - MOVQ syscall9Args_a2(DI), SI // a2 - MOVQ syscall9Args_a3(DI), DX // a3 - MOVQ syscall9Args_a4(DI), CX // a4 - MOVQ syscall9Args_a5(DI), R8 // a5 - MOVQ syscall9Args_a6(DI), R9 // a6 - MOVQ syscall9Args_a7(DI), R11 // a7 - MOVQ syscall9Args_a8(DI), R12 // a8 - MOVQ syscall9Args_a9(DI), R13 // a9 - MOVQ syscall9Args_a1(DI), DI // a1 + SUBQ $STACK_SIZE, SP + MOVQ DI, PTR_ADDRESS(BP) // save the pointer + MOVQ DI, R11 + + MOVQ syscall15Args_f1(R11), X0 // f1 + MOVQ syscall15Args_f2(R11), X1 // f2 + MOVQ syscall15Args_f3(R11), X2 // f3 + MOVQ syscall15Args_f4(R11), X3 // f4 + MOVQ syscall15Args_f5(R11), X4 // f5 + MOVQ syscall15Args_f6(R11), X5 // f6 + MOVQ syscall15Args_f7(R11), X6 // f7 + MOVQ syscall15Args_f8(R11), X7 // f8 + + MOVQ syscall15Args_a1(R11), DI // a1 + MOVQ syscall15Args_a2(R11), SI // a2 + MOVQ syscall15Args_a3(R11), DX // a3 + MOVQ syscall15Args_a4(R11), CX // a4 + MOVQ syscall15Args_a5(R11), R8 // a5 + MOVQ syscall15Args_a6(R11), R9 // a6 // push the remaining paramters onto the stack - MOVQ R11, 0(SP) // push a7 - MOVQ R12, 8(SP) // push a8 - MOVQ R13, 16(SP) // push a9 - XORL AX, AX // vararg: say "no float args" - + MOVQ syscall15Args_a7(R11), R12 + MOVQ R12, 0(SP) // push a7 + MOVQ syscall15Args_a8(R11), R12 + MOVQ R12, 8(SP) // push a8 + MOVQ syscall15Args_a9(R11), R12 + MOVQ R12, 16(SP) // push a9 + MOVQ syscall15Args_a10(R11), R12 + MOVQ R12, 24(SP) // push a10 + MOVQ syscall15Args_a11(R11), R12 + MOVQ R12, 32(SP) // push a11 + MOVQ syscall15Args_a12(R11), R12 + MOVQ R12, 40(SP) // push a12 + MOVQ syscall15Args_a13(R11), R12 + MOVQ R12, 48(SP) // push a13 + MOVQ syscall15Args_a14(R11), R12 + MOVQ R12, 56(SP) // push a14 + MOVQ syscall15Args_a15(R11), R12 + MOVQ R12, 64(SP) // push a15 + XORL AX, AX // vararg: say "no float args" + + MOVQ syscall15Args_fn(R11), R10 // fn CALL R10 - MOVQ 24(BP), DI // get the pointer back - MOVQ AX, syscall9Args_r1(DI) // r1 - MOVQ X0, syscall9Args_r2(DI) // r2 + MOVQ PTR_ADDRESS(BP), DI // get the pointer back + MOVQ AX, syscall15Args_a1(DI) // r1 + MOVQ DX, syscall15Args_a2(DI) // r3 + MOVQ X0, syscall15Args_f1(DI) // f1 + MOVQ X1, syscall15Args_f2(DI) // f2 - XORL AX, AX // no error (it's ignored anyway) - ADDQ $32, SP + XORL AX, AX // no error (it's ignored anyway) + ADDQ $STACK_SIZE, SP MOVQ BP, SP POPQ BP RET TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 - // remove return address from stack, we are not returning to callbackasm, but to its caller. - MOVQ 0(SP), AX - ADDQ $8, SP - - MOVQ 0(SP), R10 // get the return SP so that we can align register args with stack args + MOVQ 0(SP), AX // save the return address to calculate the cb index + MOVQ 8(SP), R10 // get the return SP so that we can align register args with stack args + ADDQ $8, SP // remove return address from stack, we are not returning to callbackasm, but to its caller. // make space for first six int and 8 float arguments below the frame ADJSP $14*8, SP @@ -98,7 +120,7 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 MOVQ R9, (14*8)(SP) LEAQ 8(SP), R8 // R8 = address of args vector - MOVQ R10, 0(SP) // push the stack pointer below registers + PUSHQ R10 // push the stack pointer below registers // determine index into runtime·cbs table MOVQ $callbackasm(SB), DX @@ -134,8 +156,7 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 POP_REGS_HOST_TO_ABI0() - MOVQ 0(SP), R10 // get the SP back - + POPQ R10 // get the SP back ADJSP $-14*8, SP // remove arguments MOVQ R10, 0(SP) diff --git a/vendor/github.com/ebitengine/purego/sys_arm64.s b/vendor/github.com/ebitengine/purego/sys_arm64.s index 942fd56..a68fdb9 100644 --- a/vendor/github.com/ebitengine/purego/sys_arm64.s +++ b/vendor/github.com/ebitengine/purego/sys_arm64.s @@ -1,15 +1,17 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || (!cgo && linux) || windows +//go:build darwin || freebsd || linux || windows #include "textflag.h" #include "go_asm.h" #include "funcdata.h" -#include "internal/abi/abi_arm64.h" -// syscall9X calls a function in libc on behalf of the syscall package. -// syscall9X takes a pointer to a struct like: +#define STACK_SIZE 64 +#define PTR_ADDRESS (STACK_SIZE - 8) + +// syscall15X calls a function in libc on behalf of the syscall package. +// syscall15X takes a pointer to a struct like: // struct { // fn uintptr // a1 uintptr @@ -21,44 +23,70 @@ // a7 uintptr // a8 uintptr // a9 uintptr +// a10 uintptr +// a11 uintptr +// a12 uintptr +// a13 uintptr +// a14 uintptr +// a15 uintptr // r1 uintptr // r2 uintptr // err uintptr // } -// syscall9X must be called on the g0 stack with the +// syscall15X must be called on the g0 stack with the // C calling convention (use libcCall). -GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8 -DATA ·syscall9XABI0(SB)/8, $syscall9X(SB) -TEXT syscall9X(SB), NOSPLIT, $0 - SUB $16, RSP // push structure pointer - MOVD R0, 8(RSP) +GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8 +DATA ·syscall15XABI0(SB)/8, $syscall15X(SB) +TEXT syscall15X(SB), NOSPLIT, $0 + SUB $STACK_SIZE, RSP // push structure pointer + MOVD R0, PTR_ADDRESS(RSP) + MOVD R0, R9 + + FMOVD syscall15Args_f1(R9), F0 // f1 + FMOVD syscall15Args_f2(R9), F1 // f2 + FMOVD syscall15Args_f3(R9), F2 // f3 + FMOVD syscall15Args_f4(R9), F3 // f4 + FMOVD syscall15Args_f5(R9), F4 // f5 + FMOVD syscall15Args_f6(R9), F5 // f6 + FMOVD syscall15Args_f7(R9), F6 // f7 + FMOVD syscall15Args_f8(R9), F7 // f8 + + MOVD syscall15Args_a1(R9), R0 // a1 + MOVD syscall15Args_a2(R9), R1 // a2 + MOVD syscall15Args_a3(R9), R2 // a3 + MOVD syscall15Args_a4(R9), R3 // a4 + MOVD syscall15Args_a5(R9), R4 // a5 + MOVD syscall15Args_a6(R9), R5 // a6 + MOVD syscall15Args_a7(R9), R6 // a7 + MOVD syscall15Args_a8(R9), R7 // a8 + MOVD syscall15Args_arm64_r8(R9), R8 // r8 - FMOVD syscall9Args_f1(R0), F0 // f1 - FMOVD syscall9Args_f2(R0), F1 // f2 - FMOVD syscall9Args_f3(R0), F2 // f3 - FMOVD syscall9Args_f4(R0), F3 // f4 - FMOVD syscall9Args_f5(R0), F4 // f5 - FMOVD syscall9Args_f6(R0), F5 // f6 - FMOVD syscall9Args_f7(R0), F6 // f7 - FMOVD syscall9Args_f8(R0), F7 // f8 + MOVD syscall15Args_a9(R9), R10 + MOVD R10, 0(RSP) // push a9 onto stack + MOVD syscall15Args_a10(R9), R10 + MOVD R10, 8(RSP) // push a10 onto stack + MOVD syscall15Args_a11(R9), R10 + MOVD R10, 16(RSP) // push a11 onto stack + MOVD syscall15Args_a12(R9), R10 + MOVD R10, 24(RSP) // push a12 onto stack + MOVD syscall15Args_a13(R9), R10 + MOVD R10, 32(RSP) // push a13 onto stack + MOVD syscall15Args_a14(R9), R10 + MOVD R10, 40(RSP) // push a14 onto stack + MOVD syscall15Args_a15(R9), R10 + MOVD R10, 48(RSP) // push a15 onto stack - MOVD syscall9Args_fn(R0), R12 // fn - MOVD syscall9Args_a2(R0), R1 // a2 - MOVD syscall9Args_a3(R0), R2 // a3 - MOVD syscall9Args_a4(R0), R3 // a4 - MOVD syscall9Args_a5(R0), R4 // a5 - MOVD syscall9Args_a6(R0), R5 // a6 - MOVD syscall9Args_a7(R0), R6 // a7 - MOVD syscall9Args_a8(R0), R7 // a8 - MOVD syscall9Args_a9(R0), R8 // a9 - MOVD syscall9Args_a1(R0), R0 // a1 + MOVD syscall15Args_fn(R9), R10 // fn + BL (R10) - MOVD R8, (RSP) // push a9 onto stack + MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer + ADD $STACK_SIZE, RSP - BL (R12) + MOVD R0, syscall15Args_a1(R2) // save r1 + MOVD R1, syscall15Args_a2(R2) // save r3 + FMOVD F0, syscall15Args_f1(R2) // save f0 + FMOVD F1, syscall15Args_f2(R2) // save f1 + FMOVD F2, syscall15Args_f3(R2) // save f2 + FMOVD F3, syscall15Args_f4(R2) // save f3 - MOVD 8(RSP), R2 // pop structure pointer - ADD $16, RSP - MOVD R0, syscall9Args_r1(R2) // save r1 - FMOVD F0, syscall9Args_r2(R2) // save r2 RET diff --git a/vendor/github.com/ebitengine/purego/sys_unix_arm64.s b/vendor/github.com/ebitengine/purego/sys_unix_arm64.s index d4281f7..6da06b4 100644 --- a/vendor/github.com/ebitengine/purego/sys_unix_arm64.s +++ b/vendor/github.com/ebitengine/purego/sys_unix_arm64.s @@ -1,12 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 The Ebitengine Authors -//go:build darwin || (!cgo && linux) +//go:build darwin || freebsd || linux #include "textflag.h" #include "go_asm.h" #include "funcdata.h" -#include "internal/abi/abi_arm64.h" +#include "abi_arm64.h" TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 NO_LOCAL_POINTERS @@ -17,31 +17,37 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 // Save callback register arguments R0-R7 and F0-F7. // We do this at the top of the frame so they're contiguous with stack arguments. SUB $(16*8), RSP, R14 - FMOVD F0, (0*8)(R14) - FMOVD F1, (1*8)(R14) - FMOVD F2, (2*8)(R14) - FMOVD F3, (3*8)(R14) - FMOVD F4, (4*8)(R14) - FMOVD F5, (5*8)(R14) - FMOVD F6, (6*8)(R14) - FMOVD F7, (7*8)(R14) + FSTPD (F0, F1), (0*8)(R14) + FSTPD (F2, F3), (2*8)(R14) + FSTPD (F4, F5), (4*8)(R14) + FSTPD (F6, F7), (6*8)(R14) STP (R0, R1), (8*8)(R14) STP (R2, R3), (10*8)(R14) STP (R4, R5), (12*8)(R14) STP (R6, R7), (14*8)(R14) // Adjust SP by frame size. - // crosscall2 clobbers FP in the frame record so only save/restore SP. - SUB $(28*8), RSP - MOVD R30, (RSP) + SUB $(26*8), RSP + + // It is important to save R27 because the go assembler + // uses it for move instructions for a variable. + // This line: + // MOVD ·callbackWrap_call(SB), R0 + // Creates the instructions: + // ADRP 14335(PC), R27 + // MOVD 388(27), R0 + // R27 is a callee saved register so we are responsible + // for ensuring its value doesn't change. So save it and + // restore it at the end of this function. + // R30 is the link register. crosscall2 doesn't save it + // so it's saved here. + STP (R27, R30), 0(RSP) // Create a struct callbackArgs on our stack. - ADD $(callbackArgs__size + 3*8), RSP, R13 - MOVD R12, callbackArgs_index(R13) // callback index - MOVD R14, R0 - MOVD R0, callbackArgs_args(R13) // address of args vector - MOVD $0, R0 - MOVD R0, callbackArgs_result(R13) // result + MOVD $(callbackArgs__size)(RSP), R13 + MOVD R12, callbackArgs_index(R13) // callback index + MOVD R14, callbackArgs_args(R13) // address of args vector + MOVD ZR, callbackArgs_result(R13) // result // Move parameters into registers // Get the ABIInternal function pointer @@ -54,11 +60,11 @@ TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0 BL crosscall2(SB) // Get callback result. - ADD $(callbackArgs__size + 3*8), RSP, R13 + MOVD $(callbackArgs__size)(RSP), R13 MOVD callbackArgs_result(R13), R0 - // Restore SP - MOVD (RSP), R30 - ADD $(28*8), RSP + // Restore LR and R27 + LDP 0(RSP), (R27, R30) + ADD $(26*8), RSP RET diff --git a/vendor/github.com/ebitengine/purego/syscall.go b/vendor/github.com/ebitengine/purego/syscall.go index d14fdb0..f38e4a2 100644 --- a/vendor/github.com/ebitengine/purego/syscall.go +++ b/vendor/github.com/ebitengine/purego/syscall.go @@ -1,12 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || windows || linux +//go:build darwin || freebsd || linux || windows package purego const ( - maxArgs = 9 + maxArgs = 15 numOfFloats = 8 // arm64 and amd64 both have 8 float registers ) @@ -36,5 +36,5 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { // add padding so there is no out-of-bounds slicing var tmp [maxArgs]uintptr copy(tmp[:], args) - return syscall_syscall9X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8]) + return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14]) } diff --git a/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go b/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go index 59c9a00..ee2bb21 100644 --- a/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go +++ b/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build cgo +//go:build cgo && !(amd64 || arm64) package purego @@ -11,20 +11,21 @@ import ( "github.com/ebitengine/purego/internal/cgo" ) -var syscall9XABI0 = uintptr(cgo.Syscall9XABI0) +var syscall15XABI0 = uintptr(cgo.Syscall15XABI0) // this is only here to make the assembly files happy :) -type syscall9Args struct { - fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr - f1, f2, f3, f4, f5, f6, f7, f8 uintptr - r1, r2, err uintptr +type syscall15Args struct { + fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr + f1, f2, f3, f4, f5, f6, f7, f8 uintptr + r1, r2, err uintptr + arm64_r8 uintptr } //go:nosplit -func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { - return cgo.Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9) +func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) { + return cgo.Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } func NewCallback(_ interface{}) uintptr { - panic("purego: NewCallback not supported") + panic("purego: NewCallback on Linux is only supported on amd64/arm64") } diff --git a/vendor/github.com/ebitengine/purego/syscall_sysv.go b/vendor/github.com/ebitengine/purego/syscall_sysv.go index 9e7e507..f41234b 100644 --- a/vendor/github.com/ebitengine/purego/syscall_sysv.go +++ b/vendor/github.com/ebitengine/purego/syscall_sysv.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors -//go:build darwin || (!cgo && linux && (amd64 || arm64)) +//go:build darwin || freebsd || (linux && (amd64 || arm64)) package purego @@ -12,23 +12,23 @@ import ( "unsafe" ) -var syscall9XABI0 uintptr +var syscall15XABI0 uintptr -type syscall9Args struct { - fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr - f1, f2, f3, f4, f5, f6, f7, f8 uintptr - r1, r2, err uintptr +type syscall15Args struct { + fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr + f1, f2, f3, f4, f5, f6, f7, f8 uintptr + arm64_r8 uintptr } //go:nosplit -func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { - args := syscall9Args{ - fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, +func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) { + args := syscall15Args{ + fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a1, a2, a3, a4, a5, a6, a7, a8, - r1, r2, err, + 0, } - runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args)) - return args.r1, args.r2, args.err + runtime_cgocall(syscall15XABI0, unsafe.Pointer(&args)) + return args.a1, args.a2, 0 } // NewCallback converts a Go function to a function pointer conforming to the C calling convention. @@ -37,12 +37,7 @@ func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, // of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated // for these callbacks is never released. At least 2000 callbacks can always be created. Although this function // provides similar functionality to windows.NewCallback it is distinct. -// -// NOTE: Linux is currently not supported and will panic if called. func NewCallback(fn interface{}) uintptr { - if runtime.GOOS == "linux" { - panic("purego: NewCallback not supported") - } return compileCallback(fn) } diff --git a/vendor/github.com/ebitengine/purego/syscall_windows.go b/vendor/github.com/ebitengine/purego/syscall_windows.go index a4db9f1..a45693f 100644 --- a/vendor/github.com/ebitengine/purego/syscall_windows.go +++ b/vendor/github.com/ebitengine/purego/syscall_windows.go @@ -10,16 +10,16 @@ import ( "golang.org/x/sys/windows" ) -var syscall9XABI0 uintptr +var syscall15XABI0 uintptr -type syscall9Args struct { - fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr - f1, f2, f3, f4, f5, f6, f7, f8 uintptr - r1, r2, err uintptr +type syscall15Args struct { + fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr + f1, f2, f3, f4, f5, f6, f7, f8 uintptr + arm64_r8 uintptr } -func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { - r1, r2, errno := syscall.Syscall9(fn, 9, a1, a2, a3, a4, a5, a6, a7, a8, a9) +func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) { + r1, r2, errno := syscall.Syscall15(fn, 15, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) return r1, r2, uintptr(errno) } diff --git a/vendor/github.com/ebitengine/purego/zcallback_amd64.s b/vendor/github.com/ebitengine/purego/zcallback_amd64.s index d657775..6a778bf 100644 --- a/vendor/github.com/ebitengine/purego/zcallback_amd64.s +++ b/vendor/github.com/ebitengine/purego/zcallback_amd64.s @@ -1,6 +1,6 @@ // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. -//go:build darwin || (!cgo && linux) +//go:build darwin || freebsd || linux // runtime·callbackasm is called by external code to // execute Go implemented callback function. It is not diff --git a/vendor/github.com/ebitengine/purego/zcallback_arm64.s b/vendor/github.com/ebitengine/purego/zcallback_arm64.s index 87f4a54..c079b80 100644 --- a/vendor/github.com/ebitengine/purego/zcallback_arm64.s +++ b/vendor/github.com/ebitengine/purego/zcallback_arm64.s @@ -1,6 +1,6 @@ // Code generated by wincallback.go using 'go generate'. DO NOT EDIT. -//go:build darwin || (!cgo && linux) +//go:build darwin || freebsd || linux // External code calls into callbackasm at an offset corresponding // to the callback index. Callbackasm is a table of MOV and B instructions. diff --git a/vendor/github.com/erikgeiser/coninput/.gitignore b/vendor/github.com/erikgeiser/coninput/.gitignore new file mode 100644 index 0000000..66fd13c --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/erikgeiser/coninput/.golangci.yml b/vendor/github.com/erikgeiser/coninput/.golangci.yml new file mode 100644 index 0000000..d3ed710 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/.golangci.yml @@ -0,0 +1,24 @@ +linters: + enable-all: true + disable: + - golint + - interfacer + - scopelint + - maligned + - rowserrcheck + - funlen + - depguard + - goerr113 + - exhaustivestruct + - testpackage + - gochecknoglobals + - wrapcheck + - forbidigo + - ifshort + - cyclop + - gomoddirectives +linters-settings: + exhaustive: + default-signifies-exhaustive: true +issues: + exclude-use-default: false diff --git a/vendor/github.com/erikgeiser/coninput/LICENSE b/vendor/github.com/erikgeiser/coninput/LICENSE new file mode 100644 index 0000000..83c2440 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Erik G. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/erikgeiser/coninput/README.md b/vendor/github.com/erikgeiser/coninput/README.md new file mode 100644 index 0000000..22619d1 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/README.md @@ -0,0 +1,2 @@ +# coninput +Go library for input handling using Windows Console API diff --git a/vendor/github.com/erikgeiser/coninput/keycodes.go b/vendor/github.com/erikgeiser/coninput/keycodes.go new file mode 100644 index 0000000..902ee1b --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/keycodes.go @@ -0,0 +1,205 @@ +package coninput + +// VirtualKeyCode holds a virtual key code (see +// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). +type VirtualKeyCode uint16 + +const ( + VK_LBUTTON VirtualKeyCode = 0x01 + VK_RBUTTON VirtualKeyCode = 0x02 + VK_CANCEL VirtualKeyCode = 0x03 + VK_MBUTTON VirtualKeyCode = 0x04 + VK_XBUTTON1 VirtualKeyCode = 0x05 + VK_XBUTTON2 VirtualKeyCode = 0x06 + VK_BACK VirtualKeyCode = 0x08 + VK_TAB VirtualKeyCode = 0x09 + VK_CLEAR VirtualKeyCode = 0x0C + VK_RETURN VirtualKeyCode = 0x0D + VK_SHIFT VirtualKeyCode = 0x10 + VK_CONTROL VirtualKeyCode = 0x11 + VK_MENU VirtualKeyCode = 0x12 + VK_PAUSE VirtualKeyCode = 0x13 + VK_CAPITAL VirtualKeyCode = 0x14 + VK_KANA VirtualKeyCode = 0x15 + VK_HANGEUL VirtualKeyCode = 0x15 + VK_HANGUL VirtualKeyCode = 0x15 + VK_IME_ON VirtualKeyCode = 0x16 + VK_JUNJA VirtualKeyCode = 0x17 + VK_FINAL VirtualKeyCode = 0x18 + VK_HANJA VirtualKeyCode = 0x19 + VK_KANJI VirtualKeyCode = 0x19 + VK_IME_OFF VirtualKeyCode = 0x1A + VK_ESCAPE VirtualKeyCode = 0x1B + VK_CONVERT VirtualKeyCode = 0x1C + VK_NONCONVERT VirtualKeyCode = 0x1D + VK_ACCEPT VirtualKeyCode = 0x1E + VK_MODECHANGE VirtualKeyCode = 0x1F + VK_SPACE VirtualKeyCode = 0x20 + VK_PRIOR VirtualKeyCode = 0x21 + VK_NEXT VirtualKeyCode = 0x22 + VK_END VirtualKeyCode = 0x23 + VK_HOME VirtualKeyCode = 0x24 + VK_LEFT VirtualKeyCode = 0x25 + VK_UP VirtualKeyCode = 0x26 + VK_RIGHT VirtualKeyCode = 0x27 + VK_DOWN VirtualKeyCode = 0x28 + VK_SELECT VirtualKeyCode = 0x29 + VK_PRINT VirtualKeyCode = 0x2A + VK_EXECUTE VirtualKeyCode = 0x2B + VK_SNAPSHOT VirtualKeyCode = 0x2C + VK_INSERT VirtualKeyCode = 0x2D + VK_DELETE VirtualKeyCode = 0x2E + VK_HELP VirtualKeyCode = 0x2F + VK_0 VirtualKeyCode = 0x30 + VK_1 VirtualKeyCode = 0x31 + VK_2 VirtualKeyCode = 0x32 + VK_3 VirtualKeyCode = 0x33 + VK_4 VirtualKeyCode = 0x34 + VK_5 VirtualKeyCode = 0x35 + VK_6 VirtualKeyCode = 0x36 + VK_7 VirtualKeyCode = 0x37 + VK_8 VirtualKeyCode = 0x38 + VK_9 VirtualKeyCode = 0x39 + VK_A VirtualKeyCode = 0x41 + VK_B VirtualKeyCode = 0x42 + VK_C VirtualKeyCode = 0x43 + VK_D VirtualKeyCode = 0x44 + VK_E VirtualKeyCode = 0x45 + VK_F VirtualKeyCode = 0x46 + VK_G VirtualKeyCode = 0x47 + VK_H VirtualKeyCode = 0x48 + VK_I VirtualKeyCode = 0x49 + VK_J VirtualKeyCode = 0x4A + VK_K VirtualKeyCode = 0x4B + VK_L VirtualKeyCode = 0x4C + VK_M VirtualKeyCode = 0x4D + VK_N VirtualKeyCode = 0x4E + VK_O VirtualKeyCode = 0x4F + VK_P VirtualKeyCode = 0x50 + VK_Q VirtualKeyCode = 0x51 + VK_R VirtualKeyCode = 0x52 + VK_S VirtualKeyCode = 0x53 + VK_T VirtualKeyCode = 0x54 + VK_U VirtualKeyCode = 0x55 + VK_V VirtualKeyCode = 0x56 + VK_W VirtualKeyCode = 0x57 + VK_X VirtualKeyCode = 0x58 + VK_Y VirtualKeyCode = 0x59 + VK_Z VirtualKeyCode = 0x5A + VK_LWIN VirtualKeyCode = 0x5B + VK_RWIN VirtualKeyCode = 0x5C + VK_APPS VirtualKeyCode = 0x5D + VK_SLEEP VirtualKeyCode = 0x5F + VK_NUMPAD0 VirtualKeyCode = 0x60 + VK_NUMPAD1 VirtualKeyCode = 0x61 + VK_NUMPAD2 VirtualKeyCode = 0x62 + VK_NUMPAD3 VirtualKeyCode = 0x63 + VK_NUMPAD4 VirtualKeyCode = 0x64 + VK_NUMPAD5 VirtualKeyCode = 0x65 + VK_NUMPAD6 VirtualKeyCode = 0x66 + VK_NUMPAD7 VirtualKeyCode = 0x67 + VK_NUMPAD8 VirtualKeyCode = 0x68 + VK_NUMPAD9 VirtualKeyCode = 0x69 + VK_MULTIPLY VirtualKeyCode = 0x6A + VK_ADD VirtualKeyCode = 0x6B + VK_SEPARATOR VirtualKeyCode = 0x6C + VK_SUBTRACT VirtualKeyCode = 0x6D + VK_DECIMAL VirtualKeyCode = 0x6E + VK_DIVIDE VirtualKeyCode = 0x6F + VK_F1 VirtualKeyCode = 0x70 + VK_F2 VirtualKeyCode = 0x71 + VK_F3 VirtualKeyCode = 0x72 + VK_F4 VirtualKeyCode = 0x73 + VK_F5 VirtualKeyCode = 0x74 + VK_F6 VirtualKeyCode = 0x75 + VK_F7 VirtualKeyCode = 0x76 + VK_F8 VirtualKeyCode = 0x77 + VK_F9 VirtualKeyCode = 0x78 + VK_F10 VirtualKeyCode = 0x79 + VK_F11 VirtualKeyCode = 0x7A + VK_F12 VirtualKeyCode = 0x7B + VK_F13 VirtualKeyCode = 0x7C + VK_F14 VirtualKeyCode = 0x7D + VK_F15 VirtualKeyCode = 0x7E + VK_F16 VirtualKeyCode = 0x7F + VK_F17 VirtualKeyCode = 0x80 + VK_F18 VirtualKeyCode = 0x81 + VK_F19 VirtualKeyCode = 0x82 + VK_F20 VirtualKeyCode = 0x83 + VK_F21 VirtualKeyCode = 0x84 + VK_F22 VirtualKeyCode = 0x85 + VK_F23 VirtualKeyCode = 0x86 + VK_F24 VirtualKeyCode = 0x87 + VK_NUMLOCK VirtualKeyCode = 0x90 + VK_SCROLL VirtualKeyCode = 0x91 + VK_OEM_NEC_EQUAL VirtualKeyCode = 0x92 + VK_OEM_FJ_JISHO VirtualKeyCode = 0x92 + VK_OEM_FJ_MASSHOU VirtualKeyCode = 0x93 + VK_OEM_FJ_TOUROKU VirtualKeyCode = 0x94 + VK_OEM_FJ_LOYA VirtualKeyCode = 0x95 + VK_OEM_FJ_ROYA VirtualKeyCode = 0x96 + VK_LSHIFT VirtualKeyCode = 0xA0 + VK_RSHIFT VirtualKeyCode = 0xA1 + VK_LCONTROL VirtualKeyCode = 0xA2 + VK_RCONTROL VirtualKeyCode = 0xA3 + VK_LMENU VirtualKeyCode = 0xA4 + VK_RMENU VirtualKeyCode = 0xA5 + VK_BROWSER_BACK VirtualKeyCode = 0xA6 + VK_BROWSER_FORWARD VirtualKeyCode = 0xA7 + VK_BROWSER_REFRESH VirtualKeyCode = 0xA8 + VK_BROWSER_STOP VirtualKeyCode = 0xA9 + VK_BROWSER_SEARCH VirtualKeyCode = 0xAA + VK_BROWSER_FAVORITES VirtualKeyCode = 0xAB + VK_BROWSER_HOME VirtualKeyCode = 0xAC + VK_VOLUME_MUTE VirtualKeyCode = 0xAD + VK_VOLUME_DOWN VirtualKeyCode = 0xAE + VK_VOLUME_UP VirtualKeyCode = 0xAF + VK_MEDIA_NEXT_TRACK VirtualKeyCode = 0xB0 + VK_MEDIA_PREV_TRACK VirtualKeyCode = 0xB1 + VK_MEDIA_STOP VirtualKeyCode = 0xB2 + VK_MEDIA_PLAY_PAUSE VirtualKeyCode = 0xB3 + VK_LAUNCH_MAIL VirtualKeyCode = 0xB4 + VK_LAUNCH_MEDIA_SELECT VirtualKeyCode = 0xB5 + VK_LAUNCH_APP1 VirtualKeyCode = 0xB6 + VK_LAUNCH_APP2 VirtualKeyCode = 0xB7 + VK_OEM_1 VirtualKeyCode = 0xBA + VK_OEM_PLUS VirtualKeyCode = 0xBB + VK_OEM_COMMA VirtualKeyCode = 0xBC + VK_OEM_MINUS VirtualKeyCode = 0xBD + VK_OEM_PERIOD VirtualKeyCode = 0xBE + VK_OEM_2 VirtualKeyCode = 0xBF + VK_OEM_3 VirtualKeyCode = 0xC0 + VK_OEM_4 VirtualKeyCode = 0xDB + VK_OEM_5 VirtualKeyCode = 0xDC + VK_OEM_6 VirtualKeyCode = 0xDD + VK_OEM_7 VirtualKeyCode = 0xDE + VK_OEM_8 VirtualKeyCode = 0xDF + VK_OEM_AX VirtualKeyCode = 0xE1 + VK_OEM_102 VirtualKeyCode = 0xE2 + VK_ICO_HELP VirtualKeyCode = 0xE3 + VK_ICO_00 VirtualKeyCode = 0xE4 + VK_PROCESSKEY VirtualKeyCode = 0xE5 + VK_ICO_CLEAR VirtualKeyCode = 0xE6 + VK_OEM_RESET VirtualKeyCode = 0xE9 + VK_OEM_JUMP VirtualKeyCode = 0xEA + VK_OEM_PA1 VirtualKeyCode = 0xEB + VK_OEM_PA2 VirtualKeyCode = 0xEC + VK_OEM_PA3 VirtualKeyCode = 0xED + VK_OEM_WSCTRL VirtualKeyCode = 0xEE + VK_OEM_CUSEL VirtualKeyCode = 0xEF + VK_OEM_ATTN VirtualKeyCode = 0xF0 + VK_OEM_FINISH VirtualKeyCode = 0xF1 + VK_OEM_COPY VirtualKeyCode = 0xF2 + VK_OEM_AUTO VirtualKeyCode = 0xF3 + VK_OEM_ENLW VirtualKeyCode = 0xF4 + VK_OEM_BACKTAB VirtualKeyCode = 0xF5 + VK_ATTN VirtualKeyCode = 0xF6 + VK_CRSEL VirtualKeyCode = 0xF7 + VK_EXSEL VirtualKeyCode = 0xF8 + VK_EREOF VirtualKeyCode = 0xF9 + VK_PLAY VirtualKeyCode = 0xFA + VK_ZOOM VirtualKeyCode = 0xFB + VK_NONAME VirtualKeyCode = 0xFC + VK_PA1 VirtualKeyCode = 0xFD + VK_OEM_CLEAR VirtualKeyCode = 0xFE +) diff --git a/vendor/github.com/erikgeiser/coninput/mode.go b/vendor/github.com/erikgeiser/coninput/mode.go new file mode 100644 index 0000000..e6d8bf4 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/mode.go @@ -0,0 +1,82 @@ +//go:build windows +// +build windows + +package coninput + +import ( + "strings" + + "golang.org/x/sys/windows" +) + +// AddInputModes returns the given mode with one or more additional modes enabled. +func AddInputModes(mode uint32, enableModes ...uint32) uint32 { + for _, enableMode := range enableModes { + mode |= enableMode + } + + return mode +} + +// RemoveInputModes returns the given mode with one or more additional modes disabled. +func RemoveInputModes(mode uint32, disableModes ...uint32) uint32 { + for _, disableMode := range disableModes { + mode &^= disableMode + } + + return mode +} + +// ToggleInputModes returns the given mode with one or more additional modes toggeled. +func ToggleInputModes(mode uint32, toggleModes ...uint32) uint32 { + for _, toggeMode := range toggleModes { + mode ^= toggeMode + } + + return mode +} + +var inputModes = []struct { + mode uint32 + name string +}{ + {mode: windows.ENABLE_ECHO_INPUT, name: "ENABLE_ECHO_INPUT"}, + {mode: windows.ENABLE_INSERT_MODE, name: "ENABLE_INSERT_MODE"}, + {mode: windows.ENABLE_LINE_INPUT, name: "ENABLE_LINE_INPUT"}, + {mode: windows.ENABLE_MOUSE_INPUT, name: "ENABLE_MOUSE_INPUT"}, + {mode: windows.ENABLE_PROCESSED_INPUT, name: "ENABLE_PROCESSED_INPUT"}, + {mode: windows.ENABLE_QUICK_EDIT_MODE, name: "ENABLE_QUICK_EDIT_MODE"}, + {mode: windows.ENABLE_WINDOW_INPUT, name: "ENABLE_WINDOW_INPUT"}, + {mode: windows.ENABLE_VIRTUAL_TERMINAL_INPUT, name: "ENABLE_VIRTUAL_TERMINAL_INPUT"}, +} + +// ListInputMode returnes the isolated enabled input modes as a list. +func ListInputModes(mode uint32) []uint32 { + modes := []uint32{} + + for _, inputMode := range inputModes { + if mode&inputMode.mode > 0 { + modes = append(modes, inputMode.mode) + } + } + + return modes +} + +// ListInputMode returnes the isolated enabled input mode names as a list. +func ListInputModeNames(mode uint32) []string { + modes := []string{} + + for _, inputMode := range inputModes { + if mode&inputMode.mode > 0 { + modes = append(modes, inputMode.name) + } + } + + return modes +} + +// DescribeInputMode returns a string containing the names of each enabled input mode. +func DescribeInputMode(mode uint32) string { + return strings.Join(ListInputModeNames(mode), "|") +} diff --git a/vendor/github.com/erikgeiser/coninput/read.go b/vendor/github.com/erikgeiser/coninput/read.go new file mode 100644 index 0000000..b2dd82f --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/read.go @@ -0,0 +1,154 @@ +//go:build windows +// +build windows + +package coninput + +import ( + "fmt" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + procReadConsoleInputW = modkernel32.NewProc("ReadConsoleInputW") + procPeekConsoleInputW = modkernel32.NewProc("PeekConsoleInputW") + procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents") + procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer") +) + +// NewStdinHandle is a shortcut for windows.GetStdHandle(windows.STD_INPUT_HANDLE). +func NewStdinHandle() (windows.Handle, error) { + return windows.GetStdHandle(windows.STD_INPUT_HANDLE) +} + +// WinReadConsoleInput is a thin wrapper around the Windows console API function +// ReadConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). In most +// cases it is more practical to either use ReadConsoleInput or +// ReadNConsoleInputs. +func WinReadConsoleInput(consoleInput windows.Handle, buffer *InputRecord, + length uint32, numberOfEventsRead *uint32) error { + r, _, e := syscall.Syscall6(procReadConsoleInputW.Addr(), 4, + uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length), + uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0) + if r == 0 { + return error(e) + } + + return nil +} + +// ReadNConsoleInputs is a wrapper around ReadConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/readconsoleinput) that +// automates the event buffer allocation in oder to provide io.Reader-like +// sematics. maxEvents must be greater than zero. +func ReadNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) { + if maxEvents == 0 { + return nil, fmt.Errorf("maxEvents cannot be zero") + } + + var inputRecords = make([]InputRecord, maxEvents) + n, err := ReadConsoleInput(console, inputRecords) + + return inputRecords[:n], err +} + +// ReadConsoleInput provides an ideomatic interface to the Windows console API +// function ReadConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). The size +// of inputRecords must be greater than zero. +func ReadConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) { + if len(inputRecords) == 0 { + return 0, fmt.Errorf("size of input record buffer cannot be zero") + } + + var read uint32 + err := WinReadConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read) + + return read, err +} + +// WinPeekConsoleInput is a thin wrapper around the Windows console API function +// PeekConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). In most +// cases it is more practical to either use PeekConsoleInput or +// PeekNConsoleInputs. +func WinPeekConsoleInput(consoleInput windows.Handle, buffer *InputRecord, + length uint32, numberOfEventsRead *uint32) error { + r, _, e := syscall.Syscall6(procPeekConsoleInputW.Addr(), 4, + uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length), + uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0) + if r == 0 { + return error(e) + } + + return nil + +} + +// PeekNConsoleInputs is a wrapper around PeekConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput) that +// automates the event buffer allocation in oder to provide io.Reader-like +// sematics. maxEvents must be greater than zero. +func PeekNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) { + if maxEvents == 0 { + return nil, fmt.Errorf("maxEvents cannot be zero") + } + + var inputRecords = make([]InputRecord, maxEvents) + n, err := PeekConsoleInput(console, inputRecords) + + return inputRecords[:n], err +} + +// PeekConsoleInput provides an ideomatic interface to the Windows console API +// function PeekConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). The size +// of inputRecords must be greater than zero. +func PeekConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) { + if len(inputRecords) == 0 { + return 0, fmt.Errorf("size of input record buffer cannot be zero") + } + + var read uint32 + + err := WinPeekConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read) + + return read, err +} + +// WinGetNumberOfConsoleInputEvents provides an ideomatic interface to the +// Windows console API function GetNumberOfConsoleInputEvents (see +// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents). +func WinGetNumberOfConsoleInputEvents(consoleInput windows.Handle, numberOfEvents *uint32) error { + r, _, e := syscall.Syscall6(procGetNumberOfConsoleInputEvents.Addr(), 2, + uintptr(consoleInput), uintptr(unsafe.Pointer(numberOfEvents)), 0, + 0, 0, 0) + if r == 0 { + return error(e) + } + + return nil +} + +// GetNumberOfConsoleInputEvents provides an ideomatic interface to the Windows +// console API function GetNumberOfConsoleInputEvents (see +// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents). +func GetNumberOfConsoleInputEvents(console windows.Handle) (uint32, error) { + var nEvents uint32 + err := WinGetNumberOfConsoleInputEvents(console, &nEvents) + + return nEvents, err +} + +func FlushConsoleInputBuffer(consoleInput windows.Handle) error { + r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1, uintptr(consoleInput), 0, 0) + if r == 0 { + return error(e) + } + + return nil +} diff --git a/vendor/github.com/erikgeiser/coninput/records.go b/vendor/github.com/erikgeiser/coninput/records.go new file mode 100644 index 0000000..cccf7fb --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/records.go @@ -0,0 +1,486 @@ +package coninput + +import ( + "encoding/binary" + "fmt" + "strconv" + "strings" +) + +const ( + maxEventSize = 16 + wordPaddingBytes = 2 +) + +// EventType denots the type of an event +type EventType uint16 + +// EventUnion is the union data type that contains the data for any event. +type EventUnion [maxEventSize]byte + +// InputRecord corresponds to the INPUT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +type InputRecord struct { + // EventType specifies the type of event that helt in Event. + EventType EventType + + // Padding of the 16-bit EventType to a whole 32-bit dword. + _ [wordPaddingBytes]byte + + // Event holds the actual event data. Use Unrap to access it as its + // respective event type. + Event EventUnion +} + +// String implements fmt.Stringer for InputRecord. +func (ir InputRecord) String() string { + return ir.Unwrap().String() +} + +// Unwrap parses the event data into an EventRecord of the respective event +// type. The data in the returned EventRecord does not contain any references to +// the passed InputRecord. +func (ir InputRecord) Unwrap() EventRecord { + switch ir.EventType { + case FocusEventType: + return FocusEventRecord{SetFocus: ir.Event[0] > 0} + case KeyEventType: + return KeyEventRecord{ + KeyDown: binary.LittleEndian.Uint32(ir.Event[0:4]) > 0, + RepeatCount: binary.LittleEndian.Uint16(ir.Event[4:6]), + VirtualKeyCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[6:8])), + VirtualScanCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[8:10])), + Char: rune(binary.LittleEndian.Uint16(ir.Event[10:12])), + ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[12:16])), + } + case MouseEventType: + m := MouseEventRecord{ + MousePositon: Coord{ + X: binary.LittleEndian.Uint16(ir.Event[0:2]), + Y: binary.LittleEndian.Uint16(ir.Event[2:4]), + }, + ButtonState: ButtonState(binary.LittleEndian.Uint32(ir.Event[4:8])), + ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[8:12])), + EventFlags: EventFlags(binary.LittleEndian.Uint32(ir.Event[12:16])), + } + + if (m.EventFlags&MOUSE_WHEELED > 0) || (m.EventFlags&MOUSE_HWHEELED > 0) { + if int16(highWord(uint32(m.ButtonState))) > 0 { + m.WheelDirection = 1 + } else { + m.WheelDirection = -1 + } + } + + return m + case WindowBufferSizeEventType: + return WindowBufferSizeEventRecord{ + Size: Coord{ + X: binary.LittleEndian.Uint16(ir.Event[0:2]), + Y: binary.LittleEndian.Uint16(ir.Event[2:4]), + }, + } + case MenuEventType: + return MenuEventRecord{ + CommandID: binary.LittleEndian.Uint32(ir.Event[0:4]), + } + default: + return &UnknownEvent{InputRecord: ir} + } +} + +// EventRecord represents one of the following event types: +// TypeFocusEventRecord, TypeKeyEventRecord, TypeMouseEventRecord, +// TypeWindowBufferSizeEvent, TypeMenuEventRecord and UnknownEvent. +type EventRecord interface { + Type() string + fmt.Stringer +} + +// FocusEventType is the event type for a FocusEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const FocusEventType EventType = 0x0010 + +// FocusEventRecord represent the FOCUS_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/focus-event-record-str). +// These events are used internally by the Windows console API and should be +// ignored. +type FocusEventRecord struct { + // SetFocus is reserved and should not be used. + SetFocus bool +} + +// Ensure that FocusEventRecord satisfies EventRecord interface. +var _ EventRecord = FocusEventRecord{} + +// Type ensures that FocusEventRecord satisfies EventRecord interface. +func (e FocusEventRecord) Type() string { return "FocusEvent" } + +// String ensures that FocusEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e FocusEventRecord) String() string { return fmt.Sprintf("%s[%v]", e.Type(), e.SetFocus) } + +// KeyEventType is the event type for a KeyEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const KeyEventType EventType = 0x0001 + +// KeyEventRecord represent the KEY_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/key-event-record-str). +type KeyEventRecord struct { + // KeyDown specified whether the key is pressed or released. + KeyDown bool + + // RepeatCount indicates that a key is being held down. For example, when a + // key is held down, five events with RepeatCount equal to 1 may be + // generated, one event with RepeatCount equal to 5, or multiple events + // with RepeatCount greater than or equal to 1. + RepeatCount uint16 + + // VirtualKeyCode identifies the given key in a device-independent manner + // (see + // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). + VirtualKeyCode VirtualKeyCode + + // VirtualScanCode represents the device-dependent value generated by the + // keyboard hardware. + VirtualScanCode VirtualKeyCode + + // Char is the character that corresponds to the pressed key. Char can be + // zero for some keys. + Char rune + + //ControlKeyState holds the state of the control keys. + ControlKeyState ControlKeyState +} + +// Ensure that KeyEventRecord satisfies EventRecord interface. +var _ EventRecord = KeyEventRecord{} + +// Type ensures that KeyEventRecord satisfies EventRecord interface. +func (e KeyEventRecord) Type() string { return "KeyEvent" } + +// String ensures that KeyEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e KeyEventRecord) String() string { + infos := []string{} + + repeat := "" + if e.RepeatCount > 1 { + repeat = "x" + strconv.Itoa(int(e.RepeatCount)) + } + + infos = append(infos, fmt.Sprintf("%q%s", e.Char, repeat)) + + direction := "up" + if e.KeyDown { + direction = "down" + } + + infos = append(infos, direction) + + if e.ControlKeyState != NO_CONTROL_KEY { + infos = append(infos, e.ControlKeyState.String()) + } + + infos = append(infos, fmt.Sprintf("KeyCode: %d", e.VirtualKeyCode)) + infos = append(infos, fmt.Sprintf("ScanCode: %d", e.VirtualScanCode)) + + return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", ")) +} + +// MenuEventType is the event type for a MenuEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const MenuEventType EventType = 0x0008 + +// MenuEventRecord represent the MENU_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/menu-event-record-str). +// These events are deprecated by the Windows console API and should be ignored. +type MenuEventRecord struct { + CommandID uint32 +} + +// Ensure that MenuEventRecord satisfies EventRecord interface. +var _ EventRecord = MenuEventRecord{} + +// Type ensures that MenuEventRecord satisfies EventRecord interface. +func (e MenuEventRecord) Type() string { return "MenuEvent" } + +// String ensures that MenuEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e MenuEventRecord) String() string { return fmt.Sprintf("MenuEvent[%d]", e.CommandID) } + +// MouseEventType is the event type for a MouseEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const MouseEventType EventType = 0x0002 + +// MouseEventRecord represent the MOUSE_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type MouseEventRecord struct { + // MousePosition contains the location of the cursor, in terms of the + // console screen buffer's character-cell coordinates. + MousePositon Coord + + // ButtonState holds the status of the mouse buttons. + ButtonState ButtonState + + // ControlKeyState holds the state of the control keys. + ControlKeyState ControlKeyState + + // EventFlags specify tge type of mouse event. + EventFlags EventFlags + + // WheelDirection specified the direction in which the mouse wheel is + // spinning when EventFlags contains MOUSE_HWHEELED or MOUSE_WHEELED. When + // the event flags specify MOUSE_WHEELED it is 1 if the wheel rotated + // forward (away from the user) or -1 when it rotates backwards. When + // MOUSE_HWHEELED is specified it is 1 when the wheel rotates right and -1 + // when it rotates left. When the EventFlags do not indicate a mouse wheel + // event it is 0. + WheelDirection int +} + +// Ensure that MouseEventRecord satisfies EventRecord interface. +var _ EventRecord = MouseEventRecord{} + +func (e MouseEventRecord) WheelDirectionName() string { + if e.EventFlags&MOUSE_WHEELED > 0 { + if e.WheelDirection > 0 { + return "Forward" + } + + return "Backward" + } else if e.EventFlags&MOUSE_HWHEELED > 0 { + if e.WheelDirection > 0 { + return "Right" + } + + return "Left" + } + + return "" +} + +// Type ensures that MouseEventRecord satisfies EventRecord interface. +func (e MouseEventRecord) Type() string { return "MouseEvent" } + +// String ensures that MouseEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e MouseEventRecord) String() string { + infos := []string{e.MousePositon.String()} + + if e.ButtonState&0xFF != 0 { + infos = append(infos, e.ButtonState.String()) + } + + eventDescription := e.EventFlags.String() + + wheelDirection := e.WheelDirectionName() + if wheelDirection != "" { + eventDescription += "(" + wheelDirection + ")" + } + + infos = append(infos, eventDescription) + + if e.ControlKeyState != NO_CONTROL_KEY { + infos = append(infos, e.ControlKeyState.String()) + } + + return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", ")) +} + +// WindowBufferSizeEventType is the event type for a WindowBufferSizeEventRecord +// (see https://docs.microsoft.com/en-us/windows/console/input-record-str). +const WindowBufferSizeEventType EventType = 0x0004 + +// WindowBufferSizeEventRecord represent the WINDOW_BUFFER_SIZE_RECORD structure +// from the Windows console API (see +// https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str). +type WindowBufferSizeEventRecord struct { + // Size contains the size of the console screen buffer, in character cell columns and rows. + Size Coord +} + +// Ensure that WindowBufferSizeEventRecord satisfies EventRecord interface. +var _ EventRecord = WindowBufferSizeEventRecord{} + +// Type ensures that WindowBufferSizeEventRecord satisfies EventRecord interface. +func (e WindowBufferSizeEventRecord) Type() string { return "WindowBufferSizeEvent" } + +// String ensures that WindowBufferSizeEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e WindowBufferSizeEventRecord) String() string { + return fmt.Sprintf("WindowBufferSizeEvent[%s]", e.Size) +} + +// UnknownEvent is generated when the event type does not match one of the +// following types: TypeFocusEventRecord, TypeKeyEventRecord, +// TypeMouseEventRecord, TypeWindowBufferSizeEvent, TypeMenuEventRecord and +// UnknownEvent. +type UnknownEvent struct { + InputRecord +} + +// Ensure that UnknownEvent satisfies EventRecord interface. +var _ EventRecord = UnknownEvent{} + +// Type ensures that UnknownEvent satisfies EventRecord interface. +func (e UnknownEvent) Type() string { return "UnknownEvent" } + +// String ensures that UnknownEvent satisfies EventRecord and fmt.Stringer +// interfaces. +func (e UnknownEvent) String() string { + return fmt.Sprintf("%s[Type: %d, Data: %v]", e.Type(), e.InputRecord.EventType, e.InputRecord.Event[:]) +} + +// Coord represent the COORD structure from the Windows +// console API (see https://docs.microsoft.com/en-us/windows/console/coord-str). +type Coord struct { + // X is the horizontal coordinate or column value. The units depend on the function call. + X uint16 + // Y is the vertical coordinate or row value. The units depend on the function call. + Y uint16 +} + +// String ensures that Coord satisfies the fmt.Stringer interface. +func (c Coord) String() string { + return fmt.Sprintf("(%d, %d)", c.X, c.Y) +} + +// ButtonState holds the state of the mouse buttons (see +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type ButtonState uint32 + +func (bs ButtonState) Contains(state ButtonState) bool { + return bs&state > 0 +} + +// String ensures that ButtonState satisfies the fmt.Stringer interface. +func (bs ButtonState) String() string { + switch { + case bs&FROM_LEFT_1ST_BUTTON_PRESSED > 0: + return "Left" + case bs&FROM_LEFT_2ND_BUTTON_PRESSED > 0: + return "2" + case bs&FROM_LEFT_3RD_BUTTON_PRESSED > 0: + return "3" + case bs&FROM_LEFT_4TH_BUTTON_PRESSED > 0: + return "4" + case bs&RIGHTMOST_BUTTON_PRESSED > 0: + return "Right" + case bs&0xFF == 0: + return "No Button" + default: + return fmt.Sprintf("Unknown(%d)", bs) + } +} + +func (bs ButtonState) IsReleased() bool { + return bs&0xff > 0 +} + +// Valid values for ButtonState. +const ( + FROM_LEFT_1ST_BUTTON_PRESSED ButtonState = 0x0001 + RIGHTMOST_BUTTON_PRESSED ButtonState = 0x0002 + FROM_LEFT_2ND_BUTTON_PRESSED ButtonState = 0x0004 + FROM_LEFT_3RD_BUTTON_PRESSED ButtonState = 0x0008 + FROM_LEFT_4TH_BUTTON_PRESSED ButtonState = 0x0010 +) + +// ControlKeyState holds the state of the control keys for key and mouse events +// (see https://docs.microsoft.com/en-us/windows/console/key-event-record-str +// and https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type ControlKeyState uint32 + +func (cks ControlKeyState) Contains(state ControlKeyState) bool { + return cks&state > 0 +} + +// Valid values for ControlKeyState. +const ( + CAPSLOCK_ON ControlKeyState = 0x0080 + ENHANCED_KEY ControlKeyState = 0x0100 + LEFT_ALT_PRESSED ControlKeyState = 0x0002 + LEFT_CTRL_PRESSED ControlKeyState = 0x0008 + NUMLOCK_ON ControlKeyState = 0x0020 + RIGHT_ALT_PRESSED ControlKeyState = 0x0001 + RIGHT_CTRL_PRESSED ControlKeyState = 0x0004 + SCROLLLOCK_ON ControlKeyState = 0x0040 + SHIFT_PRESSED ControlKeyState = 0x0010 + NO_CONTROL_KEY ControlKeyState = 0x0000 +) + +// String ensures that ControlKeyState satisfies the fmt.Stringer interface. +func (cks ControlKeyState) String() string { + controlKeys := []string{} + + switch { + case cks&CAPSLOCK_ON > 0: + controlKeys = append(controlKeys, "CapsLock") + case cks&ENHANCED_KEY > 0: + controlKeys = append(controlKeys, "Enhanced") + case cks&LEFT_ALT_PRESSED > 0: + controlKeys = append(controlKeys, "Alt") + case cks&LEFT_CTRL_PRESSED > 0: + controlKeys = append(controlKeys, "CTRL") + case cks&NUMLOCK_ON > 0: + controlKeys = append(controlKeys, "NumLock") + case cks&RIGHT_ALT_PRESSED > 0: + controlKeys = append(controlKeys, "RightAlt") + case cks&RIGHT_CTRL_PRESSED > 0: + controlKeys = append(controlKeys, "RightCTRL") + case cks&SCROLLLOCK_ON > 0: + controlKeys = append(controlKeys, "ScrollLock") + case cks&SHIFT_PRESSED > 0: + controlKeys = append(controlKeys, "Shift") + case cks == NO_CONTROL_KEY: + default: + return fmt.Sprintf("Unknown(%d)", cks) + } + + return strings.Join(controlKeys, ",") +} + +// EventFlags specifies the type of a mouse event (see +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type EventFlags uint32 + +// String ensures that EventFlags satisfies the fmt.Stringer interface. +func (ef EventFlags) String() string { + switch { + case ef&DOUBLE_CLICK > 0: + return "DoubleClick" + case ef&MOUSE_WHEELED > 0: + return "Wheeled" + case ef&MOUSE_MOVED > 0: + return "Moved" + case ef&MOUSE_HWHEELED > 0: + return "HWheeld" + case ef == CLICK: + return "Click" + default: + return fmt.Sprintf("Unknown(%d)", ef) + } +} + +func (ef EventFlags) Contains(flag EventFlags) bool { + return ef&flag > 0 +} + +// Valid values for EventFlags. +const ( + CLICK EventFlags = 0x0000 + MOUSE_MOVED EventFlags = 0x0001 + DOUBLE_CLICK EventFlags = 0x0002 + MOUSE_WHEELED EventFlags = 0x0004 + MOUSE_HWHEELED EventFlags = 0x0008 +) + +func highWord(data uint32) uint16 { + return uint16((data & 0xFFFF0000) >> 16) +} diff --git a/vendor/github.com/faiface/beep/README.md b/vendor/github.com/faiface/beep/README.md deleted file mode 100644 index 8219da2..0000000 --- a/vendor/github.com/faiface/beep/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Beep [![GoDoc](https://godoc.org/github.com/faiface/beep?status.svg)](https://godoc.org/github.com/faiface/beep) [![Go Report Card](https://goreportcard.com/badge/github.com/faiface/beep)](https://goreportcard.com/report/github.com/faiface/beep) [![Discord Chat](https://img.shields.io/discord/699679031603494954)](https://discord.gg/q2DK4MP) - -**Add minimp3 decoder.** - -A little package that brings sound to any Go application. Suitable for playback and audio-processing. - -``` -go get -u github.com/faiface/beep -``` - -## Features - -Beep is built on top of its [Streamer](https://godoc.org/github.com/faiface/beep#Streamer) interface, which is like [io.Reader](https://golang.org/pkg/io/#Reader), but for audio. It was one of the best design decisions I've ever made and it enabled all the rest of the features to naturally come together with not much code. - -- **Decode and play WAV, MP3, OGG, and FLAC.** -- **Encode and save WAV.** -- **Very simple API.** Limiting the support to stereo (two channel) audio made it possible to simplify the architecture and the API. -- **Rich library of compositors and effects.** Loop, pause/resume, change volume, mix, sequence, change playback speed, and more. -- **Easily create new effects.** With the `Streamer` interface, creating new effects is very easy. -- **Generate completely own artificial sounds.** Again, the `Streamer` interface enables easy sound generation. -- **Very small codebase.** The core is just ~1K LOC. - -## Tutorial - -The [Wiki](https://github.com/faiface/beep/wiki) contains a handful of tutorials for you to get started. They teach the fundamentals and advanced topics alike. **Read them especially if you call `speaker.Init` every time you play something.** - -- [Hello, Beep!](https://github.com/faiface/beep/wiki/Hello,-Beep!) -- [Composing and controlling](https://github.com/faiface/beep/wiki/Composing-and-controlling) -- [To buffer, or not to buffer, that is the question](https://github.com/faiface/beep/wiki/To-buffer,-or-not-to-buffer,-that-is-the-question) -- [Making own streamers](https://github.com/faiface/beep/wiki/Making-own-streamers) - -## Examples - -| [Speedy Player](https://github.com/faiface/beep/tree/master/examples/speedy-player) | [Doppler Stereo Room](https://github.com/faiface/beep/tree/master/examples/doppler-stereo-room) | -| --- | --- | -| ![Speedy Player](https://github.com/faiface/beep/blob/master/examples/speedy-player/screenshot.png) | ![Doppler Stereo Room](https://github.com/faiface/beep/blob/master/examples/doppler-stereo-room/screenshot.png) | - -## Dependencies - -For playback, Beep uses [Oto](https://github.com/hajimehoshi/oto) under the hood. Check its requirements to see what you need to install for building your application. - -Running an already built application should work with no extra dependencies. - -## Licence - -[MIT](https://github.com/faiface/beep/blob/master/LICENSE) - -## Projects using beep - -- [Mifasol music server](https://github.com/jypelle/mifasol) diff --git a/vendor/github.com/faiface/beep/speaker/speaker.go b/vendor/github.com/faiface/beep/speaker/speaker.go deleted file mode 100644 index 7b3734f..0000000 --- a/vendor/github.com/faiface/beep/speaker/speaker.go +++ /dev/null @@ -1,130 +0,0 @@ -// Package speaker implements playback of beep.Streamer values through physical speakers. -package speaker - -import ( - "sync" - - "github.com/faiface/beep" - "github.com/hajimehoshi/oto" - "github.com/pkg/errors" -) - -var ( - mu sync.Mutex - mixer beep.Mixer - samples [][2]float64 - buf []byte - context *oto.Context - player *oto.Player - done chan struct{} -) - -// Init initializes audio playback through speaker. Must be called before using this package. -// -// The bufferSize argument specifies the number of samples of the speaker's buffer. Bigger -// bufferSize means lower CPU usage and more reliable playback. Lower bufferSize means better -// responsiveness and less delay. -func Init(sampleRate beep.SampleRate, bufferSize int) error { - mu.Lock() - defer mu.Unlock() - - Close() - - mixer = beep.Mixer{} - - numBytes := bufferSize * 4 - samples = make([][2]float64, bufferSize) - buf = make([]byte, numBytes) - - var err error - context, err = oto.NewContext(int(sampleRate), 2, 2, numBytes) - if err != nil { - return errors.Wrap(err, "failed to initialize speaker") - } - player = context.NewPlayer() - - done = make(chan struct{}) - - go func() { - for { - select { - default: - update() - case <-done: - return - } - } - }() - - return nil -} - -// Close closes the playback and the driver. In most cases, there is certainly no need to call Close -// even when the program doesn't play anymore, because in properly set systems, the default mixer -// handles multiple concurrent processes. It's only when the default device is not a virtual but hardware -// device, that you'll probably want to manually manage the device from your application. -func Close() { - if player != nil { - if done != nil { - done <- struct{}{} - done = nil - } - player.Close() - context.Close() - player = nil - } -} - -// Lock locks the speaker. While locked, speaker won't pull new data from the playing Streamers. Lock -// if you want to modify any currently playing Streamers to avoid race conditions. -// -// Always lock speaker for as little time as possible, to avoid playback glitches. -func Lock() { - mu.Lock() -} - -// Unlock unlocks the speaker. Call after modifying any currently playing Streamer. -func Unlock() { - mu.Unlock() -} - -// Play starts playing all provided Streamers through the speaker. -func Play(s ...beep.Streamer) { - mu.Lock() - mixer.Add(s...) - mu.Unlock() -} - -// Clear removes all currently playing Streamers from the speaker. -func Clear() { - mu.Lock() - mixer.Clear() - mu.Unlock() -} - -// update pulls new data from the playing Streamers and sends it to the speaker. Blocks until the -// data is sent and started playing. -func update() { - mu.Lock() - mixer.Stream(samples) - mu.Unlock() - - for i := range samples { - for c := range samples[i] { - val := samples[i][c] - if val < -1 { - val = -1 - } - if val > +1 { - val = +1 - } - valInt16 := int16(val * (1<<15 - 1)) - low := byte(valInt16) - high := byte(valInt16 >> 8) - buf[i*4+c*2+0] = low - buf[i*4+c*2+1] = high - } - } - - player.Write(buf) -} diff --git a/vendor/github.com/go-musicfox/notificator/notification.go b/vendor/github.com/go-musicfox/notificator/notification.go index 5798889..8884aad 100644 --- a/vendor/github.com/go-musicfox/notificator/notification.go +++ b/vendor/github.com/go-musicfox/notificator/notification.go @@ -30,6 +30,9 @@ type Notificator struct { } func (n Notificator) Push(urgency string, title string, text string, iconPath string, redirectUrl string) error { + if n.notifier == nil { + return nil + } icon := n.defaultIcon if iconPath != "" { @@ -41,7 +44,6 @@ func (n Notificator) Push(urgency string, title string, text string, iconPath st } return n.notifier.push(title, text, icon, redirectUrl).Run() - } type osxNotificator struct { @@ -50,7 +52,6 @@ type osxNotificator struct { } func (o osxNotificator) push(title string, text string, iconPath string, redirectUrl string) *exec.Cmd { - // Checks if terminal-notifier exists, and is accessible. // if terminal-notifier exists, use it. @@ -61,8 +62,8 @@ func (o osxNotificator) push(title string, text string, iconPath string, redirec } return exec.Command("terminal-notifier", "-title", o.AppName, "-message", text, "-subtitle", title, "-contentImage", iconPath, "-sender", o.Sender) } else if CheckMacOSVersion() { - title = strings.Replace(title, `"`, `\"`, -1) - text = strings.Replace(text, `"`, `\"`, -1) + title = strings.ReplaceAll(title, `"`, `\"`) + text = strings.ReplaceAll(text, `"`, `\"`) notification := fmt.Sprintf("display notification \"%s\" with title \"%s\" subtitle \"%s\"", text, o.AppName, title) return exec.Command("osascript", "-e", notification) @@ -75,7 +76,6 @@ func (o osxNotificator) push(title string, text string, iconPath string, redirec // Causes the notification to stick around until clicked. func (o osxNotificator) pushCritical(title string, text string, iconPath string, redirectUrl string) *exec.Cmd { - // same function as above... if CheckTermNotif() { // timeout set to 30 seconds, to show the importance of the notification @@ -90,7 +90,6 @@ func (o osxNotificator) pushCritical(title string, text string, iconPath string, } return exec.Command("growlnotify", "-n", o.AppName, "--image", iconPath, "-m", title, "--url", redirectUrl) - } type linuxNotificator struct { @@ -118,18 +117,15 @@ func (w windowsNotificator) pushCritical(title string, text string, iconPath str } func New(o Options) *Notificator { - var Notifier notifier switch runtime.GOOS { - case "darwin": Notifier = osxNotificator{AppName: o.AppName, Sender: o.OSXSender} - case "linux": + case "linux", "android": Notifier = linuxNotificator{AppName: o.AppName} case "windows": Notifier = windowsNotificator{} - } return &Notificator{notifier: Notifier, defaultIcon: o.DefaultIcon} diff --git a/vendor/github.com/google/uuid/.travis.yml b/vendor/github.com/google/uuid/.travis.yml new file mode 100644 index 0000000..d8156a6 --- /dev/null +++ b/vendor/github.com/google/uuid/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.4.3 + - 1.5.3 + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/google/uuid/CHANGELOG.md b/vendor/github.com/google/uuid/CHANGELOG.md deleted file mode 100644 index 2bd7866..0000000 --- a/vendor/github.com/google/uuid/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# Changelog - -## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18) - - -### Bug Fixes - -* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0)) - -## Changelog diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md index 5566888..04fdf09 100644 --- a/vendor/github.com/google/uuid/CONTRIBUTING.md +++ b/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -2,22 +2,6 @@ We definitely welcome patches and contribution to this project! -### Tips - -Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org). - -Always try to include a test case! If it is not possible or not necessary, -please explain why in the pull request description. - -### Releasing - -Commits that would precipitate a SemVer change, as desrcibed in the Conventional -Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action) -to create a release candidate pull request. Once submitted, `release-please` -will create a release. - -For tips on how to work with `release-please`, see its documentation. - ### Legal requirements In order to protect both you and ourselves, you will need to sign the diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md index 3e9a618..f765a46 100644 --- a/vendor/github.com/google/uuid/README.md +++ b/vendor/github.com/google/uuid/README.md @@ -1,6 +1,6 @@ -# uuid +# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) The uuid package generates and inspects UUIDs based on -[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) +[RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. This package is based on the github.com/pborman/uuid package (previously named @@ -9,12 +9,10 @@ a UUID is a 16 byte array rather than a byte slice. One loss due to this change is the ability to represent an invalid UUID (vs a NIL UUID). ###### Install -```sh -go get github.com/google/uuid -``` +`go get github.com/google/uuid` ###### Documentation -[![Go Reference](https://pkg.go.dev/badge/github.com/google/uuid.svg)](https://pkg.go.dev/github.com/google/uuid) +[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go index b2a0bc8..24b78ed 100644 --- a/vendor/github.com/google/uuid/node_js.go +++ b/vendor/github.com/google/uuid/node_js.go @@ -7,6 +7,6 @@ package uuid // getHardwareInterface returns nil values for the JS version of the code. -// This removes the "net" dependency, because it is not used in the browser. +// This remvoves the "net" dependency, because it is not used in the browser. // Using the "net" library inflates the size of the transpiled JS code by 673k bytes. func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go index a56138c..a57207a 100644 --- a/vendor/github.com/google/uuid/uuid.go +++ b/vendor/github.com/google/uuid/uuid.go @@ -69,7 +69,7 @@ func Parse(s string) (UUID, error) { // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx case 36 + 9: - if !strings.EqualFold(s[:9], "urn:uuid:") { + if strings.ToLower(s[:9]) != "urn:uuid:" { return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) } s = s[9:] @@ -101,8 +101,7 @@ func Parse(s string) (UUID, error) { 9, 11, 14, 16, 19, 21, - 24, 26, 28, 30, 32, 34, - } { + 24, 26, 28, 30, 32, 34} { v, ok := xtob(s[x], s[x+1]) if !ok { return uuid, errors.New("invalid UUID format") @@ -118,7 +117,7 @@ func ParseBytes(b []byte) (UUID, error) { switch len(b) { case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) { + if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) } b = b[9:] @@ -146,8 +145,7 @@ func ParseBytes(b []byte) (UUID, error) { 9, 11, 14, 16, 19, 21, - 24, 26, 28, 30, 32, 34, - } { + 24, 26, 28, 30, 32, 34} { v, ok := xtob(b[x], b[x+1]) if !ok { return uuid, errors.New("invalid UUID format") diff --git a/vendor/github.com/gookit/color/README.md b/vendor/github.com/gookit/color/README.md index 77d50ca..718b11b 100644 --- a/vendor/github.com/gookit/color/README.md +++ b/vendor/github.com/gookit/color/README.md @@ -570,7 +570,6 @@ Check out these projects, which use https://github.com/gookit/color : - [xo/terminfo](https://github.com/xo/terminfo) - [beego/bee](https://github.com/beego/bee) - [issue9/term](https://github.com/issue9/term) - - [muesli/termenv](https://github.com/muesli/termenv) - [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code) - [Standard ANSI color map](https://conemu.github.io/en/AnsiEscapeCodes.html#Standard_ANSI_color_map) - [Terminal Colors](https://gist.github.com/XVilka/8346728) diff --git a/vendor/github.com/gookit/color/README.zh-CN.md b/vendor/github.com/gookit/color/README.zh-CN.md index 192a89c..1b14405 100644 --- a/vendor/github.com/gookit/color/README.zh-CN.md +++ b/vendor/github.com/gookit/color/README.zh-CN.md @@ -578,7 +578,6 @@ const ( ## 参考项目 - [inhere/console](https://github.com/inhere/php-console) - - [muesli/termenv](https://github.com/muesli/termenv) - [xo/terminfo](https://github.com/xo/terminfo) - [beego/bee](https://github.com/beego/bee) - [issue9/term](https://github.com/issue9/term) diff --git a/vendor/github.com/gookit/color/any.go b/vendor/github.com/gookit/color/any.go deleted file mode 100644 index 8bf31c1..0000000 --- a/vendor/github.com/gookit/color/any.go +++ /dev/null @@ -1,6 +0,0 @@ -//go:build !go1.18 -// +build !go1.18 - -package color - -type any = interface{} diff --git a/vendor/github.com/gookit/color/color.go b/vendor/github.com/gookit/color/color.go index 22de1b0..59e0b0b 100644 --- a/vendor/github.com/gookit/color/color.go +++ b/vendor/github.com/gookit/color/color.go @@ -183,7 +183,7 @@ func InnerErrs() []error { // Usage: // // msg := RenderCode("3;32;45", "some", "message") -func RenderCode(code string, args ...any) string { +func RenderCode(code string, args ...interface{}) string { var message string if ln := len(args); ln == 0 { return "" @@ -205,7 +205,7 @@ func RenderCode(code string, args ...any) string { // RenderWithSpaces Render code with spaces. // If the number of args is > 1, a space will be added between the args -func RenderWithSpaces(code string, args ...any) string { +func RenderWithSpaces(code string, args ...interface{}) string { msg := formatArgsForPrintln(args) if len(code) == 0 { return msg diff --git a/vendor/github.com/gookit/color/color_16.go b/vendor/github.com/gookit/color/color_16.go index 0b70efe..3551521 100644 --- a/vendor/github.com/gookit/color/color_16.go +++ b/vendor/github.com/gookit/color/color_16.go @@ -188,65 +188,57 @@ func (c Color) Text(message string) string { return RenderString(c.String(), mes // Render messages by color setting // // Usage: -// -// green := color.FgGreen.Render -// fmt.Println(green("message")) -func (c Color) Render(a ...any) string { return RenderCode(c.String(), a...) } +// green := color.FgGreen.Render +// fmt.Println(green("message")) +func (c Color) Render(a ...interface{}) string { return RenderCode(c.String(), a...) } // Renderln messages by color setting. // like Println, will add spaces for each argument // // Usage: -// -// green := color.FgGreen.Renderln -// fmt.Println(green("message")) -func (c Color) Renderln(a ...any) string { return RenderWithSpaces(c.String(), a...) } +// green := color.FgGreen.Renderln +// fmt.Println(green("message")) +func (c Color) Renderln(a ...interface{}) string { return RenderWithSpaces(c.String(), a...) } // Sprint render messages by color setting. is alias of the Render() -func (c Color) Sprint(a ...any) string { return RenderCode(c.String(), a...) } +func (c Color) Sprint(a ...interface{}) string { return RenderCode(c.String(), a...) } // Sprintf format and render message. // // Usage: -// -// green := color.Green.Sprintf -// colored := green("message") -func (c Color) Sprintf(format string, args ...any) string { +// green := color.Green.Sprintf +// colored := green("message") +func (c Color) Sprintf(format string, args ...interface{}) string { return RenderString(c.String(), fmt.Sprintf(format, args...)) } // Print messages. // // Usage: -// -// color.Green.Print("message") -// +// color.Green.Print("message") // OR: -// -// green := color.FgGreen.Print -// green("message") -func (c Color) Print(args ...any) { +// green := color.FgGreen.Print +// green("message") +func (c Color) Print(args ...interface{}) { doPrintV2(c.Code(), fmt.Sprint(args...)) } // Printf format and print messages. // // Usage: -// -// color.Cyan.Printf("string %s", "arg0") -func (c Color) Printf(format string, a ...any) { +// color.Cyan.Printf("string %s", "arg0") +func (c Color) Printf(format string, a ...interface{}) { doPrintV2(c.Code(), fmt.Sprintf(format, a...)) } // Println messages with new line -func (c Color) Println(a ...any) { doPrintlnV2(c.String(), a) } +func (c Color) Println(a ...interface{}) { doPrintlnV2(c.String(), a) } // Light current color. eg: 36(FgCyan) -> 96(FgLightCyan). // // Usage: -// -// lightCyan := Cyan.Light() -// lightCyan.Print("message") +// lightCyan := Cyan.Light() +// lightCyan.Print("message") func (c Color) Light() Color { val := int(c) if val >= 30 && val <= 47 { @@ -260,9 +252,8 @@ func (c Color) Light() Color { // Darken current color. eg. 96(FgLightCyan) -> 36(FgCyan) // // Usage: -// -// cyan := LightCyan.Darken() -// cyan.Print("message") +// cyan := LightCyan.Darken() +// cyan.Print("message") func (c Color) Darken() Color { val := int(c) if val >= 90 && val <= 107 { @@ -470,7 +461,9 @@ func Fg2Bg(val uint8) uint8 { } // Basic2nameMap data -func Basic2nameMap() map[uint8]string { return basic2nameMap } +func Basic2nameMap() map[uint8]string { + return basic2nameMap +} // func initName2basicMap() map[string]uint8 { // n2b := make(map[string]uint8, len(basic2nameMap)) diff --git a/vendor/github.com/gookit/color/color_256.go b/vendor/github.com/gookit/color/color_256.go index 991e604..c95c0f7 100644 --- a/vendor/github.com/gookit/color/color_256.go +++ b/vendor/github.com/gookit/color/color_256.go @@ -19,19 +19,16 @@ from wikipedia, 256 color: // tpl for 8 bit 256 color(`2^8`) // // format: -// -// ESC[ … 38;5; … m // 选择前景色 -// ESC[ … 48;5; … m // 选择背景色 +// ESC[ … 38;5; … m // 选择前景色 +// ESC[ … 48;5; … m // 选择背景色 // // example: -// -// fg "\x1b[38;5;242m" -// bg "\x1b[48;5;208m" -// both "\x1b[38;5;242;48;5;208m" +// fg "\x1b[38;5;242m" +// bg "\x1b[48;5;208m" +// both "\x1b[38;5;242;48;5;208m" // // links: -// -// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位 +// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位 const ( TplFg256 = "38;5;%d" TplBg256 = "48;5;%d" @@ -48,14 +45,12 @@ const ( // 颜色值使用10进制和16进制都可 0x98 = 152 // // The color consists of two uint8: -// -// 0: color value -// 1: color type; Fg=0, Bg=1, >1: unset value +// 0: color value +// 1: color type; Fg=0, Bg=1, >1: unset value // // example: -// -// fg color: [152, 0] -// bg color: [152, 1] +// fg color: [152, 0] +// bg color: [152, 1] // // NOTICE: now support 256 color on windows CMD, PowerShell // lint warn - Name starts with package name @@ -92,27 +87,27 @@ func (c Color256) Reset() error { } // Print print message -func (c Color256) Print(a ...any) { +func (c Color256) Print(a ...interface{}) { doPrintV2(c.String(), fmt.Sprint(a...)) } // Printf format and print message -func (c Color256) Printf(format string, a ...any) { +func (c Color256) Printf(format string, a ...interface{}) { doPrintV2(c.String(), fmt.Sprintf(format, a...)) } // Println print message with newline -func (c Color256) Println(a ...any) { +func (c Color256) Println(a ...interface{}) { doPrintlnV2(c.String(), a) } // Sprint returns rendered message -func (c Color256) Sprint(a ...any) string { +func (c Color256) Sprint(a ...interface{}) string { return RenderCode(c.String(), a...) } // Sprintf returns format and rendered message -func (c Color256) Sprintf(format string, a ...any) string { +func (c Color256) Sprintf(format string, a ...interface{}) string { return RenderString(c.String(), fmt.Sprintf(format, a...)) } @@ -211,10 +206,9 @@ type Style256 struct { // S256 create a color256 style // // Usage: -// -// s := color.S256() -// s := color.S256(132) // fg -// s := color.S256(132, 203) // fg and bg +// s := color.S256() +// s := color.S256(132) // fg +// s := color.S256(132, 203) // fg and bg func S256(fgAndBg ...uint8) *Style256 { s := &Style256{} vl := len(fgAndBg) @@ -262,27 +256,27 @@ func (s *Style256) AddOpts(opts ...Color) *Style256 { } // Print message -func (s *Style256) Print(a ...any) { +func (s *Style256) Print(a ...interface{}) { doPrintV2(s.String(), fmt.Sprint(a...)) } // Printf format and print message -func (s *Style256) Printf(format string, a ...any) { +func (s *Style256) Printf(format string, a ...interface{}) { doPrintV2(s.String(), fmt.Sprintf(format, a...)) } // Println print message with newline -func (s *Style256) Println(a ...any) { +func (s *Style256) Println(a ...interface{}) { doPrintlnV2(s.String(), a) } // Sprint returns rendered message -func (s *Style256) Sprint(a ...any) string { +func (s *Style256) Sprint(a ...interface{}) string { return RenderCode(s.Code(), a...) } // Sprintf returns format and rendered message -func (s *Style256) Sprintf(format string, a ...any) string { +func (s *Style256) Sprintf(format string, a ...interface{}) string { return RenderString(s.Code(), fmt.Sprintf(format, a...)) } diff --git a/vendor/github.com/gookit/color/color_rgb.go b/vendor/github.com/gookit/color/color_rgb.go index 724cf66..ff3c1bb 100644 --- a/vendor/github.com/gookit/color/color_rgb.go +++ b/vendor/github.com/gookit/color/color_rgb.go @@ -8,24 +8,20 @@ import ( // 24 bit RGB color // RGB: -// -// R 0-255 G 0-255 B 0-255 -// R 00-FF G 00-FF B 00-FF (16进制) +// R 0-255 G 0-255 B 0-255 +// R 00-FF G 00-FF B 00-FF (16进制) // // Format: -// -// ESC[ … 38;2;;; … m // Select RGB foreground color -// ESC[ … 48;2;;; … m // Choose RGB background color +// ESC[ … 38;2;;; … m // Select RGB foreground color +// ESC[ … 48;2;;; … m // Choose RGB background color // // links: -// -// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位 +// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位 // // example: -// -// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m -// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m -// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m +// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m +// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m +// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m const ( TplFgRGB = "38;2;%d;%d;%d" TplBgRGB = "48;2;%d;%d;%d" @@ -49,11 +45,10 @@ const ( // The last digit represents the foreground(0), background(1), >1 is unset value // // Usage: -// -// // 0, 1, 2 is R,G,B. -// // 3rd: Fg=0, Bg=1, >1: unset value -// RGBColor{30,144,255, 0} -// RGBColor{30,144,255, 1} +// // 0, 1, 2 is R,G,B. +// // 3rd: Fg=0, Bg=1, >1: unset value +// RGBColor{30,144,255, 0} +// RGBColor{30,144,255, 1} // // NOTICE: now support RGB color on Windows CMD, PowerShell type RGBColor [4]uint8 @@ -64,10 +59,9 @@ var emptyRGBColor = RGBColor{3: 99} // RGB color create. // // Usage: -// -// c := RGB(30,144,255) -// c := RGB(30,144,255, true) -// c.Print("message") +// c := RGB(30,144,255) +// c := RGB(30,144,255, true) +// c.Print("message") func RGB(r, g, b uint8, isBg ...bool) RGBColor { rgb := RGBColor{r, g, b} if len(isBg) > 0 && isBg[0] { @@ -96,12 +90,11 @@ func RgbFromInts(rgb []int, isBg ...bool) RGBColor { // HEX create RGB color from a HEX color string. // // Usage: -// -// c := HEX("ccc") // rgb: [204 204 204] -// c := HEX("aabbcc") // rgb: [170 187 204] -// c := HEX("#aabbcc") -// c := HEX("0xaabbcc") -// c.Print("message") +// c := HEX("ccc") // rgb: [204 204 204] +// c := HEX("aabbcc") // rgb: [170 187 204] +// c := HEX("#aabbcc") +// c := HEX("0xaabbcc") +// c.Print("message") func HEX(hex string, isBg ...bool) RGBColor { if rgb := HexToRgb(hex); len(rgb) > 0 { return RGB(uint8(rgb[0]), uint8(rgb[1]), uint8(rgb[2]), isBg...) @@ -146,12 +139,11 @@ func RGBFromSlice(rgb []uint8, isBg ...bool) RGBColor { // Support use color name in the {namedRgbMap} // // Usage: +// c := RGBFromString("170,187,204") +// c.Print("message") // -// c := RGBFromString("170,187,204") -// c.Print("message") -// -// c := RGBFromString("brown") -// c.Print("message with color brown") +// c := RGBFromString("brown") +// c.Print("message with color brown") func RGBFromString(rgb string, isBg ...bool) RGBColor { // use color name in the {namedRgbMap} if rgbVal, ok := namedRgbMap[rgb]; ok { @@ -188,27 +180,27 @@ func (c RGBColor) Reset() error { } // Print print message -func (c RGBColor) Print(a ...any) { +func (c RGBColor) Print(a ...interface{}) { doPrintV2(c.String(), fmt.Sprint(a...)) } // Printf format and print message -func (c RGBColor) Printf(format string, a ...any) { +func (c RGBColor) Printf(format string, a ...interface{}) { doPrintV2(c.String(), fmt.Sprintf(format, a...)) } // Println print message with newline -func (c RGBColor) Println(a ...any) { +func (c RGBColor) Println(a ...interface{}) { doPrintlnV2(c.String(), a) } // Sprint returns rendered message -func (c RGBColor) Sprint(a ...any) string { +func (c RGBColor) Sprint(a ...interface{}) string { return RenderCode(c.String(), a...) } // Sprintf returns format and rendered message -func (c RGBColor) Sprintf(format string, a ...any) string { +func (c RGBColor) Sprintf(format string, a ...interface{}) string { return RenderString(c.String(), fmt.Sprintf(format, a...)) } @@ -287,8 +279,8 @@ func (c RGBColor) C16() Color { return c.Basic() } // All are composed of 4 digits uint8, the first three digits are the color value; // The last bit is different from RGBColor, here it indicates whether the value is set. // -// 1 Has been set -// ^1 Not set +// 1 Has been set +// ^1 Not set type RGBStyle struct { // Name of the style Name string @@ -311,9 +303,8 @@ func NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle { // HEXStyle create a RGBStyle from HEX color string. // // Usage: -// -// s := HEXStyle("aabbcc", "eee") -// s.Print("message") +// s := HEXStyle("aabbcc", "eee") +// s.Print("message") func HEXStyle(fg string, bg ...string) *RGBStyle { s := &RGBStyle{} if len(bg) > 0 { @@ -329,9 +320,8 @@ func HEXStyle(fg string, bg ...string) *RGBStyle { // RGBStyleFromString create a RGBStyle from color value string. // // Usage: -// -// s := RGBStyleFromString("170,187,204", "70,87,4") -// s.Print("message") +// s := RGBStyleFromString("170,187,204", "70,87,4") +// s.Print("message") func RGBStyleFromString(fg string, bg ...string) *RGBStyle { s := &RGBStyle{} if len(bg) > 0 { @@ -373,27 +363,27 @@ func (s *RGBStyle) AddOpts(opts ...Color) *RGBStyle { } // Print print message -func (s *RGBStyle) Print(a ...any) { +func (s *RGBStyle) Print(a ...interface{}) { doPrintV2(s.String(), fmt.Sprint(a...)) } // Printf format and print message -func (s *RGBStyle) Printf(format string, a ...any) { +func (s *RGBStyle) Printf(format string, a ...interface{}) { doPrintV2(s.String(), fmt.Sprintf(format, a...)) } // Println print message with newline -func (s *RGBStyle) Println(a ...any) { +func (s *RGBStyle) Println(a ...interface{}) { doPrintlnV2(s.String(), a) } // Sprint returns rendered message -func (s *RGBStyle) Sprint(a ...any) string { +func (s *RGBStyle) Sprint(a ...interface{}) string { return RenderCode(s.String(), a...) } // Sprintf returns format and rendered message -func (s *RGBStyle) Sprintf(format string, a ...any) string { +func (s *RGBStyle) Sprintf(format string, a ...interface{}) string { return RenderString(s.String(), fmt.Sprintf(format, a...)) } diff --git a/vendor/github.com/gookit/color/color_tag.go b/vendor/github.com/gookit/color/color_tag.go index 1d2b9d3..4f6fed9 100644 --- a/vendor/github.com/gookit/color/color_tag.go +++ b/vendor/github.com/gookit/color/color_tag.go @@ -41,8 +41,7 @@ var ( // There are internal defined fg color tags // // Usage: -// -// content text +// content text // // @notice 加 0 在前面是为了防止之前的影响到现在的设置 var colorTags = map[string]string{ @@ -325,17 +324,15 @@ func (tp *TagParser) ParseByEnv(str string) string { return tp.Parse(str) } -// Parse given string, replace color tag and return rendered string +// Parse parse given string, replace color tag and return rendered string // // Use built in tags: -// -// CONTENT -// // e.g: `message` +// CONTENT +// // e.g: `message` // // Custom tag attributes: -// -// `CONTENT` -// // e.g: `wel` +// `CONTENT` +// // e.g: `wel` func (tp *TagParser) Parse(str string) string { // not contains color tag if !strings.Contains(str, "") { @@ -379,30 +376,26 @@ func ReplaceTag(str string) string { // ParseCodeFromAttr parse color attributes. // // attr format: -// -// // VALUE please see var: FgColors, BgColors, AllOptions -// "fg=VALUE;bg=VALUE;op=VALUE" +// // VALUE please see var: FgColors, BgColors, AllOptions +// "fg=VALUE;bg=VALUE;op=VALUE" // // 16 color: -// -// "fg=yellow" -// "bg=red" -// "op=bold,underscore" // option is allow multi value -// "fg=white;bg=blue;op=bold" -// "fg=white;op=bold,underscore" +// "fg=yellow" +// "bg=red" +// "op=bold,underscore" // option is allow multi value +// "fg=white;bg=blue;op=bold" +// "fg=white;op=bold,underscore" // // 256 color: -// // "fg=167" // "fg=167;bg=23" // "fg=167;bg=23;op=bold" // // True color: -// -// // hex +// // hex // "fg=fc1cac" // "fg=fc1cac;bg=c2c3c4" -// // r,g,b +// // r,g,b // "fg=23,45,214" // "fg=23,45,214;bg=109,99,88" func ParseCodeFromAttr(attr string) (code string) { @@ -483,10 +476,12 @@ func ClearTag(s string) string { *************************************************************/ // GetTagCode get color code by tag name -func GetTagCode(name string) string { return colorTags[name] } +func GetTagCode(name string) string { + return colorTags[name] +} // ApplyTag for messages -func ApplyTag(tag string, a ...any) string { +func ApplyTag(tag string, a ...interface{}) string { return RenderCode(GetTagCode(tag), a...) } @@ -515,12 +510,11 @@ func IsDefinedTag(name string) bool { // Tag value is a defined style name // Usage: -// -// Tag("info").Println("message") +// Tag("info").Println("message") type Tag string // Print messages -func (tg Tag) Print(a ...any) { +func (tg Tag) Print(a ...interface{}) { name := string(tg) str := fmt.Sprint(a...) @@ -532,7 +526,7 @@ func (tg Tag) Print(a ...any) { } // Printf format and print messages -func (tg Tag) Printf(format string, a ...any) { +func (tg Tag) Printf(format string, a ...interface{}) { name := string(tg) str := fmt.Sprintf(format, a...) @@ -544,7 +538,7 @@ func (tg Tag) Printf(format string, a ...any) { } // Println messages line -func (tg Tag) Println(a ...any) { +func (tg Tag) Println(a ...interface{}) { name := string(tg) if stl := GetStyle(name); !stl.IsEmpty() { stl.Println(a...) @@ -554,12 +548,12 @@ func (tg Tag) Println(a ...any) { } // Sprint render messages -func (tg Tag) Sprint(a ...any) string { +func (tg Tag) Sprint(a ...interface{}) string { return RenderCode(GetTagCode(string(tg)), a...) } // Sprintf format and render messages -func (tg Tag) Sprintf(format string, a ...any) string { +func (tg Tag) Sprintf(format string, a ...interface{}) string { tag := string(tg) str := fmt.Sprintf(format, a...) diff --git a/vendor/github.com/gookit/color/printer.go b/vendor/github.com/gookit/color/printer.go index 985a0b6..326aabc 100644 --- a/vendor/github.com/gookit/color/printer.go +++ b/vendor/github.com/gookit/color/printer.go @@ -9,19 +9,18 @@ import "fmt" // PrinterFace interface type PrinterFace interface { fmt.Stringer - Sprint(a ...any) string - Sprintf(format string, a ...any) string - Print(a ...any) - Printf(format string, a ...any) - Println(a ...any) + Sprint(a ...interface{}) string + Sprintf(format string, a ...interface{}) string + Print(a ...interface{}) + Printf(format string, a ...interface{}) + Println(a ...interface{}) } // Printer a generic color message printer. // // Usage: -// -// p := &Printer{Code: "32;45;3"} -// p.Print("message") +// p := &Printer{Code: "32;45;3"} +// p.Print("message") type Printer struct { // NoColor disable color. NoColor bool @@ -41,27 +40,27 @@ func (p *Printer) String() string { } // Sprint returns rendering colored messages -func (p *Printer) Sprint(a ...any) string { +func (p *Printer) Sprint(a ...interface{}) string { return RenderCode(p.String(), a...) } // Sprintf returns format and rendering colored messages -func (p *Printer) Sprintf(format string, a ...any) string { +func (p *Printer) Sprintf(format string, a ...interface{}) string { return RenderString(p.String(), fmt.Sprintf(format, a...)) } // Print rendering colored messages -func (p *Printer) Print(a ...any) { +func (p *Printer) Print(a ...interface{}) { doPrintV2(p.String(), fmt.Sprint(a...)) } // Printf format and rendering colored messages -func (p *Printer) Printf(format string, a ...any) { +func (p *Printer) Printf(format string, a ...interface{}) { doPrintV2(p.String(), fmt.Sprintf(format, a...)) } // Println rendering colored messages with newline -func (p *Printer) Println(a ...any) { +func (p *Printer) Println(a ...interface{}) { doPrintlnV2(p.Code, a) } @@ -78,56 +77,46 @@ func (p *Printer) IsEmpty() bool { type SimplePrinter struct{} // Print message -func (s *SimplePrinter) Print(v ...any) { +func (s *SimplePrinter) Print(v ...interface{}) { Print(v...) } // Printf message -func (s *SimplePrinter) Printf(format string, v ...any) { +func (s *SimplePrinter) Printf(format string, v ...interface{}) { Printf(format, v...) } // Println message -func (s *SimplePrinter) Println(v ...any) { +func (s *SimplePrinter) Println(v ...interface{}) { Println(v...) } -// Successf message -func (s *SimplePrinter) Successf(format string, a ...any) { - Success.Printf(format, a...) -} - -// Successln message -func (s *SimplePrinter) Successln(a ...any) { - Success.Println(a...) -} - // Infof message -func (s *SimplePrinter) Infof(format string, a ...any) { +func (s *SimplePrinter) Infof(format string, a ...interface{}) { Info.Printf(format, a...) } // Infoln message -func (s *SimplePrinter) Infoln(a ...any) { +func (s *SimplePrinter) Infoln(a ...interface{}) { Info.Println(a...) } // Warnf message -func (s *SimplePrinter) Warnf(format string, a ...any) { +func (s *SimplePrinter) Warnf(format string, a ...interface{}) { Warn.Printf(format, a...) } // Warnln message -func (s *SimplePrinter) Warnln(a ...any) { +func (s *SimplePrinter) Warnln(a ...interface{}) { Warn.Println(a...) } // Errorf message -func (s *SimplePrinter) Errorf(format string, a ...any) { +func (s *SimplePrinter) Errorf(format string, a ...interface{}) { Error.Printf(format, a...) } // Errorln message -func (s *SimplePrinter) Errorln(a ...any) { +func (s *SimplePrinter) Errorln(a ...interface{}) { Error.Println(a...) } diff --git a/vendor/github.com/gookit/color/quickstart.go b/vendor/github.com/gookit/color/quickstart.go index b368b8a..4dbd1a4 100644 --- a/vendor/github.com/gookit/color/quickstart.go +++ b/vendor/github.com/gookit/color/quickstart.go @@ -5,104 +5,104 @@ package color *************************************************************/ // Redp print message with Red color -func Redp(a ...any) { Red.Print(a...) } +func Redp(a ...interface{}) { Red.Print(a...) } // Redf print message with Red color -func Redf(format string, a ...any) { Red.Printf(format, a...) } +func Redf(format string, a ...interface{}) { Red.Printf(format, a...) } // Redln print message line with Red color -func Redln(a ...any) { Red.Println(a...) } +func Redln(a ...interface{}) { Red.Println(a...) } // Bluep print message with Blue color -func Bluep(a ...any) { Blue.Print(a...) } +func Bluep(a ...interface{}) { Blue.Print(a...) } // Bluef print message with Blue color -func Bluef(format string, a ...any) { Blue.Printf(format, a...) } +func Bluef(format string, a ...interface{}) { Blue.Printf(format, a...) } // Blueln print message line with Blue color -func Blueln(a ...any) { Blue.Println(a...) } +func Blueln(a ...interface{}) { Blue.Println(a...) } // Cyanp print message with Cyan color -func Cyanp(a ...any) { Cyan.Print(a...) } +func Cyanp(a ...interface{}) { Cyan.Print(a...) } // Cyanf print message with Cyan color -func Cyanf(format string, a ...any) { Cyan.Printf(format, a...) } +func Cyanf(format string, a ...interface{}) { Cyan.Printf(format, a...) } // Cyanln print message line with Cyan color -func Cyanln(a ...any) { Cyan.Println(a...) } +func Cyanln(a ...interface{}) { Cyan.Println(a...) } // Grayp print message with Gray color -func Grayp(a ...any) { Gray.Print(a...) } +func Grayp(a ...interface{}) { Gray.Print(a...) } // Grayf print message with Gray color -func Grayf(format string, a ...any) { Gray.Printf(format, a...) } +func Grayf(format string, a ...interface{}) { Gray.Printf(format, a...) } // Grayln print message line with Gray color -func Grayln(a ...any) { Gray.Println(a...) } +func Grayln(a ...interface{}) { Gray.Println(a...) } // Greenp print message with Green color -func Greenp(a ...any) { Green.Print(a...) } +func Greenp(a ...interface{}) { Green.Print(a...) } // Greenf print message with Green color -func Greenf(format string, a ...any) { Green.Printf(format, a...) } +func Greenf(format string, a ...interface{}) { Green.Printf(format, a...) } // Greenln print message line with Green color -func Greenln(a ...any) { Green.Println(a...) } +func Greenln(a ...interface{}) { Green.Println(a...) } // Yellowp print message with Yellow color -func Yellowp(a ...any) { Yellow.Print(a...) } +func Yellowp(a ...interface{}) { Yellow.Print(a...) } // Yellowf print message with Yellow color -func Yellowf(format string, a ...any) { Yellow.Printf(format, a...) } +func Yellowf(format string, a ...interface{}) { Yellow.Printf(format, a...) } // Yellowln print message line with Yellow color -func Yellowln(a ...any) { Yellow.Println(a...) } +func Yellowln(a ...interface{}) { Yellow.Println(a...) } // Magentap print message with Magenta color -func Magentap(a ...any) { Magenta.Print(a...) } +func Magentap(a ...interface{}) { Magenta.Print(a...) } // Magentaf print message with Magenta color -func Magentaf(format string, a ...any) { Magenta.Printf(format, a...) } +func Magentaf(format string, a ...interface{}) { Magenta.Printf(format, a...) } // Magentaln print message line with Magenta color -func Magentaln(a ...any) { Magenta.Println(a...) } +func Magentaln(a ...interface{}) { Magenta.Println(a...) } /************************************************************* * quick use style print message *************************************************************/ // Infop print message with Info color -func Infop(a ...any) { Info.Print(a...) } +func Infop(a ...interface{}) { Info.Print(a...) } // Infof print message with Info style -func Infof(format string, a ...any) { Info.Printf(format, a...) } +func Infof(format string, a ...interface{}) { Info.Printf(format, a...) } // Infoln print message with Info style -func Infoln(a ...any) { Info.Println(a...) } +func Infoln(a ...interface{}) { Info.Println(a...) } // Successp print message with success color -func Successp(a ...any) { Success.Print(a...) } +func Successp(a ...interface{}) { Success.Print(a...) } // Successf print message with success style -func Successf(format string, a ...any) { Success.Printf(format, a...) } +func Successf(format string, a ...interface{}) { Success.Printf(format, a...) } // Successln print message with success style -func Successln(a ...any) { Success.Println(a...) } +func Successln(a ...interface{}) { Success.Println(a...) } // Errorp print message with Error color -func Errorp(a ...any) { Error.Print(a...) } +func Errorp(a ...interface{}) { Error.Print(a...) } // Errorf print message with Error style -func Errorf(format string, a ...any) { Error.Printf(format, a...) } +func Errorf(format string, a ...interface{}) { Error.Printf(format, a...) } // Errorln print message with Error style -func Errorln(a ...any) { Error.Println(a...) } +func Errorln(a ...interface{}) { Error.Println(a...) } // Warnp print message with Warn color -func Warnp(a ...any) { Warn.Print(a...) } +func Warnp(a ...interface{}) { Warn.Print(a...) } // Warnf print message with Warn style -func Warnf(format string, a ...any) { Warn.Printf(format, a...) } +func Warnf(format string, a ...interface{}) { Warn.Printf(format, a...) } // Warnln print message with Warn style -func Warnln(a ...any) { Warn.Println(a...) } +func Warnln(a ...interface{}) { Warn.Println(a...) } diff --git a/vendor/github.com/gookit/color/style.go b/vendor/github.com/gookit/color/style.go index a009d1d..fad76fb 100644 --- a/vendor/github.com/gookit/color/style.go +++ b/vendor/github.com/gookit/color/style.go @@ -12,14 +12,12 @@ import ( // Style a 16 color style. can add: fg color, bg color, color options // // Example: -// -// color.Style{color.FgGreen}.Print("message") +// color.Style{color.FgGreen}.Print("message") type Style []Color // New create a custom style // // Usage: -// // color.New(color.FgGreen).Print("message") // equals to: // color.Style{color.FgGreen}.Print("message") @@ -39,45 +37,43 @@ func (s *Style) Add(cs ...Color) { // Render render text // Usage: -// -// color.New(color.FgGreen).Render("text") -// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text") -func (s Style) Render(a ...any) string { +// color.New(color.FgGreen).Render("text") +// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text") +func (s Style) Render(a ...interface{}) string { return RenderCode(s.String(), a...) } // Renderln render text line. // like Println, will add spaces for each argument // Usage: -// -// color.New(color.FgGreen).Renderln("text", "more") -// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more") -func (s Style) Renderln(a ...any) string { +// color.New(color.FgGreen).Renderln("text", "more") +// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more") +func (s Style) Renderln(a ...interface{}) string { return RenderWithSpaces(s.String(), a...) } // Sprint is alias of the 'Render' -func (s Style) Sprint(a ...any) string { +func (s Style) Sprint(a ...interface{}) string { return RenderCode(s.String(), a...) } // Sprintf format and render message. -func (s Style) Sprintf(format string, a ...any) string { +func (s Style) Sprintf(format string, a ...interface{}) string { return RenderString(s.String(), fmt.Sprintf(format, a...)) } // Print render and Print text -func (s Style) Print(a ...any) { +func (s Style) Print(a ...interface{}) { doPrintV2(s.String(), fmt.Sprint(a...)) } // Printf render and print text -func (s Style) Printf(format string, a ...any) { +func (s Style) Printf(format string, a ...interface{}) { doPrintV2(s.Code(), fmt.Sprintf(format, a...)) } // Println render and print text line -func (s Style) Println(a ...any) { +func (s Style) Println(a ...interface{}) { doPrintlnV2(s.String(), a) } @@ -119,20 +115,20 @@ func (t *Theme) Save() { } // Tips use name as title, only apply style for name -func (t *Theme) Tips(format string, a ...any) { +func (t *Theme) Tips(format string, a ...interface{}) { // only apply style for name t.Print(strings.ToUpper(t.Name) + ": ") Printf(format+"\n", a...) } // Prompt use name as title, and apply style for message -func (t *Theme) Prompt(format string, a ...any) { +func (t *Theme) Prompt(format string, a ...interface{}) { title := strings.ToUpper(t.Name) + ":" t.Println(title, fmt.Sprintf(format, a...)) } // Block like Prompt, but will wrap a empty line -func (t *Theme) Block(format string, a ...any) { +func (t *Theme) Block(format string, a ...interface{}) { title := strings.ToUpper(t.Name) + ":\n" t.Println(title, fmt.Sprintf(format, a...)) @@ -144,11 +140,10 @@ func (t *Theme) Block(format string, a ...any) { // internal themes(like bootstrap style) // Usage: -// -// color.Info.Print("message") -// color.Info.Printf("a %s message", "test") -// color.Warn.Println("message") -// color.Error.Println("message") +// color.Info.Print("message") +// color.Info.Printf("a %s message", "test") +// color.Warn.Println("message") +// color.Error.Println("message") var ( // Info color style Info = &Theme{"info", Style{OpReset, FgGreen}} @@ -180,8 +175,7 @@ var ( // Themes internal defined themes. // Usage: -// -// color.Themes["info"].Println("message") +// color.Themes["info"].Println("message") var Themes = map[string]*Theme{ "info": Info, "note": Note, @@ -217,8 +211,7 @@ func GetTheme(name string) *Theme { // Styles internal defined styles, like bootstrap styles. // Usage: -// -// color.Styles["info"].Println("message") +// color.Styles["info"].Println("message") var Styles = map[string]Style{ "info": {OpReset, FgGreen}, "note": {OpBold, FgLightCyan}, @@ -292,31 +285,31 @@ func (s *Scheme) Style(name string) Style { } // Infof message print -func (s *Scheme) Infof(format string, a ...any) { +func (s *Scheme) Infof(format string, a ...interface{}) { s.Styles["info"].Printf(format, a...) } // Infoln message print -func (s *Scheme) Infoln(v ...any) { +func (s *Scheme) Infoln(v ...interface{}) { s.Styles["info"].Println(v...) } // Warnf message print -func (s *Scheme) Warnf(format string, a ...any) { +func (s *Scheme) Warnf(format string, a ...interface{}) { s.Styles["warn"].Printf(format, a...) } // Warnln message print -func (s *Scheme) Warnln(v ...any) { +func (s *Scheme) Warnln(v ...interface{}) { s.Styles["warn"].Println(v...) } // Errorf message print -func (s *Scheme) Errorf(format string, a ...any) { +func (s *Scheme) Errorf(format string, a ...interface{}) { s.Styles["error"].Printf(format, a...) } // Errorln message print -func (s *Scheme) Errorln(v ...any) { +func (s *Scheme) Errorln(v ...interface{}) { s.Styles["error"].Println(v...) } diff --git a/vendor/github.com/gookit/color/utils.go b/vendor/github.com/gookit/color/utils.go index b6920f6..4554b27 100644 --- a/vendor/github.com/gookit/color/utils.go +++ b/vendor/github.com/gookit/color/utils.go @@ -32,31 +32,39 @@ func ResetTerminal() error { *************************************************************/ // Print render color tag and print messages -func Print(a ...any) { +func Print(a ...interface{}) { Fprint(output, a...) } // Printf format and print messages -func Printf(format string, a ...any) { +func Printf(format string, a ...interface{}) { Fprintf(output, format, a...) } // Println messages with new line -func Println(a ...any) { +func Println(a ...interface{}) { Fprintln(output, a...) } // Fprint print rendered messages to writer // // Notice: will ignore print error -func Fprint(w io.Writer, a ...any) { +func Fprint(w io.Writer, a ...interface{}) { _, err := fmt.Fprint(w, Render(a...)) saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprint(w, Render(a...)) + // }) + // } else { + // _, _ = fmt.Fprint(w, Render(a...)) + // } } // Fprintf print format and rendered messages to writer. // Notice: will ignore print error -func Fprintf(w io.Writer, format string, a ...any) { +func Fprintf(w io.Writer, format string, a ...interface{}) { str := fmt.Sprintf(format, a...) _, err := fmt.Fprint(w, ReplaceTag(str)) saveInternalError(err) @@ -64,7 +72,7 @@ func Fprintf(w io.Writer, format string, a ...any) { // Fprintln print rendered messages line to writer // Notice: will ignore print error -func Fprintln(w io.Writer, a ...any) { +func Fprintln(w io.Writer, a ...interface{}) { str := formatArgsForPrintln(a) _, err := fmt.Fprintln(w, ReplaceTag(str)) saveInternalError(err) @@ -72,7 +80,7 @@ func Fprintln(w io.Writer, a ...any) { // Lprint passes colored messages to a log.Logger for printing. // Notice: should be goroutine safe -func Lprint(l *log.Logger, a ...any) { +func Lprint(l *log.Logger, a ...interface{}) { l.Print(Render(a...)) } @@ -82,7 +90,7 @@ func Lprint(l *log.Logger, a ...any) { // // text := Render("hello world!") // fmt.Println(text) -func Render(a ...any) string { +func Render(a ...interface{}) string { if len(a) == 0 { return "" } @@ -90,23 +98,28 @@ func Render(a ...any) string { } // Sprint parse color tags, return rendered string -func Sprint(a ...any) string { +func Sprint(a ...interface{}) string { if len(a) == 0 { return "" } + return ReplaceTag(fmt.Sprint(a...)) } // Sprintf format and return rendered string -func Sprintf(format string, a ...any) string { +func Sprintf(format string, a ...interface{}) string { return ReplaceTag(fmt.Sprintf(format, a...)) } // String alias of the ReplaceTag -func String(s string) string { return ReplaceTag(s) } +func String(s string) string { + return ReplaceTag(s) +} // Text alias of the ReplaceTag -func Text(s string) string { return ReplaceTag(s) } +func Text(s string) string { + return ReplaceTag(s) +} // Uint8sToInts convert []uint8 to []int // func Uint8sToInts(u8s []uint8 ) []int { @@ -125,17 +138,25 @@ func Text(s string) string { return ReplaceTag(s) } func doPrintV2(code, str string) { _, err := fmt.Fprint(output, RenderString(code, str)) saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprint(output, RenderString(code, str)) + // }) + // } else { + // _, _ = fmt.Fprint(output, RenderString(code, str)) + // } } // new implementation, support render full color code on pwsh.exe, cmd.exe -func doPrintlnV2(code string, args []any) { +func doPrintlnV2(code string, args []interface{}) { str := formatArgsForPrintln(args) _, err := fmt.Fprintln(output, RenderString(code, str)) saveInternalError(err) } // use Println, will add spaces for each arg -func formatArgsForPrintln(args []any) (message string) { +func formatArgsForPrintln(args []interface{}) (message string) { if ln := len(args); ln == 0 { message = "" } else if ln == 1 { @@ -157,7 +178,7 @@ func formatArgsForPrintln(args []any) (message string) { // return debugMode == "on" // } -func debugf(f string, v ...any) { +func debugf(f string, v ...interface{}) { if debugMode { fmt.Print("COLOR_DEBUG: ") fmt.Printf(f, v...) diff --git a/vendor/github.com/gookit/goutil/Makefile b/vendor/github.com/gookit/goutil/Makefile index 19b591e..f902a5f 100644 --- a/vendor/github.com/gookit/goutil/Makefile +++ b/vendor/github.com/gookit/goutil/Makefile @@ -29,7 +29,7 @@ readme: readme-c: ## Generate or update README file and commit change to git readme-c: readme git add README.* internal - git commit -m ":memo: doc: update and re-generate README docs" + git commit -m "doc: update and re-generate README docs" csfix: ## Fix code style for all files by go fmt csfix: diff --git a/vendor/github.com/gookit/goutil/README.md b/vendor/github.com/gookit/goutil/README.md index cbd0cde..66658a9 100644 --- a/vendor/github.com/gookit/goutil/README.md +++ b/vendor/github.com/gookit/goutil/README.md @@ -7,7 +7,7 @@ [![Coverage Status](https://coveralls.io/repos/github/gookit/goutil/badge.svg?branch=master)](https://coveralls.io/github/gookit/goutil?branch=master) [![Go Reference](https://pkg.go.dev/badge/github.com/gookit/goutil.svg)](https://pkg.go.dev/github.com/gookit/goutil) -💪 Useful utils(**600+**) package for the Go: int, string, array/slice, map, error, time, format, CLI, ENV, filesystem, system, testing and more. +💪 Useful utils(**500+**) package for the Go: int, string, array/slice, map, error, time, format, CLI, ENV, filesystem, system, testing and more. > **[中文说明](README.zh-CN.md)** @@ -18,7 +18,7 @@ - [`envutil`](./envutil) ENV util for current runtime env information. eg: get one, get info, parse var - [`fmtutil`](./fmtutil) Format data util functions. eg: data, size, time - [`fsutil`](./fsutil) Filesystem util functions, quick create, read and write file. eg: file and dir check, operate -- [`jsonutil`](./jsonutil) Provide some util functions for quick read, write, encode, decode JSON data. +- [`jsonutil`](./jsonutil) some util functions for quick read, write, encode, decode JSON data. - [`maputil`](./maputil) Map data util functions. eg: convert, sub-value get, simple merge - [`mathutil`](./mathutil) Math(int, number) util functions. eg: convert, math calc, random - `netutil` Network util functions @@ -35,19 +35,16 @@ - [cmdline](./cliutil/cmdline) Provide cmdline parse, args build to cmdline - [`dump`](./dump): GO value printing tool. print slice, map will auto wrap each element and display the call location - [`errorx`](./errorx) Provide an enhanced error implements for go, allow with stacktrace and wrap another error. -- [`finder`](./fsutil/finder) Provides a simple and convenient filedir lookup function, supports filtering, excluding, matching, ignoring, etc. - net util: - [httpreq](netutil/httpreq) An easier-to-use HTTP client that wraps http.Client - string util: - [textscan](strutil/textscan) Implemented a parser that quickly scans and analyzes text content. It can be used to parse INI, Properties and other formats - - [textutil](strutil/textutil) Provide some extensions text handle util functions. eg: text replace, etc. -- system util: +- sys util: - [clipboard](./sysutil/clipboard) Provide a simple clipboard read and write operations. - [cmdr](./sysutil/cmdr) Provide for quick build and run a cmd, batch run multi cmd tasks - [process](./sysutil/process) Provide some process handle util functions. -- [`testutil`](testutil) Test help util functions. eg: http test, mock ENV value - - [assert](testutil/assert) Provides commonly asserts functions for help testing - - [fakeobj](testutil/fakeobj) provides a fake object for testing. such as fake fs.File, fs.FileInfo, fs.DirEntry etc. +- [`testutil`](./testutil) Test help util functions. eg: http test, mock ENV value + - [assert](./testutil/assert) Asserts functions for help testing - [`timex`](./timex) Provides an enhanced time.Time implementation. Add more commonly used functional methods - such as: DayStart(), DayAfter(), DayAgo(), DateFormat() and more. @@ -138,9 +135,8 @@ func SliceToInt64s(arr []any) []int64 func StringsAsInts(ss []string) []int func StringsToInts(ss []string) (ints []int, err error) func StringsTryInts(ss []string) (ints []int, err error) -func AnyToSlice(sl any) (ls []any, err error) -func AnyToStrings(arr any) []string func MustToStrings(arr any) []string +func AnyToStrings(arr any) []string func StringsToSlice(ss []string) []any func ToStrings(arr any) (ret []string, err error) func SliceToStrings(arr []any) []string @@ -149,7 +145,6 @@ func ConvType[T any, R any](arr []T, newElemTyp R) ([]R, error) func AnyToString(arr any) string func SliceToString(arr ...any) string func ToString(arr []any) string -func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V func CombineToSMap(keys, values []string) map[string]string // source at arrutil/format.go func NewFormatter(arr any) *ArrFormatter @@ -177,6 +172,24 @@ ss, err := arrutil.ToStrings([]int{1, 2}) // ss: []string{"1", "2"} ``` +### Basefn + +> Package `github.com/gookit/goutil/basefn` + +```go +// source at basefn/basefunc.go +func Panicf(format string, v ...any) +func MustOK(err error) +func Must[T any](v T, err error) T +func ErrOnFail(cond bool, err error) error +func OrError(cond bool, err error) error +func FirstOr[T any](sl []T, elseVal T) T +func OrValue[T any](cond bool, okVal, elVal T) T +func OrReturn[T any](cond bool, okFn, elseFn func() T) T +func CallOn(cond bool, fn ErrFunc) error +func CallOrElse(cond bool, okFn, elseFn ErrFunc) error +``` + ### Bytes Utils > Package `github.com/gookit/goutil/byteutil` @@ -185,14 +198,9 @@ ss, err := arrutil.ToStrings([]int{1, 2}) // ss: []string{"1", "2"} // source at byteutil/buffer.go func NewBuffer() *Buffer // source at byteutil/byteutil.go -func Random(length int) ([]byte, error) func FirstLine(bs []byte) []byte func StrOrErr(bs []byte, err error) (string, error) func SafeString(bs []byte, err error) string -func String(b []byte) string -func ToString(b []byte) string -func AppendAny(dst []byte, v any) []byte -func Cut(bs []byte, sep byte) (before, after []byte, found bool) // source at byteutil/bytex.go func Md5(src any) []byte // source at byteutil/check.go @@ -306,9 +314,7 @@ func ReadLine(question string) (string, error) func ReadFirst(question string) (string, error) func ReadFirstByte(question string) (byte, error) func ReadFirstRune(question string) (rune, error) -func ReadAsBool(tip string, defVal bool) bool func ReadPassword(question ...string) string -func Confirm(tip string, defVal ...bool) bool func InputIsYes(ans string) bool func ByteIsYes(ans byte) bool ``` @@ -540,10 +546,7 @@ func Config(fns ...func(opt *ErrStackOpt)) func SkipDepth(skipDepth int) func(opt *ErrStackOpt) func TraceDepth(traceDepth int) func(opt *ErrStackOpt) // source at errorx/util.go -func Err(msg string) error func Raw(msg string) error -func Ef(tpl string, vars ...any) error -func Errf(tpl string, vars ...any) error func Rawf(tpl string, vars ...any) error func Cause(err error) error func Unwrap(err error) error @@ -636,8 +639,6 @@ runtime.goexit() > Package `github.com/gookit/goutil/fmtutil` ```go -// source at fmtutil/fmtutil.go -func StringOrJSON(v any) ([]byte, error) // source at fmtutil/format.go func DataSize(size uint64) string func SizeToString(size uint64) string @@ -645,7 +646,7 @@ func StringToByte(sizeStr string) uint64 func ParseByte(sizeStr string) uint64 func PrettyJSON(v any) (string, error) func StringsToInts(ss []string) (ints []int, err error) -func ArgsWithSpaces(vs []any) (message string) +func ArgsWithSpaces(args []any) (message string) // source at fmtutil/time.go func HowLongAgo(sec int64) string ``` @@ -663,21 +664,6 @@ func IsFile(path string) bool func IsAbsPath(aPath string) bool func IsImageFile(path string) bool func IsZipFile(filepath string) bool -func PathMatch(pattern, s string) bool -// source at fsutil/find.go -func SearchNameUp(dirPath, name string) string -func SearchNameUpx(dirPath, name string) (string, bool) -func WalkDir(dir string, fn fs.WalkDirFunc) error -func Glob(pattern string, fls ...comdef.StringMatchFunc) []string -func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) -func OnlyFindDir(_ string, ent fs.DirEntry) bool -func OnlyFindFile(_ string, ent fs.DirEntry) bool -func ExcludeNames(names ...string) FilterFunc -func IncludeSuffix(ss ...string) FilterFunc -func ExcludeDotFile(_ string, ent fs.DirEntry) bool -func ExcludeSuffix(ss ...string) FilterFunc -func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool -func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) // source at fsutil/fsutil.go func OSTempFile(pattern string) (*os.File, error) func TempFile(dir, pattern string) (*os.File, error) @@ -686,10 +672,8 @@ func TempDir(dir, pattern string) (string, error) func MimeType(path string) (mime string) func ReaderMimeType(r io.Reader) (mime string) func JoinPaths(elem ...string) string -func JoinSubPaths(basePath string, elem ...string) string func SlashPath(path string) string func UnixPath(path string) string -func ToAbsPath(p string) string // source at fsutil/info.go func Dir(fpath string) string func PathName(fpath string) string @@ -699,8 +683,9 @@ func Extname(fpath string) string func Suffix(fpath string) string func Expand(pathStr string) string func ExpandPath(pathStr string) string -func ResolvePath(pathStr string) string func SplitPath(pathStr string) (dir, name string) +func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) +func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) // source at fsutil/info_nonwin.go func Realpath(pathStr string) string // source at fsutil/operate.go @@ -709,10 +694,9 @@ func MkDirs(perm os.FileMode, dirPaths ...string) error func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error func MkParentDir(fpath string) error func OpenFile(filepath string, flag int, perm os.FileMode) (*os.File, error) -func MustOpenFile(filepath string, flag int, perm os.FileMode) *os.File func QuickOpenFile(filepath string, fileFlag ...int) (*os.File, error) -func OpenAppendFile(filepath string, filePerm ...os.FileMode) (*os.File, error) -func OpenTruncFile(filepath string, filePerm ...os.FileMode) (*os.File, error) +func OpenAppendFile(filepath string) (*os.File, error) +func OpenTruncFile(filepath string) (*os.File, error) func OpenReadFile(filepath string) (*os.File, error) func CreateFile(fpath string, filePerm, dirPerm os.FileMode, fileFlag ...int) (*os.File, error) func MustCreateFile(filePath string, filePerm, dirPerm os.FileMode) *os.File @@ -723,7 +707,6 @@ func RmIfExist(fPath string) error func DeleteIfExist(fPath string) error func RmFileIfExist(fPath string) error func DeleteIfFileExist(fPath string) error -func RemoveSub(dirPath string, fns ...FilterFunc) error func Unzip(archive, targetDir string) (err error) // source at fsutil/opread.go func NewIOReader(in any) (r io.Reader, err error) @@ -733,10 +716,8 @@ func MustReadFile(filePath string) []byte func ReadReader(r io.Reader) []byte func MustReadReader(r io.Reader) []byte func ReadString(in any) string -func ReadStringOrErr(in any) (string, error) func ReadAll(in any) []byte func GetContents(in any) []byte -func ReadOrErr(in any) ([]byte, error) func ReadExistFile(filePath string) []byte func TextScanner(in any) *scanner.Scanner func LineScanner(in any) *bufio.Scanner @@ -757,23 +738,30 @@ package main import ( "fmt" - "io/fs" + "os" - "github.com/gookit/goutil/fsutil" + "github.com/gookit/goutil/fsutil/finder" ) func main() { - // find all files in dir - fsutil.FindInDir("./", func(filePath string, de fs.DirEntry) error { - fmt.Println(filePath) - return nil - }) - - // find files with filters - fsutil.FindInDir("./", func(filePath string, de fs.DirEntry) error { - fmt.Println(filePath) - return nil - }, fsutil.ExcludeDotFile) + f := finder.EmptyFinder() + + f. + AddDir("./testdata"). + AddFile("finder.go"). + NoDotFile(). + // NoDotDir(). + Find(). + Each(func(filePath string) { + fmt.Println(filePath) + }) + + finder.NewFinder([]string{"./testdata"}). + AddFile("finder.go"). + NoDotDir(). + EachStat(func(fi os.FileInfo, filePath string) { + fmt.Println(filePath, "=>", fi.ModTime()) + }) } ``` @@ -785,7 +773,6 @@ func main() { ```go // source at jsonutil/jsonutil.go func WriteFile(filePath string, data any) error -func WritePretty(filePath string, data any) error func ReadFile(filePath string, v any) error func Pretty(v any) (string, error) func Encode(v any) ([]byte, error) @@ -796,8 +783,6 @@ func Decode(bts []byte, ptr any) error func DecodeString(str string, ptr any) error func DecodeReader(r io.Reader, ptr any) error func Mapping(src, dst any) error -func IsJSON(s string) bool -func IsJSONFast(s string) bool func StripComments(src string) string ``` @@ -808,17 +793,12 @@ func StripComments(src string) string ```go // source at maputil/check.go func HasKey(mp, key any) (ok bool) -func HasOneKey(mp any, keys ...any) (ok bool, key any) func HasAllKeys(mp any, keys ...any) (ok bool, noKey any) // source at maputil/convert.go func KeyToLower(src map[string]string) map[string]string func ToStringMap(src map[string]any) map[string]string func CombineToSMap(keys, values []string) SMap -func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V -func ToAnyMap(mp any) map[string]any -func TryAnyMap(mp any) (map[string]any, error) func HTTPQueryString(data map[string]any) string -func StringsMapToAnyMap(ssMp map[string][]string) map[string]any func ToString(mp map[string]any) string func ToString2(mp any) string func FormatIndent(mp any, indent string) string @@ -830,10 +810,8 @@ func NewFormatter(mp any) *MapFormatter func DeepGet(mp map[string]any, path string) (val any) func QuietGet(mp map[string]any, path string) (val any) func GetByPath(path string, mp map[string]any) (val any, ok bool) -func GetByPathKeys(mp map[string]any, keys []string) (val any, ok bool) func Keys(mp any) (keys []string) func Values(mp any) (values []any) -func EachAnyMap(mp any, fn func(key string, val any)) // source at maputil/maputil.go func SimpleMerge(src, dst map[string]any) map[string]any func DeepMerge(src, dst map[string]any, deep int) map[string]any @@ -853,13 +831,8 @@ func SetByKeys(mp *map[string]any, keys []string, val any) (err error) ```go // source at mathutil/check.go func Compare(srcVal, dstVal any, op string) (ok bool) -func CompInt[T comdef.Xint](srcVal, dstVal T, op string) (ok bool) -func CompInt64(srcVal, dstVal int64, op string) bool -func CompFloat[T comdef.Float](srcVal, dstVal T, op string) (ok bool) -func CompValue[T comdef.XintOrFloat](srcVal, dstVal T, op string) (ok bool) -func InRange[T comdef.IntOrFloat](val, min, max T) bool -func OutRange[T comdef.IntOrFloat](val, min, max T) bool -func InUintRange[T comdef.Uint](val, min, max T) bool +func CompInt64(srcI64, dstI64 int64, op string) (ok bool) +func CompFloat(srcF64, dstF64 float64, op string) (ok bool) // source at mathutil/convert.go func Int(in any) (int, error) func QuietInt(in any) int @@ -893,9 +866,7 @@ func QuietString(val any) string func String(val any) string func TryToString(val any, defaultAsErr bool) (str string, err error) // source at mathutil/mathutil.go -func Min[T comdef.XintOrFloat](x, y T) T func Max[T comdef.XintOrFloat](x, y T) T -func SwapMin[T comdef.XintOrFloat](x, y T) (T, T) func SwapMax[T comdef.XintOrFloat](x, y T) (T, T) func MaxInt(x, y int) int func SwapMaxInt(x, y int) (int, int) @@ -924,10 +895,6 @@ func RandomIntWithSeed(min, max int, seed int64) int // source at reflects/check.go func HasChild(v reflect.Value) bool func IsArrayOrSlice(k reflect.Kind) bool -func IsSimpleKind(k reflect.Kind) bool -func IsAnyInt(k reflect.Kind) bool -func IsIntx(k reflect.Kind) bool -func IsUintX(k reflect.Kind) bool func IsNil(v reflect.Value) bool func IsFunc(val any) bool func IsEqual(src, dst any) bool @@ -950,13 +917,7 @@ func Elem(v reflect.Value) reflect.Value func Indirect(v reflect.Value) reflect.Value func Len(v reflect.Value) int func SliceSubKind(typ reflect.Type) reflect.Kind -func SliceElemKind(typ reflect.Type) reflect.Kind -func UnexportedValue(rv reflect.Value) any -func SetUnexportedValue(rv reflect.Value, value any) func SetValue(rv reflect.Value, val any) error -func SetRValue(rv, val reflect.Value) -func EachMap(mp reflect.Value, fn func(key, val reflect.Value)) -func EachStrAnyMap(mp reflect.Value, fn func(key string, val any)) func FlatMap(rv reflect.Value, fn FlatFunc) // source at reflects/value.go func Wrap(rv reflect.Value) Value @@ -969,9 +930,9 @@ func ValueOf(v any) Value ```go // source at stdio/ioutil.go -func QuietFprint(w io.Writer, a ...any) +func QuietFprint(w io.Writer, ss ...string) func QuietFprintf(w io.Writer, tpl string, vs ...any) -func QuietFprintln(w io.Writer, a ...any) +func QuietFprintln(w io.Writer, ss ...string) func QuietWriteString(w io.Writer, ss ...string) // source at stdio/stdio.go func DiscardReader(src io.Reader) @@ -979,9 +940,7 @@ func ReadString(r io.Reader) string func MustReadReader(r io.Reader) []byte func NewIOReader(in any) io.Reader func NewScanner(in any) *bufio.Scanner -func WriteByte(b byte) func WriteBytes(bs []byte) -func WritelnBytes(bs []byte) func WriteString(s string) func Writeln(s string) // source at stdio/writer.go @@ -1041,26 +1000,18 @@ func NewAliases(checker func(alias string)) *Aliases func ToMap(st any, optFns ...MapOptFunc) map[string]any func MustToMap(st any, optFns ...MapOptFunc) map[string]any func TryToMap(st any, optFns ...MapOptFunc) (map[string]any, error) -func ToSMap(st any, optFns ...MapOptFunc) map[string]string -func TryToSMap(st any, optFns ...MapOptFunc) (map[string]string, error) -func MustToSMap(st any, optFns ...MapOptFunc) map[string]string func ToString(st any, optFns ...MapOptFunc) string -func WithMapTagName(tagName string) MapOptFunc -func MergeAnonymous(opt *MapOptions) -func ExportPrivate(opt *MapOptions) func StructToMap(st any, optFns ...MapOptFunc) (map[string]any, error) -// source at structs/copy.go -func MapStruct(srcSt, dstSt any) // source at structs/data.go -func NewLiteData(data map[string]any) *Data func NewData() *Data func NewOrderedMap(len int) *OrderedMap -// source at structs/init.go -func Init(ptr any, optFns ...InitOptFunc) error +// source at structs/setval.go func InitDefaults(ptr any, optFns ...InitOptFunc) error +func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error // source at structs/structs.go -func IsExported(name string) bool -func IsUnexported(name string) bool +func MapStruct(srcSt, dstSt any) +func IsExported(fieldName string) bool +func IsUnexported(fieldName string) bool // source at structs/tags.go func ParseTags(st any, tagNames []string) (map[string]maputil.SMap, error) func ParseReflectTags(rt reflect.Type, tagNames []string) (map[string]maputil.SMap, error) @@ -1071,14 +1022,6 @@ func ParseTagValueDefine(sep string, defines []string) TagValFunc func ParseTagValueNamed(field, tagVal string, keys ...string) (mp maputil.SMap, err error) // source at structs/value.go func NewValue(val any) *Value -// source at structs/wrapper.go -func Wrap(src any) *Wrapper -func NewWrapper(src any) *Wrapper -func WrapValue(rv reflect.Value) *Wrapper -// source at structs/writer.go -func NewWriter(ptr any) *Wrapper -func WithParseDefault(opt *SetOptions) -func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error ``` ### Strings @@ -1110,7 +1053,6 @@ func HasPrefix(s string, prefix string) bool func IsStartOf(s, prefix string) bool func HasSuffix(s string, suffix string) bool func IsEndOf(s, suffix string) bool -func HasOneSuffix(s string, suffixes []string) bool func IsValidUtf8(s string) bool func IsSpace(c byte) bool func IsEmpty(s string) bool @@ -1123,12 +1065,8 @@ func IsAllEmpty(ss ...string) bool func IsVersion(s string) bool func Compare(s1, s2, op string) bool func VersionCompare(v1, v2, op string) bool -func SimpleMatch(s string, keywords []string) bool func QuickMatch(pattern, s string) bool -func PathMatch(pattern, s string) bool func GlobMatch(pattern, s string) bool -func LikeMatch(pattern, s string) bool -func MatchNodePath(pattern, s string, sep string) bool // source at strutil/convert.go func Quote(s string) string func Unquote(s string) string @@ -1170,6 +1108,8 @@ func Strings(s string, sep ...string) []string func ToStrings(s string, sep ...string) []string func ToSlice(s string, sep ...string) []string func ToOSArgs(s string) []string +func MustToTime(s string, layouts ...string) time.Time +func ToTime(s string, layouts ...string) (t time.Time, err error) func ToDuration(s string) (time.Duration, error) // source at strutil/crypto.go func Md5(src any) string @@ -1204,7 +1144,6 @@ func Rtrim(s string, cutSet ...string) string func RTrim(s string, cutSet ...string) string func TrimRight(s string, cutSet ...string) string func FilterEmail(s string) string -func Filter(ss []string, fls ...comdef.StringMatchFunc) []string // source at strutil/format.go func Title(s string) string func Lower(s string) string @@ -1222,7 +1161,6 @@ func IndentBytes(b, prefix []byte) []byte // source at strutil/id.go func MicroTimeID() string func MicroTimeHexID() string -func DatetimeNo(prefix string) string // source at strutil/padding.go func Padding(s, pad string, length int, pos PosFlag) string func PadLeft(s, pad string, length int) string @@ -1239,19 +1177,12 @@ func Repeat(s string, times int) string func RepeatRune(char rune, times int) []rune func RepeatBytes(char byte, times int) []byte func RepeatChars[T byte | rune](char T, times int) []T -// source at strutil/parse.go -func MustToTime(s string, layouts ...string) time.Time -func ToTime(s string, layouts ...string) (t time.Time, err error) -func ParseSizeRange(expr string, opt *ParseSizeOpt) (min, max uint64, err error) -func SafeByteSize(sizeStr string) uint64 -func ToByteSize(sizeStr string) (uint64, error) // source at strutil/random.go func RandomChars(ln int) string func RandomCharsV2(ln int) string func RandomCharsV3(ln int) string func RandomBytes(length int) ([]byte, error) func RandomString(length int) (string, error) -func RandWithTpl(n int, letters string) string // source at strutil/runes.go func RuneIsWord(c rune) bool func RuneIsLower(c rune) bool @@ -1265,7 +1196,6 @@ func RuneWidth(r rune) int func TextWidth(s string) int func Utf8Width(s string) int func RunesWidth(rs []rune) (w int) -func Truncate(s string, w int, tail string) string func TextTruncate(s string, w int, tail string) string func Utf8Truncate(s string, w int, tail string) string func TextSplit(s string, w int) []string @@ -1340,21 +1270,20 @@ func OsGoInfo() (*GoInfo, error) // source at sysutil/sysutil.go func Workdir() string func BinDir() string -func BinName() string func BinFile() string -func Open(fileOrURL string) error -func OpenBrowser(fileOrURL string) error +func Open(fileOrUrl string) error +func OpenBrowser(fileOrUrl string) error func OpenFile(path string) error -// source at sysutil/sysutil_nonwin.go -func Kill(pid int, signal syscall.Signal) error -func ProcessExists(pid int) bool -// source at sysutil/sysutil_unix.go +// source at sysutil/sysutil_linux.go func IsWin() bool func IsWindows() bool func IsMac() bool func IsDarwin() bool func IsLinux() bool func OpenURL(URL string) error +// source at sysutil/sysutil_nonwin.go +func Kill(pid int, signal syscall.Signal) error +func ProcessExists(pid int) bool // source at sysutil/user.go func MustFindUser(uname string) *user.User func LoginUser() *user.User @@ -1366,10 +1295,9 @@ func UserDir(subPath string) string func UserCacheDir(subPath string) string func UserConfigDir(subPath string) string func ExpandPath(path string) string -func ExpandHome(path string) string // source at sysutil/user_nonwin.go func ChangeUserByName(newUname string) (err error) -func ChangeUserUidGid(newUID int, newGid int) (err error) +func ChangeUserUidGid(newUid int, newGid int) (err error) ``` ### Testing Utils @@ -1378,7 +1306,7 @@ func ChangeUserUidGid(newUID int, newGid int) (err error) ```go // source at testutil/buffer.go -func NewBuffer() *byteutil.Buffer +func NewBuffer() *Buffer // source at testutil/envmock.go func MockEnvValue(key, val string, fn func(nv string)) func MockEnvValues(kvMap map[string]string, fn func()) @@ -1387,16 +1315,9 @@ func MockOsEnv(mp map[string]string, fn func()) func ClearOSEnv() func RevertOSEnv() func MockCleanOsEnv(mp map[string]string, fn func()) -// source at testutil/fsmock.go -func NewDirEnt(fpath string, isDir ...bool) *fakeobj.DirEntry // source at testutil/httpmock.go func NewHttpRequest(method, path string, data *MD) *http.Request func MockRequest(h http.Handler, method, path string, data *MD) *httptest.ResponseRecorder -func TestMain(m *testing.M) -func NewEchoServer() *httptest.Server -func BuildEchoReply(r *http.Request) *EchoReply -func ParseRespToReply(w *http.Response) *EchoReply -func ParseBodyToReply(bd io.ReadCloser) *EchoReply // source at testutil/testutil.go func DiscardStdout() error func ReadOutput() (s string) @@ -1414,26 +1335,6 @@ func NewTestWriter() *TestWriter Provides an enhanced time.Time implementation, and add more commonly used functional methods. ```go -// source at timex/gotime.go -func SetLocalByName(tzName string) error -func NowAddDay(day int) time.Time -func NowAddHour(hour int) time.Time -func NowAddMinutes(minutes int) time.Time -func NowAddSec(seconds int) time.Time -func NowAddSeconds(seconds int) time.Time -func NowHourStart() time.Time -func NowHourEnd() time.Time -func AddDay(t time.Time, day int) time.Time -func AddHour(t time.Time, hour int) time.Time -func AddMinutes(t time.Time, minutes int) time.Time -func AddSeconds(t time.Time, seconds int) time.Time -func AddSec(t time.Time, seconds int) time.Time -func HourStart(t time.Time) time.Time -func HourEnd(t time.Time) time.Time -func DayStart(t time.Time) time.Time -func DayEnd(t time.Time) time.Time -func TodayStart() time.Time -func TodayEnd() time.Time // source at timex/template.go func ToLayout(template string) string // source at timex/timex.go @@ -1448,23 +1349,33 @@ func FromString(s string, layouts ...string) (*Time, error) func LocalByName(tzName string) *Time // source at timex/util.go func NowUnix() int64 +func SetLocalByName(tzName string) error func Format(t time.Time) string func FormatBy(t time.Time, layout string) string -func Date(t time.Time, template ...string) string -func Datetime(t time.Time, template ...string) string +func Date(t time.Time, template string) string func DateFormat(t time.Time, template string) string func FormatByTpl(t time.Time, template string) string -func FormatUnix(sec int64, layout ...string) string +func FormatUnix(sec int64) string func FormatUnixBy(sec int64, layout string) string -func FormatUnixByTpl(sec int64, template ...string) string +func FormatUnixByTpl(sec int64, template string) string +func NowAddDay(day int) time.Time +func NowAddHour(hour int) time.Time +func NowAddMinutes(minutes int) time.Time +func NowAddSeconds(seconds int) time.Time +func NowHourStart() time.Time +func NowHourEnd() time.Time +func AddDay(t time.Time, day int) time.Time +func AddHour(t time.Time, hour int) time.Time +func AddMinutes(t time.Time, minutes int) time.Time +func AddSeconds(t time.Time, seconds int) time.Time +func HourStart(t time.Time) time.Time +func HourEnd(t time.Time) time.Time +func DayStart(t time.Time) time.Time +func DayEnd(t time.Time) time.Time +func TodayStart() time.Time +func TodayEnd() time.Time func HowLongAgo(sec int64) string -func ToTime(s string, layouts ...string) (time.Time, error) -func ToDur(s string) (time.Duration, error) func ToDuration(s string) (time.Duration, error) -func IsDuration(s string) bool -func TryToTime(s string, bt time.Time) (time.Time, error) -func InRange(dst, start, end time.Time) bool -func ParseRange(expr string, opt *ParseRangeOpt) (start, end time.Time, err error) ``` #### Timex Usage diff --git a/vendor/github.com/gookit/goutil/README.zh-CN.md b/vendor/github.com/gookit/goutil/README.zh-CN.md index 49a46c6..0c19e05 100644 --- a/vendor/github.com/gookit/goutil/README.zh-CN.md +++ b/vendor/github.com/gookit/goutil/README.zh-CN.md @@ -7,7 +7,7 @@ [![Coverage Status](https://coveralls.io/repos/github/gookit/goutil/badge.svg?branch=master)](https://coveralls.io/github/gookit/goutil?branch=master) [![Go Reference](https://pkg.go.dev/badge/github.com/gookit/goutil.svg)](https://pkg.go.dev/github.com/gookit/goutil) -`goutil` Go 常用功能的扩展工具库(**600+**)。包含:数字,byte, 字符串,slice/数组,Map,结构体,反射,文本,文件,错误,时间日期,测试,特殊处理,格式化,常用信息获取等等。 +`goutil` Go 常用功能的扩展工具库(**500+**)。包含:数字,byte, 字符串,slice/数组,Map,结构体,反射,文本,文件,错误,时间日期,测试,特殊处理,格式化,常用信息获取等等。 > **[EN README](README.md)** @@ -33,19 +33,16 @@ - [`cflag`](./cflag): 包装和扩展 go `flag.FlagSet` 以方便快速的构建简单的命令行应用程序 - [`dump`](./dump) GO变量打印工具,打印 slice, map 会自动换行显示每个元素,同时会显示打印调用位置 - [`errorx`](./errorx) 为 go 提供增强的错误实现,允许带有堆栈跟踪信息和包装另一个错误。 -- [`finder`](./fsutil/finder) 提供简单方便的file/dir查找功能,支持过滤、排除、匹配、忽略等。 -- netutil: +- strutil: - `netutil/httpreq` 包装 http.Client 实现的更加易于使用的HTTP客户端 - strutil: - [textscan](strutil/textscan) 实现了一个快速扫描和分析文本内容的解析器. 可用于解析 INI, Properties 等格式内容 - - [textutil](strutil/textutil) 提供一些常用的扩展文本处理功能函数。 - sysutil: - [clipboard](sysutil/clipboard) 提供简单的剪贴板读写操作工具库 - [cmdr](sysutil/cmdr) 提供快速构建和运行一个cmd,批量运行多个cmd任务 - - [process](sysutil/process) 提供一些进程操作相关的实用功能。 + - [process](./sysutil/process) 提供一些进程操作相关的实用功能。 - [`testutil`](testutil) test help 相关操作的函数工具包. eg: http test, mock ENV value - - [assert](testutil/assert) 用于帮助测试的断言函数工具包,方便编写单元测试。 - - [fakeobj](testutil/fakeobj) 提供一些接口的假的实现,用于模拟测试. 例如 fs.File, fs.FileInfo, fs.DirEntry 等等. + - [assert](testutil/assert) 用于帮助测试的断言函数工具包 - [`timex`](timex) 提供增强的 time.Time 实现。添加更多常用的功能方法 - 提供类似 `Y-m-d H:i:s` 的日期时间格式解析处理 - 例如: DayStart(), DayAfter(), DayAgo(), DateFormat() 等等 @@ -137,9 +134,8 @@ func SliceToInt64s(arr []any) []int64 func StringsAsInts(ss []string) []int func StringsToInts(ss []string) (ints []int, err error) func StringsTryInts(ss []string) (ints []int, err error) -func AnyToSlice(sl any) (ls []any, err error) -func AnyToStrings(arr any) []string func MustToStrings(arr any) []string +func AnyToStrings(arr any) []string func StringsToSlice(ss []string) []any func ToStrings(arr any) (ret []string, err error) func SliceToStrings(arr []any) []string @@ -148,7 +144,6 @@ func ConvType[T any, R any](arr []T, newElemTyp R) ([]R, error) func AnyToString(arr any) string func SliceToString(arr ...any) string func ToString(arr []any) string -func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V func CombineToSMap(keys, values []string) map[string]string // source at arrutil/format.go func NewFormatter(arr any) *ArrFormatter @@ -176,6 +171,24 @@ ss, err := arrutil.ToStrings([]int{1, 2}) // ss: []string{"1", "2"} ``` +### Basefn + +> Package `github.com/gookit/goutil/basefn` + +```go +// source at basefn/basefunc.go +func Panicf(format string, v ...any) +func MustOK(err error) +func Must[T any](v T, err error) T +func ErrOnFail(cond bool, err error) error +func OrError(cond bool, err error) error +func FirstOr[T any](sl []T, elseVal T) T +func OrValue[T any](cond bool, okVal, elVal T) T +func OrReturn[T any](cond bool, okFn, elseFn func() T) T +func CallOn(cond bool, fn ErrFunc) error +func CallOrElse(cond bool, okFn, elseFn ErrFunc) error +``` + ### Bytes Utils > Package `github.com/gookit/goutil/byteutil` @@ -184,14 +197,9 @@ ss, err := arrutil.ToStrings([]int{1, 2}) // ss: []string{"1", "2"} // source at byteutil/buffer.go func NewBuffer() *Buffer // source at byteutil/byteutil.go -func Random(length int) ([]byte, error) func FirstLine(bs []byte) []byte func StrOrErr(bs []byte, err error) (string, error) func SafeString(bs []byte, err error) string -func String(b []byte) string -func ToString(b []byte) string -func AppendAny(dst []byte, v any) []byte -func Cut(bs []byte, sep byte) (before, after []byte, found bool) // source at byteutil/bytex.go func Md5(src any) []byte // source at byteutil/check.go @@ -305,9 +313,7 @@ func ReadLine(question string) (string, error) func ReadFirst(question string) (string, error) func ReadFirstByte(question string) (byte, error) func ReadFirstRune(question string) (rune, error) -func ReadAsBool(tip string, defVal bool) bool func ReadPassword(question ...string) string -func Confirm(tip string, defVal ...bool) bool func InputIsYes(ans string) bool func ByteIsYes(ans byte) bool ``` @@ -541,10 +547,7 @@ func Config(fns ...func(opt *ErrStackOpt)) func SkipDepth(skipDepth int) func(opt *ErrStackOpt) func TraceDepth(traceDepth int) func(opt *ErrStackOpt) // source at errorx/util.go -func Err(msg string) error func Raw(msg string) error -func Ef(tpl string, vars ...any) error -func Errf(tpl string, vars ...any) error func Rawf(tpl string, vars ...any) error func Cause(err error) error func Unwrap(err error) error @@ -637,8 +640,6 @@ runtime.goexit() > Package `github.com/gookit/goutil/fmtutil` ```go -// source at fmtutil/fmtutil.go -func StringOrJSON(v any) ([]byte, error) // source at fmtutil/format.go func DataSize(size uint64) string func SizeToString(size uint64) string @@ -646,7 +647,7 @@ func StringToByte(sizeStr string) uint64 func ParseByte(sizeStr string) uint64 func PrettyJSON(v any) (string, error) func StringsToInts(ss []string) (ints []int, err error) -func ArgsWithSpaces(vs []any) (message string) +func ArgsWithSpaces(args []any) (message string) // source at fmtutil/time.go func HowLongAgo(sec int64) string ``` @@ -664,21 +665,6 @@ func IsFile(path string) bool func IsAbsPath(aPath string) bool func IsImageFile(path string) bool func IsZipFile(filepath string) bool -func PathMatch(pattern, s string) bool -// source at fsutil/find.go -func SearchNameUp(dirPath, name string) string -func SearchNameUpx(dirPath, name string) (string, bool) -func WalkDir(dir string, fn fs.WalkDirFunc) error -func Glob(pattern string, fls ...comdef.StringMatchFunc) []string -func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) -func OnlyFindDir(_ string, ent fs.DirEntry) bool -func OnlyFindFile(_ string, ent fs.DirEntry) bool -func ExcludeNames(names ...string) FilterFunc -func IncludeSuffix(ss ...string) FilterFunc -func ExcludeDotFile(_ string, ent fs.DirEntry) bool -func ExcludeSuffix(ss ...string) FilterFunc -func ApplyFilters(fPath string, ent fs.DirEntry, filters []FilterFunc) bool -func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) // source at fsutil/fsutil.go func OSTempFile(pattern string) (*os.File, error) func TempFile(dir, pattern string) (*os.File, error) @@ -687,10 +673,8 @@ func TempDir(dir, pattern string) (string, error) func MimeType(path string) (mime string) func ReaderMimeType(r io.Reader) (mime string) func JoinPaths(elem ...string) string -func JoinSubPaths(basePath string, elem ...string) string func SlashPath(path string) string func UnixPath(path string) string -func ToAbsPath(p string) string // source at fsutil/info.go func Dir(fpath string) string func PathName(fpath string) string @@ -700,8 +684,9 @@ func Extname(fpath string) string func Suffix(fpath string) string func Expand(pathStr string) string func ExpandPath(pathStr string) string -func ResolvePath(pathStr string) string func SplitPath(pathStr string) (dir, name string) +func GlobWithFunc(pattern string, fn func(filePath string) error) (err error) +func FindInDir(dir string, handleFn HandleFunc, filters ...FilterFunc) (e error) // source at fsutil/info_nonwin.go func Realpath(pathStr string) string // source at fsutil/operate.go @@ -710,10 +695,9 @@ func MkDirs(perm os.FileMode, dirPaths ...string) error func MkSubDirs(perm os.FileMode, parentDir string, subDirs ...string) error func MkParentDir(fpath string) error func OpenFile(filepath string, flag int, perm os.FileMode) (*os.File, error) -func MustOpenFile(filepath string, flag int, perm os.FileMode) *os.File func QuickOpenFile(filepath string, fileFlag ...int) (*os.File, error) -func OpenAppendFile(filepath string, filePerm ...os.FileMode) (*os.File, error) -func OpenTruncFile(filepath string, filePerm ...os.FileMode) (*os.File, error) +func OpenAppendFile(filepath string) (*os.File, error) +func OpenTruncFile(filepath string) (*os.File, error) func OpenReadFile(filepath string) (*os.File, error) func CreateFile(fpath string, filePerm, dirPerm os.FileMode, fileFlag ...int) (*os.File, error) func MustCreateFile(filePath string, filePerm, dirPerm os.FileMode) *os.File @@ -724,7 +708,6 @@ func RmIfExist(fPath string) error func DeleteIfExist(fPath string) error func RmFileIfExist(fPath string) error func DeleteIfFileExist(fPath string) error -func RemoveSub(dirPath string, fns ...FilterFunc) error func Unzip(archive, targetDir string) (err error) // source at fsutil/opread.go func NewIOReader(in any) (r io.Reader, err error) @@ -734,10 +717,8 @@ func MustReadFile(filePath string) []byte func ReadReader(r io.Reader) []byte func MustReadReader(r io.Reader) []byte func ReadString(in any) string -func ReadStringOrErr(in any) (string, error) func ReadAll(in any) []byte func GetContents(in any) []byte -func ReadOrErr(in any) ([]byte, error) func ReadExistFile(filePath string) []byte func TextScanner(in any) *scanner.Scanner func LineScanner(in any) *bufio.Scanner @@ -758,23 +739,30 @@ package main import ( "fmt" - "io/fs" + "os" - "github.com/gookit/goutil/fsutil" + "github.com/gookit/goutil/fsutil/finder" ) func main() { - // find all files in dir - fsutil.FindInDir("./", func(filePath string, de fs.DirEntry) error { - fmt.Println(filePath) - return nil - }) - - // find files with filters - fsutil.FindInDir("./", func(filePath string, de fs.DirEntry) error { - fmt.Println(filePath) - return nil - }, fsutil.ExcludeDotFile) + f := finder.EmptyFinder() + + f. + AddDir("./testdata"). + AddFile("finder.go"). + NoDotFile(). + // NoDotDir(). + Find(). + Each(func(filePath string) { + fmt.Println(filePath) + }) + + finder.NewFinder([]string{"./testdata"}). + AddFile("finder.go"). + NoDotDir(). + EachStat(func(fi os.FileInfo, filePath string) { + fmt.Println(filePath, "=>", fi.ModTime()) + }) } ``` @@ -786,7 +774,6 @@ func main() { ```go // source at jsonutil/jsonutil.go func WriteFile(filePath string, data any) error -func WritePretty(filePath string, data any) error func ReadFile(filePath string, v any) error func Pretty(v any) (string, error) func Encode(v any) ([]byte, error) @@ -797,8 +784,6 @@ func Decode(bts []byte, ptr any) error func DecodeString(str string, ptr any) error func DecodeReader(r io.Reader, ptr any) error func Mapping(src, dst any) error -func IsJSON(s string) bool -func IsJSONFast(s string) bool func StripComments(src string) string ``` @@ -809,17 +794,12 @@ func StripComments(src string) string ```go // source at maputil/check.go func HasKey(mp, key any) (ok bool) -func HasOneKey(mp any, keys ...any) (ok bool, key any) func HasAllKeys(mp any, keys ...any) (ok bool, noKey any) // source at maputil/convert.go func KeyToLower(src map[string]string) map[string]string func ToStringMap(src map[string]any) map[string]string func CombineToSMap(keys, values []string) SMap -func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V -func ToAnyMap(mp any) map[string]any -func TryAnyMap(mp any) (map[string]any, error) func HTTPQueryString(data map[string]any) string -func StringsMapToAnyMap(ssMp map[string][]string) map[string]any func ToString(mp map[string]any) string func ToString2(mp any) string func FormatIndent(mp any, indent string) string @@ -831,10 +811,8 @@ func NewFormatter(mp any) *MapFormatter func DeepGet(mp map[string]any, path string) (val any) func QuietGet(mp map[string]any, path string) (val any) func GetByPath(path string, mp map[string]any) (val any, ok bool) -func GetByPathKeys(mp map[string]any, keys []string) (val any, ok bool) func Keys(mp any) (keys []string) func Values(mp any) (values []any) -func EachAnyMap(mp any, fn func(key string, val any)) // source at maputil/maputil.go func SimpleMerge(src, dst map[string]any) map[string]any func DeepMerge(src, dst map[string]any, deep int) map[string]any @@ -854,13 +832,8 @@ func SetByKeys(mp *map[string]any, keys []string, val any) (err error) ```go // source at mathutil/check.go func Compare(srcVal, dstVal any, op string) (ok bool) -func CompInt[T comdef.Xint](srcVal, dstVal T, op string) (ok bool) -func CompInt64(srcVal, dstVal int64, op string) bool -func CompFloat[T comdef.Float](srcVal, dstVal T, op string) (ok bool) -func CompValue[T comdef.XintOrFloat](srcVal, dstVal T, op string) (ok bool) -func InRange[T comdef.IntOrFloat](val, min, max T) bool -func OutRange[T comdef.IntOrFloat](val, min, max T) bool -func InUintRange[T comdef.Uint](val, min, max T) bool +func CompInt64(srcI64, dstI64 int64, op string) (ok bool) +func CompFloat(srcF64, dstF64 float64, op string) (ok bool) // source at mathutil/convert.go func Int(in any) (int, error) func QuietInt(in any) int @@ -894,9 +867,7 @@ func QuietString(val any) string func String(val any) string func TryToString(val any, defaultAsErr bool) (str string, err error) // source at mathutil/mathutil.go -func Min[T comdef.XintOrFloat](x, y T) T func Max[T comdef.XintOrFloat](x, y T) T -func SwapMin[T comdef.XintOrFloat](x, y T) (T, T) func SwapMax[T comdef.XintOrFloat](x, y T) (T, T) func MaxInt(x, y int) int func SwapMaxInt(x, y int) (int, int) @@ -925,10 +896,6 @@ func RandomIntWithSeed(min, max int, seed int64) int // source at reflects/check.go func HasChild(v reflect.Value) bool func IsArrayOrSlice(k reflect.Kind) bool -func IsSimpleKind(k reflect.Kind) bool -func IsAnyInt(k reflect.Kind) bool -func IsIntx(k reflect.Kind) bool -func IsUintX(k reflect.Kind) bool func IsNil(v reflect.Value) bool func IsFunc(val any) bool func IsEqual(src, dst any) bool @@ -951,13 +918,7 @@ func Elem(v reflect.Value) reflect.Value func Indirect(v reflect.Value) reflect.Value func Len(v reflect.Value) int func SliceSubKind(typ reflect.Type) reflect.Kind -func SliceElemKind(typ reflect.Type) reflect.Kind -func UnexportedValue(rv reflect.Value) any -func SetUnexportedValue(rv reflect.Value, value any) func SetValue(rv reflect.Value, val any) error -func SetRValue(rv, val reflect.Value) -func EachMap(mp reflect.Value, fn func(key, val reflect.Value)) -func EachStrAnyMap(mp reflect.Value, fn func(key string, val any)) func FlatMap(rv reflect.Value, fn FlatFunc) // source at reflects/value.go func Wrap(rv reflect.Value) Value @@ -970,9 +931,9 @@ func ValueOf(v any) Value ```go // source at stdio/ioutil.go -func QuietFprint(w io.Writer, a ...any) +func QuietFprint(w io.Writer, ss ...string) func QuietFprintf(w io.Writer, tpl string, vs ...any) -func QuietFprintln(w io.Writer, a ...any) +func QuietFprintln(w io.Writer, ss ...string) func QuietWriteString(w io.Writer, ss ...string) // source at stdio/stdio.go func DiscardReader(src io.Reader) @@ -980,9 +941,7 @@ func ReadString(r io.Reader) string func MustReadReader(r io.Reader) []byte func NewIOReader(in any) io.Reader func NewScanner(in any) *bufio.Scanner -func WriteByte(b byte) func WriteBytes(bs []byte) -func WritelnBytes(bs []byte) func WriteString(s string) func Writeln(s string) // source at stdio/writer.go @@ -1042,26 +1001,18 @@ func NewAliases(checker func(alias string)) *Aliases func ToMap(st any, optFns ...MapOptFunc) map[string]any func MustToMap(st any, optFns ...MapOptFunc) map[string]any func TryToMap(st any, optFns ...MapOptFunc) (map[string]any, error) -func ToSMap(st any, optFns ...MapOptFunc) map[string]string -func TryToSMap(st any, optFns ...MapOptFunc) (map[string]string, error) -func MustToSMap(st any, optFns ...MapOptFunc) map[string]string func ToString(st any, optFns ...MapOptFunc) string -func WithMapTagName(tagName string) MapOptFunc -func MergeAnonymous(opt *MapOptions) -func ExportPrivate(opt *MapOptions) func StructToMap(st any, optFns ...MapOptFunc) (map[string]any, error) -// source at structs/copy.go -func MapStruct(srcSt, dstSt any) // source at structs/data.go -func NewLiteData(data map[string]any) *Data func NewData() *Data func NewOrderedMap(len int) *OrderedMap -// source at structs/init.go -func Init(ptr any, optFns ...InitOptFunc) error +// source at structs/setval.go func InitDefaults(ptr any, optFns ...InitOptFunc) error +func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error // source at structs/structs.go -func IsExported(name string) bool -func IsUnexported(name string) bool +func MapStruct(srcSt, dstSt any) +func IsExported(fieldName string) bool +func IsUnexported(fieldName string) bool // source at structs/tags.go func ParseTags(st any, tagNames []string) (map[string]maputil.SMap, error) func ParseReflectTags(rt reflect.Type, tagNames []string) (map[string]maputil.SMap, error) @@ -1072,14 +1023,6 @@ func ParseTagValueDefine(sep string, defines []string) TagValFunc func ParseTagValueNamed(field, tagVal string, keys ...string) (mp maputil.SMap, err error) // source at structs/value.go func NewValue(val any) *Value -// source at structs/wrapper.go -func Wrap(src any) *Wrapper -func NewWrapper(src any) *Wrapper -func WrapValue(rv reflect.Value) *Wrapper -// source at structs/writer.go -func NewWriter(ptr any) *Wrapper -func WithParseDefault(opt *SetOptions) -func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error ``` ### Strings @@ -1111,7 +1054,6 @@ func HasPrefix(s string, prefix string) bool func IsStartOf(s, prefix string) bool func HasSuffix(s string, suffix string) bool func IsEndOf(s, suffix string) bool -func HasOneSuffix(s string, suffixes []string) bool func IsValidUtf8(s string) bool func IsSpace(c byte) bool func IsEmpty(s string) bool @@ -1124,12 +1066,8 @@ func IsAllEmpty(ss ...string) bool func IsVersion(s string) bool func Compare(s1, s2, op string) bool func VersionCompare(v1, v2, op string) bool -func SimpleMatch(s string, keywords []string) bool func QuickMatch(pattern, s string) bool -func PathMatch(pattern, s string) bool func GlobMatch(pattern, s string) bool -func LikeMatch(pattern, s string) bool -func MatchNodePath(pattern, s string, sep string) bool // source at strutil/convert.go func Quote(s string) string func Unquote(s string) string @@ -1171,6 +1109,8 @@ func Strings(s string, sep ...string) []string func ToStrings(s string, sep ...string) []string func ToSlice(s string, sep ...string) []string func ToOSArgs(s string) []string +func MustToTime(s string, layouts ...string) time.Time +func ToTime(s string, layouts ...string) (t time.Time, err error) func ToDuration(s string) (time.Duration, error) // source at strutil/crypto.go func Md5(src any) string @@ -1205,7 +1145,6 @@ func Rtrim(s string, cutSet ...string) string func RTrim(s string, cutSet ...string) string func TrimRight(s string, cutSet ...string) string func FilterEmail(s string) string -func Filter(ss []string, fls ...comdef.StringMatchFunc) []string // source at strutil/format.go func Title(s string) string func Lower(s string) string @@ -1223,7 +1162,6 @@ func IndentBytes(b, prefix []byte) []byte // source at strutil/id.go func MicroTimeID() string func MicroTimeHexID() string -func DatetimeNo(prefix string) string // source at strutil/padding.go func Padding(s, pad string, length int, pos PosFlag) string func PadLeft(s, pad string, length int) string @@ -1240,19 +1178,12 @@ func Repeat(s string, times int) string func RepeatRune(char rune, times int) []rune func RepeatBytes(char byte, times int) []byte func RepeatChars[T byte | rune](char T, times int) []T -// source at strutil/parse.go -func MustToTime(s string, layouts ...string) time.Time -func ToTime(s string, layouts ...string) (t time.Time, err error) -func ParseSizeRange(expr string, opt *ParseSizeOpt) (min, max uint64, err error) -func SafeByteSize(sizeStr string) uint64 -func ToByteSize(sizeStr string) (uint64, error) // source at strutil/random.go func RandomChars(ln int) string func RandomCharsV2(ln int) string func RandomCharsV3(ln int) string func RandomBytes(length int) ([]byte, error) func RandomString(length int) (string, error) -func RandWithTpl(n int, letters string) string // source at strutil/runes.go func RuneIsWord(c rune) bool func RuneIsLower(c rune) bool @@ -1266,7 +1197,6 @@ func RuneWidth(r rune) int func TextWidth(s string) int func Utf8Width(s string) int func RunesWidth(rs []rune) (w int) -func Truncate(s string, w int, tail string) string func TextTruncate(s string, w int, tail string) string func Utf8Truncate(s string, w int, tail string) string func TextSplit(s string, w int) []string @@ -1341,21 +1271,20 @@ func OsGoInfo() (*GoInfo, error) // source at sysutil/sysutil.go func Workdir() string func BinDir() string -func BinName() string func BinFile() string -func Open(fileOrURL string) error -func OpenBrowser(fileOrURL string) error +func Open(fileOrUrl string) error +func OpenBrowser(fileOrUrl string) error func OpenFile(path string) error -// source at sysutil/sysutil_nonwin.go -func Kill(pid int, signal syscall.Signal) error -func ProcessExists(pid int) bool -// source at sysutil/sysutil_unix.go +// source at sysutil/sysutil_linux.go func IsWin() bool func IsWindows() bool func IsMac() bool func IsDarwin() bool func IsLinux() bool func OpenURL(URL string) error +// source at sysutil/sysutil_nonwin.go +func Kill(pid int, signal syscall.Signal) error +func ProcessExists(pid int) bool // source at sysutil/user.go func MustFindUser(uname string) *user.User func LoginUser() *user.User @@ -1367,10 +1296,9 @@ func UserDir(subPath string) string func UserCacheDir(subPath string) string func UserConfigDir(subPath string) string func ExpandPath(path string) string -func ExpandHome(path string) string // source at sysutil/user_nonwin.go func ChangeUserByName(newUname string) (err error) -func ChangeUserUidGid(newUID int, newGid int) (err error) +func ChangeUserUidGid(newUid int, newGid int) (err error) ``` ### Testing Utils @@ -1379,7 +1307,7 @@ func ChangeUserUidGid(newUID int, newGid int) (err error) ```go // source at testutil/buffer.go -func NewBuffer() *byteutil.Buffer +func NewBuffer() *Buffer // source at testutil/envmock.go func MockEnvValue(key, val string, fn func(nv string)) func MockEnvValues(kvMap map[string]string, fn func()) @@ -1388,16 +1316,9 @@ func MockOsEnv(mp map[string]string, fn func()) func ClearOSEnv() func RevertOSEnv() func MockCleanOsEnv(mp map[string]string, fn func()) -// source at testutil/fsmock.go -func NewDirEnt(fpath string, isDir ...bool) *fakeobj.DirEntry // source at testutil/httpmock.go func NewHttpRequest(method, path string, data *MD) *http.Request func MockRequest(h http.Handler, method, path string, data *MD) *httptest.ResponseRecorder -func TestMain(m *testing.M) -func NewEchoServer() *httptest.Server -func BuildEchoReply(r *http.Request) *EchoReply -func ParseRespToReply(w *http.Response) *EchoReply -func ParseBodyToReply(bd io.ReadCloser) *EchoReply // source at testutil/testutil.go func DiscardStdout() error func ReadOutput() (s string) @@ -1415,26 +1336,6 @@ func NewTestWriter() *TestWriter Provides an enhanced time.Time implementation, and add more commonly used functional methods. ```go -// source at timex/gotime.go -func SetLocalByName(tzName string) error -func NowAddDay(day int) time.Time -func NowAddHour(hour int) time.Time -func NowAddMinutes(minutes int) time.Time -func NowAddSec(seconds int) time.Time -func NowAddSeconds(seconds int) time.Time -func NowHourStart() time.Time -func NowHourEnd() time.Time -func AddDay(t time.Time, day int) time.Time -func AddHour(t time.Time, hour int) time.Time -func AddMinutes(t time.Time, minutes int) time.Time -func AddSeconds(t time.Time, seconds int) time.Time -func AddSec(t time.Time, seconds int) time.Time -func HourStart(t time.Time) time.Time -func HourEnd(t time.Time) time.Time -func DayStart(t time.Time) time.Time -func DayEnd(t time.Time) time.Time -func TodayStart() time.Time -func TodayEnd() time.Time // source at timex/template.go func ToLayout(template string) string // source at timex/timex.go @@ -1449,23 +1350,33 @@ func FromString(s string, layouts ...string) (*Time, error) func LocalByName(tzName string) *Time // source at timex/util.go func NowUnix() int64 +func SetLocalByName(tzName string) error func Format(t time.Time) string func FormatBy(t time.Time, layout string) string -func Date(t time.Time, template ...string) string -func Datetime(t time.Time, template ...string) string +func Date(t time.Time, template string) string func DateFormat(t time.Time, template string) string func FormatByTpl(t time.Time, template string) string -func FormatUnix(sec int64, layout ...string) string +func FormatUnix(sec int64) string func FormatUnixBy(sec int64, layout string) string -func FormatUnixByTpl(sec int64, template ...string) string +func FormatUnixByTpl(sec int64, template string) string +func NowAddDay(day int) time.Time +func NowAddHour(hour int) time.Time +func NowAddMinutes(minutes int) time.Time +func NowAddSeconds(seconds int) time.Time +func NowHourStart() time.Time +func NowHourEnd() time.Time +func AddDay(t time.Time, day int) time.Time +func AddHour(t time.Time, hour int) time.Time +func AddMinutes(t time.Time, minutes int) time.Time +func AddSeconds(t time.Time, seconds int) time.Time +func HourStart(t time.Time) time.Time +func HourEnd(t time.Time) time.Time +func DayStart(t time.Time) time.Time +func DayEnd(t time.Time) time.Time +func TodayStart() time.Time +func TodayEnd() time.Time func HowLongAgo(sec int64) string -func ToTime(s string, layouts ...string) (time.Time, error) -func ToDur(s string) (time.Duration, error) func ToDuration(s string) (time.Duration, error) -func IsDuration(s string) bool -func TryToTime(s string, bt time.Time) (time.Time, error) -func InRange(dst, start, end time.Time) bool -func ParseRange(expr string, opt *ParseRangeOpt) (start, end time.Time, err error) ``` #### Timex Usage diff --git a/vendor/github.com/gookit/goutil/arrutil/README.md b/vendor/github.com/gookit/goutil/arrutil/README.md index 1a1467a..9f9351c 100644 --- a/vendor/github.com/gookit/goutil/arrutil/README.md +++ b/vendor/github.com/gookit/goutil/arrutil/README.md @@ -12,8 +12,6 @@ go get github.com/gookit/goutil/arrutil ## Functions API -> **Note**: doc by run `go doc ./arrutil` - ```go func AnyToString(arr any) string func CloneSlice(data any) interface{} diff --git a/vendor/github.com/gookit/goutil/arrutil/arrutil.go b/vendor/github.com/gookit/goutil/arrutil/arrutil.go index dff2656..275e317 100644 --- a/vendor/github.com/gookit/goutil/arrutil/arrutil.go +++ b/vendor/github.com/gookit/goutil/arrutil/arrutil.go @@ -105,10 +105,6 @@ func RandomOne[T any](arr []T) T { // Unique value in the given slice data. func Unique[T ~string | comdef.XintOrFloat](list []T) []T { - if len(list) < 2 { - return list - } - valMap := make(map[T]struct{}, len(list)) uniArr := make([]T, 0, len(list)) diff --git a/vendor/github.com/gookit/goutil/arrutil/collection_gte118.go b/vendor/github.com/gookit/goutil/arrutil/collection_gte118.go index fe406ca..f580c59 100644 --- a/vendor/github.com/gookit/goutil/arrutil/collection_gte118.go +++ b/vendor/github.com/gookit/goutil/arrutil/collection_gte118.go @@ -2,14 +2,12 @@ package arrutil // type MapFn func(obj T) (target V, find bool) -// Map a list to new list -// -// eg: mapping [object0{},object1{},...] to flatten list [object0.someKey, object1.someKey, ...] +// Map an object list [object0{},object1{},...] to flatten list [object0.someKey, object1.someKey, ...] func Map[T any, V any](list []T, mapFn func(obj T) (val V, find bool)) []V { flatArr := make([]V, 0, len(list)) for _, obj := range list { - if target, ok := mapFn(obj); ok { + if target, find := mapFn(obj); find { flatArr = append(flatArr, target) } } diff --git a/vendor/github.com/gookit/goutil/arrutil/convert.go b/vendor/github.com/gookit/goutil/arrutil/convert.go index 34dbb3c..b2cc8d9 100644 --- a/vendor/github.com/gookit/goutil/arrutil/convert.go +++ b/vendor/github.com/gookit/goutil/arrutil/convert.go @@ -6,7 +6,6 @@ import ( "strconv" "strings" - "github.com/gookit/goutil/comdef" "github.com/gookit/goutil/mathutil" "github.com/gookit/goutil/reflects" "github.com/gookit/goutil/strutil" @@ -108,25 +107,6 @@ func StringsTryInts(ss []string) (ints []int, err error) { return } -// AnyToSlice convert any(allow: array,slice) to []any -func AnyToSlice(sl any) (ls []any, err error) { - rfKeys := reflect.ValueOf(sl) - if rfKeys.Kind() != reflect.Slice && rfKeys.Kind() != reflect.Array { - return nil, ErrInvalidType - } - - for i := 0; i < rfKeys.Len(); i++ { - ls = append(ls, rfKeys.Index(i).Interface()) - } - return -} - -// AnyToStrings convert array or slice to []string -func AnyToStrings(arr any) []string { - ret, _ := ToStrings(arr) - return ret -} - // MustToStrings convert array or slice to []string func MustToStrings(arr any) []string { ret, err := ToStrings(arr) @@ -136,6 +116,12 @@ func MustToStrings(arr any) []string { return ret } +// AnyToStrings convert array or slice to []string +func AnyToStrings(arr any) []string { + ret, _ := ToStrings(arr) + return ret +} + // StringsToSlice convert []string to []any func StringsToSlice(ss []string) []any { args := make([]any, len(ss)) @@ -240,22 +226,6 @@ func ToString(arr []any) string { return sb.String() } -// CombineToMap combine two slice to map[K]V. -// -// If keys length is greater than values, the extra keys will be ignored. -func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V { - ln := len(values) - mp := make(map[K]V, len(keys)) - - for i, key := range keys { - if i >= ln { - break - } - mp[key] = values[i] - } - return mp -} - // CombineToSMap combine two string-slice to map[string]string func CombineToSMap(keys, values []string) map[string]string { ln := len(values) diff --git a/vendor/github.com/gookit/goutil/basefn/basefunc.go b/vendor/github.com/gookit/goutil/basefn/basefunc.go deleted file mode 100644 index decc318..0000000 --- a/vendor/github.com/gookit/goutil/basefn/basefunc.go +++ /dev/null @@ -1,80 +0,0 @@ -// Package basefn provide some no-dependents util functions -package basefn - -import "fmt" - -// Panicf format panic message use fmt.Sprintf -func Panicf(format string, v ...any) { - panic(fmt.Sprintf(format, v...)) -} - -// MustOK if error is not empty, will panic -func MustOK(err error) { - if err != nil { - panic(err) - } -} - -// Must if error is not empty, will panic -func Must[T any](v T, err error) T { - if err != nil { - panic(err) - } - return v -} - -// ErrOnFail return input error on cond is false, otherwise return nil -func ErrOnFail(cond bool, err error) error { - return OrError(cond, err) -} - -// OrError return input error on cond is false, otherwise return nil -func OrError(cond bool, err error) error { - if !cond { - return err - } - return nil -} - -// FirstOr get first elem or elseVal -func FirstOr[T any](sl []T, elseVal T) T { - if len(sl) > 0 { - return sl[0] - } - return elseVal -} - -// OrValue get -func OrValue[T any](cond bool, okVal, elVal T) T { - if cond { - return okVal - } - return elVal -} - -// OrReturn call okFunc() on condition is true, else call elseFn() -func OrReturn[T any](cond bool, okFn, elseFn func() T) T { - if cond { - return okFn() - } - return elseFn() -} - -// ErrFunc type -type ErrFunc func() error - -// CallOn call func on condition is true -func CallOn(cond bool, fn ErrFunc) error { - if cond { - return fn() - } - return nil -} - -// CallOrElse call okFunc() on condition is true, else call elseFn() -func CallOrElse(cond bool, okFn, elseFn ErrFunc) error { - if cond { - return okFn() - } - return elseFn() -} diff --git a/vendor/github.com/gookit/goutil/basefn/extfunc.go b/vendor/github.com/gookit/goutil/basefn/extfunc.go deleted file mode 100644 index 15be452..0000000 --- a/vendor/github.com/gookit/goutil/basefn/extfunc.go +++ /dev/null @@ -1,74 +0,0 @@ -package basefn - -import ( - "fmt" -) - -// DataSize format bytes number friendly. eg: 1024 => 1KB, 1024*1024 => 1MB -// -// Usage: -// -// file, err := os.Open(path) -// fl, err := file.Stat() -// fmtSize := DataSize(fl.Size()) -func DataSize(size uint64) string { - switch { - case size < 1024: - return fmt.Sprintf("%dB", size) - case size < 1024*1024: - return fmt.Sprintf("%.2fK", float64(size)/1024) - case size < 1024*1024*1024: - return fmt.Sprintf("%.2fM", float64(size)/1024/1024) - default: - return fmt.Sprintf("%.2fG", float64(size)/1024/1024/1024) - } -} - -var timeFormats = [][]int{ - {0}, - {1}, - {2, 1}, - {60}, - {120, 60}, - {3600}, - {7200, 3600}, - {86400}, - {172800, 86400}, -} - -var timeMessages = []string{ - "< 1 sec", "1 sec", "secs", "1 min", "mins", "1 hr", "hrs", "1 day", "days", -} - -// HowLongAgo format a seconds, get how lang ago -func HowLongAgo(sec int64) string { - intVal := int(sec) - length := len(timeFormats) - - for i, item := range timeFormats { - if intVal >= item[0] { - ni := i + 1 - match := false - - if ni < length { // next exists - next := timeFormats[ni] - if intVal < next[0] { // current <= intVal < next - match = true - } - } else if ni == length { // current is last - match = true - } - - if match { // match success - if len(item) == 1 { - return timeMessages[i] - } - - // len is 2 - return fmt.Sprintf("%d %s", intVal/item[1], timeMessages[i]) - } - } - } - - return "unknown" // He should never happen -} diff --git a/vendor/github.com/gookit/goutil/byteutil/README.md b/vendor/github.com/gookit/goutil/byteutil/README.md index 89147dc..dfd7581 100644 --- a/vendor/github.com/gookit/goutil/byteutil/README.md +++ b/vendor/github.com/gookit/goutil/byteutil/README.md @@ -14,18 +14,9 @@ go get github.com/gookit/goutil/byteutil ## Functions API -> **Note**: doc by run `go doc ./byteutil` - ```go -func AppendAny(dst []byte, v any) []byte -func FirstLine(bs []byte) []byte -func IsNumChar(c byte) bool +var HexEncoder = NewStdEncoder(func(src []byte) []byte { ... }, func(src []byte) ([]byte, error) { ... }) ... func Md5(src any) []byte -func Random(length int) ([]byte, error) -func SafeString(bs []byte, err error) string -func StrOrErr(bs []byte, err error) (string, error) -func String(b []byte) string -func ToString(b []byte) string type Buffer struct{ ... } func NewBuffer() *Buffer type BytesEncoder interface{ ... } diff --git a/vendor/github.com/gookit/goutil/byteutil/buffer.go b/vendor/github.com/gookit/goutil/byteutil/buffer.go index aa03183..c0a6917 100644 --- a/vendor/github.com/gookit/goutil/byteutil/buffer.go +++ b/vendor/github.com/gookit/goutil/byteutil/buffer.go @@ -3,14 +3,12 @@ package byteutil import ( "bytes" "fmt" + "strings" ) -// Buffer wrap and extends the bytes.Buffer, add some useful methods +// Buffer wrap and extends the bytes.Buffer type Buffer struct { bytes.Buffer - // custom error for testing - CloseErr error - FlushErr error } // NewBuffer instance @@ -18,87 +16,45 @@ func NewBuffer() *Buffer { return &Buffer{} } -// PrintByte to buffer, ignore error. alias of WriteByte() -func (b *Buffer) PrintByte(c byte) { - _ = b.WriteByte(c) -} - -// WriteStr1 quiet write one string to buffer -func (b *Buffer) WriteStr1(s string) { - b.writeStringNl(s, false) -} - -// WriteStr1Nl quiet write one string and end with newline -func (b *Buffer) WriteStr1Nl(s string) { - b.writeStringNl(s, true) -} - -// writeStringNl quiet write one string and end with newline -func (b *Buffer) writeStringNl(s string, nl bool) { - _, _ = b.Buffer.WriteString(s) - if nl { - _ = b.WriteByte('\n') +// WriteAny type value to buffer +func (b *Buffer) WriteAny(vs ...any) { + for _, v := range vs { + _, _ = b.Buffer.WriteString(fmt.Sprint(v)) } } -// WriteStr quiet write strings to buffer -func (b *Buffer) WriteStr(ss ...string) { - b.writeStringsNl(ss, false) -} - -// WriteStrings to buffer, ignore error. -func (b *Buffer) WriteStrings(ss []string) { - b.writeStringsNl(ss, false) -} - -// WriteStringNl write message to buffer and end with newline -func (b *Buffer) WriteStringNl(ss ...string) { - b.writeStringsNl(ss, true) +// QuietWriteByte to buffer +func (b *Buffer) QuietWriteByte(c byte) { + _ = b.WriteByte(c) } -// writeStringsNl to buffer, ignore error. -func (b *Buffer) writeStringsNl(ss []string, nl bool) { - for _, s := range ss { - _, _ = b.Buffer.WriteString(s) - } - if nl { - _ = b.WriteByte('\n') - } +// QuietWritef write message to buffer +func (b *Buffer) QuietWritef(tpl string, vs ...any) { + _, _ = b.WriteString(fmt.Sprintf(tpl, vs...)) } -// WriteAny type value to buffer -func (b *Buffer) WriteAny(vs ...any) { - b.writeAnysWithNl(vs, false) +// Writeln write message to buffer with newline +func (b *Buffer) Writeln(ss ...string) { + b.QuietWriteln(ss...) } -// Writeln write values to buffer and end with newline -func (b *Buffer) Writeln(vs ...any) { - b.writeAnysWithNl(vs, true) +// QuietWriteln write message to buffer with newline +func (b *Buffer) QuietWriteln(ss ...string) { + _, _ = b.WriteString(strings.Join(ss, "")) + _ = b.WriteByte('\n') } -// WriteAnyNl type value to buffer and end with newline -func (b *Buffer) WriteAnyNl(vs ...any) { - b.writeAnysWithNl(vs, true) +// QuietWriteString to buffer +func (b *Buffer) QuietWriteString(ss ...string) { + _, _ = b.WriteString(strings.Join(ss, "")) } -// WriteAnyLn type value to buffer and end with newline -func (b *Buffer) writeAnysWithNl(vs []any, nl bool) { - for _, v := range vs { - _, _ = b.Buffer.WriteString(fmt.Sprint(v)) +// MustWriteString to buffer +func (b *Buffer) MustWriteString(ss ...string) { + _, err := b.WriteString(strings.Join(ss, "")) + if err != nil { + panic(err) } - if nl { - _ = b.WriteByte('\n') - } -} - -// Printf quiet write message to buffer, ignore error. -func (b *Buffer) Printf(tpl string, vs ...any) { - _, _ = b.WriteString(fmt.Sprintf(tpl, vs...)) -} - -// ResetGet buffer string. alias of ResetAndGet() -func (b *Buffer) ResetGet() string { - return b.ResetAndGet() } // ResetAndGet buffer string. @@ -107,13 +63,3 @@ func (b *Buffer) ResetAndGet() string { b.Reset() return s } - -// Close buffer -func (b *Buffer) Close() error { - return b.CloseErr -} - -// Flush buffer -func (b *Buffer) Flush() error { - return b.FlushErr -} diff --git a/vendor/github.com/gookit/goutil/byteutil/byteutil.go b/vendor/github.com/gookit/goutil/byteutil/byteutil.go index 45c3945..8c1c6e1 100644 --- a/vendor/github.com/gookit/goutil/byteutil/byteutil.go +++ b/vendor/github.com/gookit/goutil/byteutil/byteutil.go @@ -2,23 +2,8 @@ package byteutil import ( "bytes" - "fmt" - "math/rand" - "strconv" - "time" - "unsafe" ) -// Random bytes generate -func Random(length int) ([]byte, error) { - b := make([]byte, length) - // Note that err == nil only if we read len(b) bytes. - if _, err := rand.Read(b); err != nil { - return nil, err - } - return b, nil -} - // FirstLine from command output func FirstLine(bs []byte) []byte { if i := bytes.IndexByte(bs, '\n'); i >= 0 { @@ -42,74 +27,3 @@ func SafeString(bs []byte, err error) string { } return string(bs) } - -// String unsafe convert bytes to string -func String(b []byte) string { - return *(*string)(unsafe.Pointer(&b)) -} - -// ToString convert bytes to string -func ToString(b []byte) string { - return *(*string)(unsafe.Pointer(&b)) -} - -// AppendAny append any value to byte slice -func AppendAny(dst []byte, v any) []byte { - if v == nil { - return append(dst, ""...) - } - - switch val := v.(type) { - case []byte: - dst = append(dst, val...) - case string: - dst = append(dst, val...) - case int: - dst = strconv.AppendInt(dst, int64(val), 10) - case int8: - dst = strconv.AppendInt(dst, int64(val), 10) - case int16: - dst = strconv.AppendInt(dst, int64(val), 10) - case int32: - dst = strconv.AppendInt(dst, int64(val), 10) - case int64: - dst = strconv.AppendInt(dst, val, 10) - case uint: - dst = strconv.AppendUint(dst, uint64(val), 10) - case uint8: - dst = strconv.AppendUint(dst, uint64(val), 10) - case uint16: - dst = strconv.AppendUint(dst, uint64(val), 10) - case uint32: - dst = strconv.AppendUint(dst, uint64(val), 10) - case uint64: - dst = strconv.AppendUint(dst, val, 10) - case float32: - dst = strconv.AppendFloat(dst, float64(val), 'f', -1, 32) - case float64: - dst = strconv.AppendFloat(dst, val, 'f', -1, 64) - case bool: - dst = strconv.AppendBool(dst, val) - case time.Time: - dst = val.AppendFormat(dst, time.RFC3339) - case time.Duration: - dst = strconv.AppendInt(dst, int64(val), 10) - case error: - dst = append(dst, val.Error()...) - case fmt.Stringer: - dst = append(dst, val.String()...) - default: - dst = append(dst, fmt.Sprint(v)...) - } - return dst -} - -// Cut bytes. like the strings.Cut() -func Cut(bs []byte, sep byte) (before, after []byte, found bool) { - if i := bytes.IndexByte(bs, sep); i >= 0 { - return bs[:i], bs[i+1:], true - } - - before = bs - return -} diff --git a/vendor/github.com/gookit/goutil/comdef/comdef.go b/vendor/github.com/gookit/goutil/comdef/comdef.go index 06e86a2..2a3f7ef 100644 --- a/vendor/github.com/gookit/goutil/comdef/comdef.go +++ b/vendor/github.com/gookit/goutil/comdef/comdef.go @@ -20,19 +20,6 @@ type StringWriteStringer interface { fmt.Stringer } -// StringMatcher interface -type StringMatcher interface { - Match(s string) bool -} - -// StringMatchFunc definition -type StringMatchFunc func(s string) bool - -// Match satisfies the StringMatcher interface -func (fn StringMatchFunc) Match(s string) bool { - return fn(s) -} - type ( // MarshalFunc define MarshalFunc func(v any) ([]byte, error) diff --git a/vendor/github.com/gookit/goutil/comdef/types.go b/vendor/github.com/gookit/goutil/comdef/types.go index 2fe167f..a3b9597 100644 --- a/vendor/github.com/gookit/goutil/comdef/types.go +++ b/vendor/github.com/gookit/goutil/comdef/types.go @@ -25,7 +25,7 @@ type IntOrFloat interface { Int | Float } -// XintOrFloat interface type. all int, uint and float types +// XintOrFloat interface type. all (x)int and float types type XintOrFloat interface { Int | Uint | Float } diff --git a/vendor/github.com/gookit/goutil/envutil/README.md b/vendor/github.com/gookit/goutil/envutil/README.md index 85d18c9..1f727c7 100644 --- a/vendor/github.com/gookit/goutil/envutil/README.md +++ b/vendor/github.com/gookit/goutil/envutil/README.md @@ -14,8 +14,6 @@ go get github.com/gookit/goutil/envutil ## Functions API -> **Note**: doc by run `go doc ./envutil` - ```go func Environ() map[string]string func GetBool(name string, def ...bool) bool diff --git a/vendor/github.com/gookit/goutil/errorx/util.go b/vendor/github.com/gookit/goutil/errorx/util.go index 8558785..54cf9ea 100644 --- a/vendor/github.com/gookit/goutil/errorx/util.go +++ b/vendor/github.com/gookit/goutil/errorx/util.go @@ -5,31 +5,11 @@ import ( "fmt" ) -// E new a raw go error. alias of errors.New() -func E(msg string) error { - return errors.New(msg) -} - -// Err new a raw go error. alias of errors.New() -func Err(msg string) error { - return errors.New(msg) -} - // Raw new a raw go error. alias of errors.New() func Raw(msg string) error { return errors.New(msg) } -// Ef new a raw go error. alias of errors.New() -func Ef(tpl string, vars ...any) error { - return fmt.Errorf(tpl, vars...) -} - -// Errf new a raw go error. alias of errors.New() -func Errf(tpl string, vars ...any) error { - return fmt.Errorf(tpl, vars...) -} - // Rawf new a raw go error. alias of errors.New() func Rawf(tpl string, vars ...any) error { return fmt.Errorf(tpl, vars...) @@ -74,7 +54,7 @@ func ToErrorX(err error) (ex *ErrorX, ok bool) { return } -// Has contains target error, or err is eq target. +// Has check err has contains target, or err is eq target. // alias of errors.Is() func Has(err, target error) bool { return errors.Is(err, target) diff --git a/vendor/github.com/gookit/goutil/fmtutil/fmtutil.go b/vendor/github.com/gookit/goutil/fmtutil/fmtutil.go index df87d3c..fcfd27d 100644 --- a/vendor/github.com/gookit/goutil/fmtutil/fmtutil.go +++ b/vendor/github.com/gookit/goutil/fmtutil/fmtutil.go @@ -1,17 +1,2 @@ // Package fmtutil provide some format util functions. package fmtutil - -import ( - "encoding/json" - - "github.com/gookit/goutil/strutil" -) - -// StringOrJSON encode pretty JSON data to json bytes. -func StringOrJSON(v any) ([]byte, error) { - s, err := strutil.StringOrErr(v) - if err != nil { - return json.MarshalIndent(v, "", " ") - } - return []byte(s), nil -} diff --git a/vendor/github.com/gookit/goutil/fmtutil/format.go b/vendor/github.com/gookit/goutil/fmtutil/format.go index 9e39553..502bbb6 100644 --- a/vendor/github.com/gookit/goutil/fmtutil/format.go +++ b/vendor/github.com/gookit/goutil/fmtutil/format.go @@ -2,11 +2,10 @@ package fmtutil import ( "encoding/json" + "fmt" "strconv" - - "github.com/gookit/goutil/basefn" - "github.com/gookit/goutil/byteutil" - "github.com/gookit/goutil/strutil" + "strings" + "unicode" ) // data size @@ -24,7 +23,16 @@ const ( // fl, err := file.Stat() // fmtSize := DataSize(fl.Size()) func DataSize(size uint64) string { - return basefn.DataSize(size) + switch { + case size < 1024: + return fmt.Sprintf("%dB", size) + case size < 1024*1024: + return fmt.Sprintf("%.2fK", float64(size)/1024) + case size < 1024*1024*1024: + return fmt.Sprintf("%.2fM", float64(size)/1024/1024) + default: + return fmt.Sprintf("%.2fG", float64(size)/1024/1024/1024) + } } // SizeToString alias of the DataSize @@ -35,8 +43,42 @@ func StringToByte(sizeStr string) uint64 { return ParseByte(sizeStr) } // ParseByte converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes func ParseByte(sizeStr string) uint64 { - val, _ := strutil.ToByteSize(sizeStr) - return val + sizeStr = strings.TrimSpace(sizeStr) + lastPos := len(sizeStr) - 1 + if lastPos < 1 { + return 0 + } + + if sizeStr[lastPos] == 'b' || sizeStr[lastPos] == 'B' { + // last second char is k,m,g + lastSec := sizeStr[lastPos-1] + if lastSec > 'A' { + lastPos-- + } + } + + multiplier := float64(1) + switch unicode.ToLower(rune(sizeStr[lastPos])) { + case 'k': + multiplier = 1 << 10 + sizeStr = strings.TrimSpace(sizeStr[:lastPos]) + case 'm': + multiplier = 1 << 20 + sizeStr = strings.TrimSpace(sizeStr[:lastPos]) + case 'g': + multiplier = 1 << 30 + sizeStr = strings.TrimSpace(sizeStr[:lastPos]) + default: // b + multiplier = 1 + sizeStr = strings.TrimSpace(sizeStr[:lastPos]) + } + + size, _ := strconv.ParseFloat(sizeStr, 64) + if size < 0 { + return 0 + } + + return uint64(size * multiplier) } // PrettyJSON get pretty Json string @@ -60,19 +102,15 @@ func StringsToInts(ss []string) (ints []int, err error) { } // ArgsWithSpaces it like Println, will add spaces for each argument -func ArgsWithSpaces(vs []any) (message string) { - if ln := len(vs); ln == 0 { - return "" +func ArgsWithSpaces(args []any) (message string) { + if ln := len(args); ln == 0 { + message = "" } else if ln == 1 { - return strutil.SafeString(vs[0]) + message = fmt.Sprint(args[0]) } else { - bs := make([]byte, 0, ln*8) - for i := range vs { - if i > 0 { // add space - bs = append(bs, ' ') - } - bs = byteutil.AppendAny(bs, vs[i]) - } - return string(bs) + message = fmt.Sprintln(args...) + // clear last "\n" + message = message[:len(message)-1] } + return } diff --git a/vendor/github.com/gookit/goutil/fmtutil/time.go b/vendor/github.com/gookit/goutil/fmtutil/time.go index 2d61c2b..d6ccfc4 100644 --- a/vendor/github.com/gookit/goutil/fmtutil/time.go +++ b/vendor/github.com/gookit/goutil/fmtutil/time.go @@ -1,10 +1,52 @@ package fmtutil -import ( - "github.com/gookit/goutil/basefn" -) +import "fmt" + +var timeFormats = [][]int{ + {0}, + {1}, + {2, 1}, + {60}, + {120, 60}, + {3600}, + {7200, 3600}, + {86400}, + {172800, 86400}, +} + +var timeMessages = []string{ + "< 1 sec", "1 sec", "secs", "1 min", "mins", "1 hr", "hrs", "1 day", "days", +} // HowLongAgo format a seconds, get how lang ago func HowLongAgo(sec int64) string { - return basefn.HowLongAgo(sec) + intVal := int(sec) + length := len(timeFormats) + + for i, item := range timeFormats { + if intVal >= item[0] { + ni := i + 1 + match := false + + if ni < length { // next exists + next := timeFormats[ni] + if intVal < next[0] { // current <= intVal < next + match = true + } + } else if ni == length { // current is last + match = true + } + + if match { // match success + if len(item) == 1 { + return timeMessages[i] + } + + // len is 2 + return fmt.Sprintf("%d %s", intVal/item[1], timeMessages[i]) + } + } + } + + return "unknown" // He should never happen } diff --git a/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go b/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go index bd9e752..4789294 100644 --- a/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go +++ b/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go @@ -4,9 +4,7 @@ import ( "fmt" "os" "regexp" - "strconv" "strings" - "time" ) // Environ like os.Environ, but will returns key-value map[string]string data. @@ -102,73 +100,3 @@ func FormatTplAndArgs(fmtAndArgs []any) string { } return fmt.Sprint(fmtAndArgs...) } - -var ( - // TIP: extend unit d,w - // time.ParseDuration() is not supported. eg: "1d", "2w" - durStrReg = regexp.MustCompile(`^(-?\d+)(ns|us|µs|ms|s|m|h|d|w)$`) - // match long duration string, such as "1hour", "2hours", "3minutes", "4mins", "5days", "1weeks" - // time.ParseDuration() is not supported. - durStrRegL = regexp.MustCompile(`^(-?\d+)([a-zA-Z]{3,})$`) -) - -// IsDuration check the string is a duration string. -func IsDuration(s string) bool { - if s == "0" || durStrReg.MatchString(s) { - return true - } - return durStrRegL.MatchString(s) -} - -// ToDuration parses a duration string. such as "300ms", "-1.5h" or "2h45m". -// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". -// -// Diff of time.ParseDuration: -// - support extend unit d, w at the end of string. such as "1d", "2w". -// - support long string unit at end. such as "1hour", "2hours", "3minutes", "4mins", "5days", "1weeks". -// -// If the string is not a valid duration string, it will return an error. -func ToDuration(s string) (time.Duration, error) { - ln := len(s) - if ln == 0 { - return 0, fmt.Errorf("empty duration string") - } - - s = strings.ToLower(s) - if s == "0" { - return 0, nil - } - - // extend unit d,w, time.ParseDuration() is not supported. eg: "1d", "2w" - if lastUnit := s[ln-1]; lastUnit == 'd' { - s = s + "ay" - } else if lastUnit == 'w' { - s = s + "eek" - } - - // long unit, time.ParseDuration() is not supported. eg: "-3sec" => [3sec -3 sec] - ss := durStrRegL.FindStringSubmatch(s) - if len(ss) == 3 { - num, unit := ss[1], ss[2] - - // convert to short unit - switch unit { - case "week", "weeks": - // max unit is hour, so need convert by 24 * 7 * n - n, _ := strconv.Atoi(num) - s = strconv.Itoa(n*24*7) + "h" - case "day", "days": - // max unit is hour, so need convert by 24 * n - n, _ := strconv.Atoi(num) - s = strconv.Itoa(n*24) + "h" - case "hour", "hours": - s = num + "h" - case "min", "mins", "minute", "minutes": - s = num + "m" - case "sec", "secs", "second", "seconds": - s = num + "s" - } - } - - return time.ParseDuration(s) -} diff --git a/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go b/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go index aef90e9..76fd61f 100644 --- a/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go +++ b/vendor/github.com/gookit/goutil/internal/comfunc/sysfunc.go @@ -8,14 +8,8 @@ import ( "strings" ) -// Workdir get -func Workdir() string { - dir, _ := os.Getwd() - return dir -} - -// ExpandHome will parse first `~` as user home dir path. -func ExpandHome(pathStr string) string { +// ExpandPath will parse first `~` as user home dir path. +func ExpandPath(pathStr string) string { if len(pathStr) == 0 { return pathStr } @@ -32,6 +26,7 @@ func ExpandHome(pathStr string) string { if err != nil { return pathStr } + return homeDir + pathStr[1:] } @@ -78,26 +73,23 @@ var curShell string // // eg "/bin/zsh" "/bin/bash". // if onlyName=true, will return "zsh", "bash" -func CurrentShell(onlyName bool) (binPath string) { +func CurrentShell(onlyName bool) (path string) { var err error if curShell == "" { - binPath = os.Getenv("SHELL") - if len(binPath) == 0 { - binPath, err = ShellExec("echo $SHELL") - if err != nil { - return "" - } + path, err = ShellExec("echo $SHELL") + if err != nil { + return "" } - binPath = strings.TrimSpace(binPath) + path = strings.TrimSpace(path) // cache result - curShell = binPath + curShell = path } else { - binPath = curShell + path = curShell } - if onlyName && len(binPath) > 0 { - binPath = filepath.Base(binPath) + if onlyName && len(path) > 0 { + path = filepath.Base(path) } return } @@ -114,5 +106,6 @@ func HasShellEnv(shell string) bool { if err != nil { return false } + return strings.TrimSpace(out) == "OK" } diff --git a/vendor/github.com/gookit/goutil/maputil/check.go b/vendor/github.com/gookit/goutil/maputil/check.go index 1f31944..d2c10ff 100644 --- a/vendor/github.com/gookit/goutil/maputil/check.go +++ b/vendor/github.com/gookit/goutil/maputil/check.go @@ -21,25 +21,7 @@ func HasKey(mp, key any) (ok bool) { return } -// HasOneKey check of the given map. return the first exist key -func HasOneKey(mp any, keys ...any) (ok bool, key any) { - rftVal := reflect.Indirect(reflect.ValueOf(mp)) - if rftVal.Kind() != reflect.Map { - return - } - - for _, key = range keys { - for _, keyRv := range rftVal.MapKeys() { - if reflects.IsEqual(keyRv.Interface(), key) { - return true, key - } - } - } - - return false, nil -} - -// HasAllKeys check of the given map. return the first not exist key +// HasAllKeys check of the given map. func HasAllKeys(mp any, keys ...any) (ok bool, noKey any) { rftVal := reflect.Indirect(reflect.ValueOf(mp)) if rftVal.Kind() != reflect.Map { diff --git a/vendor/github.com/gookit/goutil/maputil/convert.go b/vendor/github.com/gookit/goutil/maputil/convert.go index 13d4b0c..24b49fc 100644 --- a/vendor/github.com/gookit/goutil/maputil/convert.go +++ b/vendor/github.com/gookit/goutil/maputil/convert.go @@ -1,12 +1,10 @@ package maputil import ( - "errors" "reflect" "strings" "github.com/gookit/goutil/arrutil" - "github.com/gookit/goutil/comdef" "github.com/gookit/goutil/reflects" "github.com/gookit/goutil/strutil" ) @@ -25,7 +23,7 @@ func KeyToLower(src map[string]string) map[string]string { func ToStringMap(src map[string]any) map[string]string { strMp := make(map[string]string, len(src)) for k, v := range src { - strMp[k] = strutil.SafeString(v) + strMp[k] = strutil.MustString(v) } return strMp } @@ -35,35 +33,6 @@ func CombineToSMap(keys, values []string) SMap { return arrutil.CombineToSMap(keys, values) } -// CombineToMap combine two any slice to map[K]V. alias of arrutil.CombineToMap -func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V { - return arrutil.CombineToMap(keys, values) -} - -// ToAnyMap convert map[TYPE1]TYPE2 to map[string]any -func ToAnyMap(mp any) map[string]any { - amp, _ := TryAnyMap(mp) - return amp -} - -// TryAnyMap convert map[TYPE1]TYPE2 to map[string]any -func TryAnyMap(mp any) (map[string]any, error) { - if aMp, ok := mp.(map[string]any); ok { - return aMp, nil - } - - rv := reflect.Indirect(reflect.ValueOf(mp)) - if rv.Kind() != reflect.Map { - return nil, errors.New("input is not a map value") - } - - anyMp := make(map[string]any, rv.Len()) - for _, key := range rv.MapKeys() { - anyMp[key.String()] = rv.MapIndex(key).Interface() - } - return anyMp, nil -} - // HTTPQueryString convert map[string]any data to http query string. func HTTPQueryString(data map[string]any) string { ss := make([]string, 0, len(data)) @@ -74,30 +43,6 @@ func HTTPQueryString(data map[string]any) string { return strings.Join(ss, "&") } -// StringsMapToAnyMap convert map[string][]string to map[string]any -// -// Example: -// {"k1": []string{"v1", "v2"}, "k2": []string{"v3"}} -// => -// {"k": []string{"v1", "v2"}, "k2": "v3"} -// -// mp := StringsMapToAnyMap(httpReq.Header) -func StringsMapToAnyMap(ssMp map[string][]string) map[string]any { - if len(ssMp) == 0 { - return nil - } - - anyMp := make(map[string]any, len(ssMp)) - for k, v := range ssMp { - if len(v) == 1 { - anyMp[k] = v[0] - continue - } - anyMp[k] = v - } - return anyMp -} - // ToString simple and quickly convert map[string]any to string. func ToString(mp map[string]any) string { if mp == nil { diff --git a/vendor/github.com/gookit/goutil/maputil/data.go b/vendor/github.com/gookit/goutil/maputil/data.go index 4049a8b..fad2f14 100644 --- a/vendor/github.com/gookit/goutil/maputil/data.go +++ b/vendor/github.com/gookit/goutil/maputil/data.go @@ -245,16 +245,9 @@ func (d Data) String() string { return ToString(d) } -// Load other data to current data map +// Load data to current data map func (d Data) Load(sub map[string]any) { for name, val := range sub { d[name] = val } } - -// LoadSMap to data -func (d Data) LoadSMap(smp map[string]string) { - for name, val := range smp { - d[name] = val - } -} diff --git a/vendor/github.com/gookit/goutil/maputil/get.go b/vendor/github.com/gookit/goutil/maputil/get.go index c2236c4..151d918 100644 --- a/vendor/github.com/gookit/goutil/maputil/get.go +++ b/vendor/github.com/gookit/goutil/maputil/get.go @@ -6,12 +6,6 @@ import ( "strings" ) -// some consts for separators -const ( - Wildcard = "*" - PathSep = "." -) - // DeepGet value by key path. eg "top" "top.sub" func DeepGet(mp map[string]any, path string) (val any) { val, _ = GetByPath(path, mp) @@ -31,96 +25,48 @@ func GetByPath(path string, mp map[string]any) (val any, ok bool) { } // no sub key - if len(mp) == 0 || strings.IndexByte(path, '.') < 1 { + if len(mp) == 0 || !strings.ContainsRune(path, '.') { return nil, false } // has sub key. eg. "top.sub" keys := strings.Split(path, ".") - return GetByPathKeys(mp, keys) -} - -// GetByPathKeys get value by path keys from a map(map[string]any). eg "top" "top.sub" -// -// Example: -// -// mp := map[string]any{ -// "top": map[string]any{ -// "sub": "value", -// }, -// } -// val, ok := GetByPathKeys(mp, []string{"top", "sub"}) // return "value", true -func GetByPathKeys(mp map[string]any, keys []string) (val any, ok bool) { - kl := len(keys) - if kl == 0 { - return mp, true - } + topK := keys[0] // find top item data use top key var item any - - topK := keys[0] if item, ok = mp[topK]; !ok { return } - // find sub item data use sub key - for i, k := range keys[1:] { + for _, k := range keys[1:] { switch tData := item.(type) { - case map[string]string: // is string map + case map[string]string: // is simple map if item, ok = tData[k]; !ok { return } - case map[string]any: // is map(decode from toml/json/yaml) + case map[string]any: // is map(decode from toml/json) if item, ok = tData[k]; !ok { return } - case map[any]any: // is map(decode from yaml.v2) + case map[any]any: // is map(decode from yaml) if item, ok = tData[k]; !ok { return } - case []map[string]any: // is an any-map slice - if k == Wildcard { - if kl == i+2 { - return tData, true - } - - sl := make([]any, 0, len(tData)) - for _, v := range tData { - if val, ok = GetByPathKeys(v, keys[i+2:]); ok { - sl = append(sl, val) - } - } - return sl, true + case []any: // is a slice + if item, ok = getBySlice(k, tData); !ok { + return } - - // k is index number - idx, err := strconv.Atoi(k) - if err != nil { - return nil, false + case []string, []int, []float32, []float64, []bool, []rune: + slice := reflect.ValueOf(tData) + sData := make([]any, slice.Len()) + for i := 0; i < slice.Len(); i++ { + sData[i] = slice.Index(i).Interface() } - - if idx >= len(tData) { - return nil, false - } - item = tData[idx] - default: - rv := reflect.ValueOf(tData) - // check is slice - if rv.Kind() == reflect.Slice { - i, err := strconv.Atoi(k) - if err != nil { - return nil, false - } - if i >= rv.Len() { - return nil, false - } - - item = rv.Index(i).Interface() - continue + if item, ok = getBySlice(k, sData); !ok { + return } - - // as error + default: // error return nil, false } } @@ -128,6 +74,17 @@ func GetByPathKeys(mp map[string]any, keys []string) (val any, ok bool) { return item, true } +func getBySlice(k string, slice []any) (val any, ok bool) { + i, err := strconv.ParseInt(k, 10, 64) + if err != nil { + return nil, false + } + if size := int64(len(slice)); i >= size { + return nil, false + } + return slice[i], true +} + // Keys get all keys of the given map. func Keys(mp any) (keys []string) { rftVal := reflect.Indirect(reflect.ValueOf(mp)) @@ -144,26 +101,14 @@ func Keys(mp any) (keys []string) { // Values get all values from the given map. func Values(mp any) (values []any) { - rv := reflect.Indirect(reflect.ValueOf(mp)) - if rv.Kind() != reflect.Map { + rftVal := reflect.Indirect(reflect.ValueOf(mp)) + if rftVal.Kind() != reflect.Map { return } - values = make([]any, 0, rv.Len()) - for _, key := range rv.MapKeys() { - values = append(values, rv.MapIndex(key).Interface()) + values = make([]any, 0, rftVal.Len()) + for _, key := range rftVal.MapKeys() { + values = append(values, rftVal.MapIndex(key).Interface()) } return } - -// EachAnyMap iterates the given map and calls the given function for each item. -func EachAnyMap(mp any, fn func(key string, val any)) { - rv := reflect.Indirect(reflect.ValueOf(mp)) - if rv.Kind() != reflect.Map { - panic("not a map value") - } - - for _, key := range rv.MapKeys() { - fn(key.String(), rv.MapIndex(key).Interface()) - } -} diff --git a/vendor/github.com/gookit/goutil/maputil/maputil.go b/vendor/github.com/gookit/goutil/maputil/maputil.go index 96247fd..7becfa7 100644 --- a/vendor/github.com/gookit/goutil/maputil/maputil.go +++ b/vendor/github.com/gookit/goutil/maputil/maputil.go @@ -22,25 +22,18 @@ func SimpleMerge(src, dst map[string]any) map[string]any { if len(src) == 0 { return dst } + if len(dst) == 0 { return src } for key, val := range src { - if mp, ok := val.(map[string]any); ok { - if dmp, ok := dst[key].(map[string]any); ok { - dst[key] = SimpleMerge(mp, dmp) - continue - } - } - - // simple merge dst[key] = val } return dst } -// func DeepMerge(src, dst map[string]any, deep int) map[string]any { TODO +// func DeepMerge(src, dst map[string]any, deep int) map[string]any { // } // MergeSMap simple merge two string map. merge src to dst map @@ -61,6 +54,7 @@ func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]stri if ignoreCase { k = strings.ToLower(k) } + dst[k] = v } return dst diff --git a/vendor/github.com/gookit/goutil/mathutil/check.go b/vendor/github.com/gookit/goutil/mathutil/check.go index 055fc4d..45c4992 100644 --- a/vendor/github.com/gookit/goutil/mathutil/check.go +++ b/vendor/github.com/gookit/goutil/mathutil/check.go @@ -1,8 +1,6 @@ package mathutil -import "github.com/gookit/goutil/comdef" - -// Compare any intX,floatX value by given op. returns `srcVal op(=,!=,<,<=,>,>=) dstVal` +// Compare intX,floatX value by given op. returns `srcVal op(=,!=,<,<=,>,>=) dstVal` // // Usage: // @@ -44,54 +42,40 @@ func Compare(srcVal, dstVal any, op string) (ok bool) { return CompInt64(srcInt, dstInt, op) } -// CompInt compare int,uint value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal` -func CompInt[T comdef.Xint](srcVal, dstVal T, op string) (ok bool) { - return CompValue(srcVal, dstVal, op) -} - -// CompInt64 compare int64 value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal` -func CompInt64(srcVal, dstVal int64, op string) bool { - return CompValue(srcVal, dstVal, op) -} - -// CompFloat compare float64,float32 value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal` -func CompFloat[T comdef.Float](srcVal, dstVal T, op string) (ok bool) { - return CompValue(srcVal, dstVal, op) -} - -// CompValue compare intX,uintX,floatX value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal` -func CompValue[T comdef.XintOrFloat](srcVal, dstVal T, op string) (ok bool) { +// CompInt64 compare int64, returns the srcI64 op dstI64 +func CompInt64(srcI64, dstI64 int64, op string) (ok bool) { switch op { case "<", "lt": - ok = srcVal < dstVal + ok = srcI64 < dstI64 case "<=", "lte": - ok = srcVal <= dstVal + ok = srcI64 <= dstI64 case ">", "gt": - ok = srcVal > dstVal + ok = srcI64 > dstI64 case ">=", "gte": - ok = srcVal >= dstVal + ok = srcI64 >= dstI64 case "=", "eq": - ok = srcVal == dstVal + ok = srcI64 == dstI64 case "!=", "ne", "neq": - ok = srcVal != dstVal + ok = srcI64 != dstI64 } return } -// InRange check if val in int/float range [min, max] -func InRange[T comdef.IntOrFloat](val, min, max T) bool { - return val >= min && val <= max -} - -// OutRange check if val not in int/float range [min, max] -func OutRange[T comdef.IntOrFloat](val, min, max T) bool { - return val < min || val > max -} - -// InUintRange check if val in unit range [min, max] -func InUintRange[T comdef.Uint](val, min, max T) bool { - if max == 0 { - return val >= min +// CompFloat compare float64 +func CompFloat(srcF64, dstF64 float64, op string) (ok bool) { + switch op { + case "<", "lt": + ok = srcF64 < dstF64 + case "<=", "lte": + ok = srcF64 <= dstF64 + case ">", "gt": + ok = srcF64 > dstF64 + case ">=", "gte": + ok = srcF64 >= dstF64 + case "=", "eq": + ok = srcF64 == dstF64 + case "!=", "ne", "neq": + ok = srcF64 != dstF64 } - return val >= min && val <= max + return } diff --git a/vendor/github.com/gookit/goutil/mathutil/convert.go b/vendor/github.com/gookit/goutil/mathutil/convert.go index 4034e39..c8bf855 100644 --- a/vendor/github.com/gookit/goutil/mathutil/convert.go +++ b/vendor/github.com/gookit/goutil/mathutil/convert.go @@ -388,8 +388,8 @@ func TryToString(val any, defaultAsErr bool) (str string, err error) { case float64: str = strconv.FormatFloat(value, 'f', -1, 64) case time.Duration: - str = strconv.FormatInt(int64(value), 10) - case fmt.Stringer: + str = strconv.FormatUint(uint64(value.Nanoseconds()), 10) + case json.Number: str = value.String() default: if defaultAsErr { diff --git a/vendor/github.com/gookit/goutil/mathutil/mathutil.go b/vendor/github.com/gookit/goutil/mathutil/mathutil.go index 52a2e14..587346a 100644 --- a/vendor/github.com/gookit/goutil/mathutil/mathutil.go +++ b/vendor/github.com/gookit/goutil/mathutil/mathutil.go @@ -7,14 +7,6 @@ import ( "github.com/gookit/goutil/comdef" ) -// Min compare two value and return max value -func Min[T comdef.XintOrFloat](x, y T) T { - if x < y { - return x - } - return y -} - // Max compare two value and return max value func Max[T comdef.XintOrFloat](x, y T) T { if x > y { @@ -23,14 +15,6 @@ func Max[T comdef.XintOrFloat](x, y T) T { return y } -// SwapMin compare and always return [min, max] value -func SwapMin[T comdef.XintOrFloat](x, y T) (T, T) { - if x < y { - return x, y - } - return y, x -} - // SwapMax compare and always return [max, min] value func SwapMax[T comdef.XintOrFloat](x, y T) (T, T) { if x > y { diff --git a/vendor/github.com/gookit/goutil/mathutil/number.go b/vendor/github.com/gookit/goutil/mathutil/number.go index 5b13594..8c5d29b 100644 --- a/vendor/github.com/gookit/goutil/mathutil/number.go +++ b/vendor/github.com/gookit/goutil/mathutil/number.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/gookit/goutil/basefn" + "github.com/gookit/goutil/fmtutil" ) // IsNumeric returns true if the given character is a numeric, otherwise false. @@ -17,6 +17,7 @@ func Percent(val, total int) float64 { if total == 0 { return float64(0) } + return (float64(val) / float64(total)) * 100 } @@ -25,13 +26,12 @@ func ElapsedTime(startTime time.Time) string { return fmt.Sprintf("%.3f", time.Since(startTime).Seconds()*1000) } -// DataSize format value to data size string. eg: 1024 => 1KB, 1024*1024 => 1MB -// alias format.DataSize() +// DataSize format value. alias format.DataSize() func DataSize(size uint64) string { - return basefn.DataSize(size) + return fmtutil.DataSize(size) } // HowLongAgo calc time. alias format.HowLongAgo() func HowLongAgo(sec int64) string { - return basefn.HowLongAgo(sec) + return fmtutil.HowLongAgo(sec) } diff --git a/vendor/github.com/gookit/goutil/reflects/README.md b/vendor/github.com/gookit/goutil/reflects/README.md index 1215141..84269fe 100644 --- a/vendor/github.com/gookit/goutil/reflects/README.md +++ b/vendor/github.com/gookit/goutil/reflects/README.md @@ -16,58 +16,6 @@ go get github.com/gookit/goutil/reflects ## Usage -```go -import "github.com/gookit/goutil/reflects" - -// get struct field value -reflects.GetFieldValue(obj, "Name") -``` - -## Functions API - -> **Note**: doc by run `go doc ./reflects` - -```go -func BaseTypeVal(v reflect.Value) (value any, err error) -func ConvSlice(oldSlRv reflect.Value, newElemTyp reflect.Type) (rv reflect.Value, err error) -func EachMap(mp reflect.Value, fn func(key, val reflect.Value)) -func EachStrAnyMap(mp reflect.Value, fn func(key string, val any)) -func Elem(v reflect.Value) reflect.Value -func FlatMap(rv reflect.Value, fn FlatFunc) -func HasChild(v reflect.Value) bool -func Indirect(v reflect.Value) reflect.Value -func IsAnyInt(k reflect.Kind) bool -func IsArrayOrSlice(k reflect.Kind) bool -func IsEmpty(v reflect.Value) bool -func IsEmptyValue(v reflect.Value) bool -func IsEqual(src, dst any) bool -func IsFunc(val any) bool -func IsIntx(k reflect.Kind) bool -func IsNil(v reflect.Value) bool -func IsSimpleKind(k reflect.Kind) bool -func IsUintX(k reflect.Kind) bool -func Len(v reflect.Value) int -func SetRValue(rv, val reflect.Value) -func SetUnexportedValue(rv reflect.Value, value any) -func SetValue(rv reflect.Value, val any) error -func SliceElemKind(typ reflect.Type) reflect.Kind -func SliceSubKind(typ reflect.Type) reflect.Kind -func String(rv reflect.Value) string -func ToString(rv reflect.Value) (str string, err error) -func UnexportedValue(rv reflect.Value) any -func ValToString(rv reflect.Value, defaultAsErr bool) (str string, err error) -func ValueByKind(val any, kind reflect.Kind) (rv reflect.Value, err error) -func ValueByType(val any, typ reflect.Type) (rv reflect.Value, err error) -type BKind uint - func ToBKind(kind reflect.Kind) BKind - func ToBaseKind(kind reflect.Kind) BKind -type FlatFunc func(path string, val reflect.Value) -type Type interface{ ... } - func TypeOf(v any) Type -type Value struct{ ... } - func ValueOf(v any) Value - func Wrap(rv reflect.Value) Value -``` ## Testings diff --git a/vendor/github.com/gookit/goutil/reflects/check.go b/vendor/github.com/gookit/goutil/reflects/check.go index 7ca257c..804eba0 100644 --- a/vendor/github.com/gookit/goutil/reflects/check.go +++ b/vendor/github.com/gookit/goutil/reflects/check.go @@ -5,7 +5,7 @@ import ( "reflect" ) -// HasChild type check. eg: array, slice, map, struct +// HasChild check. eg: array, slice, map, struct func HasChild(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.Struct: @@ -19,29 +19,6 @@ func IsArrayOrSlice(k reflect.Kind) bool { return k == reflect.Slice || k == reflect.Array } -// IsSimpleKind kind in: string, bool, intX, uintX, floatX -func IsSimpleKind(k reflect.Kind) bool { - if reflect.String == k { - return true - } - return k > reflect.Invalid && k <= reflect.Float64 -} - -// IsAnyInt check is intX or uintX type -func IsAnyInt(k reflect.Kind) bool { - return k >= reflect.Int && k <= reflect.Uintptr -} - -// IsIntx check is intX type -func IsIntx(k reflect.Kind) bool { - return k >= reflect.Int && k <= reflect.Int64 -} - -// IsUintX check is uintX type -func IsUintX(k reflect.Kind) bool { - return k >= reflect.Uint && k <= reflect.Uintptr -} - // IsNil reflect value func IsNil(v reflect.Value) bool { switch v.Kind() { diff --git a/vendor/github.com/gookit/goutil/reflects/conv.go b/vendor/github.com/gookit/goutil/reflects/conv.go index 1dfa303..ca4b343 100644 --- a/vendor/github.com/gookit/goutil/reflects/conv.go +++ b/vendor/github.com/gookit/goutil/reflects/conv.go @@ -130,11 +130,7 @@ func ValueByKind(val any, kind reflect.Kind) (rv reflect.Value, err error) { return } -// ConvSlice make new type slice from old slice, will auto convert element type. -// -// TIPs: -// -// Only support kind: string, bool, intX, uintX, floatX +// ConvSlice make new type slice from old slice func ConvSlice(oldSlRv reflect.Value, newElemTyp reflect.Type) (rv reflect.Value, err error) { if !IsArrayOrSlice(oldSlRv.Kind()) { panic("only allow array or slice type value") diff --git a/vendor/github.com/gookit/goutil/reflects/util.go b/vendor/github.com/gookit/goutil/reflects/util.go index 44d1716..f8d2941 100644 --- a/vendor/github.com/gookit/goutil/reflects/util.go +++ b/vendor/github.com/gookit/goutil/reflects/util.go @@ -4,7 +4,6 @@ import ( "fmt" "reflect" "strconv" - "unsafe" ) // Elem returns the value that the interface v contains @@ -50,56 +49,23 @@ func Len(v reflect.Value) int { return -1 } -// SliceSubKind get sub-elem kind of the array, slice, variadic-var. alias SliceElemKind() -func SliceSubKind(typ reflect.Type) reflect.Kind { - return SliceElemKind(typ) -} - -// SliceElemKind get sub-elem kind of the array, slice, variadic-var. +// SliceSubKind get sub-elem kind of the array, slice, variadic-var. // // Usage: // -// SliceElemKind(reflect.TypeOf([]string{"abc"})) // reflect.String -func SliceElemKind(typ reflect.Type) reflect.Kind { +// SliceSubKind(reflect.TypeOf([]string{"abc"})) // reflect.String +func SliceSubKind(typ reflect.Type) reflect.Kind { if typ.Kind() == reflect.Slice || typ.Kind() == reflect.Array { return typ.Elem().Kind() } return reflect.Invalid } -// UnexportedValue quickly get unexported value by reflect.Value -// -// NOTE: this method is unsafe, use it carefully. -// should ensure rv is addressable by field.CanAddr() -// -// refer: https://stackoverflow.com/questions/42664837/how-to-access-unexported-struct-fields -func UnexportedValue(rv reflect.Value) any { - if rv.CanAddr() { - // create new value from addr, now can be read and set. - return reflect.NewAt(rv.Type(), unsafe.Pointer(rv.UnsafeAddr())).Elem().Interface() - } - - // If the rv is not addressable this trick won't work, but you can create an addressable copy like this - rs2 := reflect.New(rv.Type()).Elem() - rs2.Set(rv) - rv = rs2.Field(0) - rv = reflect.NewAt(rv.Type(), unsafe.Pointer(rv.UnsafeAddr())).Elem() - // Now rv can be read. TIP: Setting will succeed but only affects the temporary copy. - return rv.Interface() -} - -// SetUnexportedValue quickly set unexported field value by reflect -// -// NOTE: this method is unsafe, use it carefully. -// should ensure rv is addressable by field.CanAddr() -func SetUnexportedValue(rv reflect.Value, value any) { - reflect.NewAt(rv.Type(), unsafe.Pointer(rv.UnsafeAddr())).Elem().Set(reflect.ValueOf(value)) -} - -// SetValue to a `reflect.Value`. will auto convert type if needed. +// SetValue to a reflect.Value func SetValue(rv reflect.Value, val any) error { // get real type of the ptr value if rv.Kind() == reflect.Ptr { + // init if is nil if rv.IsNil() { elemTyp := rv.Type().Elem() rv.Set(reflect.New(elemTyp)) @@ -116,40 +82,6 @@ func SetValue(rv reflect.Value, val any) error { return err } -// SetRValue to a `reflect.Value`. will direct set value without convert type. -func SetRValue(rv, val reflect.Value) { - if rv.Kind() == reflect.Ptr { - if rv.IsNil() { - elemTyp := rv.Type().Elem() - rv.Set(reflect.New(elemTyp)) - } - rv = reflect.Indirect(rv) - } - - rv.Set(val) -} - -// EachMap process any map data -func EachMap(mp reflect.Value, fn func(key, val reflect.Value)) { - if fn == nil { - return - } - if mp.Kind() != reflect.Map { - panic("only allow map value data") - } - - for _, key := range mp.MapKeys() { - fn(key, mp.MapIndex(key)) - } -} - -// EachStrAnyMap process any map data as string key and any value -func EachStrAnyMap(mp reflect.Value, fn func(key string, val any)) { - EachMap(mp, func(key, val reflect.Value) { - fn(String(key), val.Interface()) - }) -} - // FlatFunc custom collect handle func type FlatFunc func(path string, val reflect.Value) diff --git a/vendor/github.com/gookit/goutil/stdio/ioutil.go b/vendor/github.com/gookit/goutil/stdio/ioutil.go index 1bf65c0..13d1608 100644 --- a/vendor/github.com/gookit/goutil/stdio/ioutil.go +++ b/vendor/github.com/gookit/goutil/stdio/ioutil.go @@ -7,8 +7,8 @@ import ( ) // QuietFprint to writer, will ignore error -func QuietFprint(w io.Writer, a ...any) { - _, _ = fmt.Fprint(w, a...) +func QuietFprint(w io.Writer, ss ...string) { + _, _ = fmt.Fprint(w, strings.Join(ss, "")) } // QuietFprintf to writer, will ignore error @@ -17,8 +17,8 @@ func QuietFprintf(w io.Writer, tpl string, vs ...any) { } // QuietFprintln to writer, will ignore error -func QuietFprintln(w io.Writer, a ...any) { - _, _ = fmt.Fprintln(w, a...) +func QuietFprintln(w io.Writer, ss ...string) { + _, _ = fmt.Fprintln(w, strings.Join(ss, "")) } // QuietWriteString to writer, will ignore error diff --git a/vendor/github.com/gookit/goutil/stdio/stdio.go b/vendor/github.com/gookit/goutil/stdio/stdio.go index 48f7738..6252704 100644 --- a/vendor/github.com/gookit/goutil/stdio/stdio.go +++ b/vendor/github.com/gookit/goutil/stdio/stdio.go @@ -61,22 +61,11 @@ func NewScanner(in any) *bufio.Scanner { } } -// WriteByte to stdout -func WriteByte(b byte) { - _, _ = os.Stdout.Write([]byte{b}) -} - // WriteBytes to stdout func WriteBytes(bs []byte) { _, _ = os.Stdout.Write(bs) } -// WritelnBytes to stdout -func WritelnBytes(bs []byte) { - _, _ = os.Stdout.Write(bs) - _, _ = os.Stdout.Write([]byte("\n")) -} - // WriteString to stdout func WriteString(s string) { _, _ = os.Stdout.WriteString(s) diff --git a/vendor/github.com/gookit/goutil/structs/alias.go b/vendor/github.com/gookit/goutil/structs/alias.go index a25e1bf..5288056 100644 --- a/vendor/github.com/gookit/goutil/structs/alias.go +++ b/vendor/github.com/gookit/goutil/structs/alias.go @@ -27,6 +27,7 @@ func (as *Aliases) AddAlias(real, alias string) { if rn, ok := as.mapping[alias]; ok { panic(fmt.Sprintf("The alias '%s' is already used by '%s'", alias, rn)) } + as.mapping[alias] = real } diff --git a/vendor/github.com/gookit/goutil/structs/convert.go b/vendor/github.com/gookit/goutil/structs/convert.go index 8a379fe..78e56e9 100644 --- a/vendor/github.com/gookit/goutil/structs/convert.go +++ b/vendor/github.com/gookit/goutil/structs/convert.go @@ -6,7 +6,6 @@ import ( "reflect" "github.com/gookit/goutil/maputil" - "github.com/gookit/goutil/reflects" ) // ToMap quickly convert structs to map by reflect @@ -29,31 +28,7 @@ func TryToMap(st any, optFns ...MapOptFunc) (map[string]any, error) { return StructToMap(st, optFns...) } -// ToSMap quickly and safe convert structs to map[string]string by reflect -func ToSMap(st any, optFns ...MapOptFunc) map[string]string { - mp, _ := StructToMap(st, optFns...) - return maputil.ToStringMap(mp) -} - -// TryToSMap quickly convert structs to map[string]string by reflect -func TryToSMap(st any, optFns ...MapOptFunc) (map[string]string, error) { - mp, err := StructToMap(st, optFns...) - if err != nil { - return nil, err - } - return maputil.ToStringMap(mp), nil -} - -// MustToSMap alias of ToStringMap(), but will panic on error -func MustToSMap(st any, optFns ...MapOptFunc) map[string]string { - mp, err := StructToMap(st, optFns...) - if err != nil { - panic(err) - } - return maputil.ToStringMap(mp) -} - -// ToString quickly format struct to string +// ToString format func ToString(st any, optFns ...MapOptFunc) string { mp, err := StructToMap(st, optFns...) if err == nil { @@ -64,38 +39,14 @@ func ToString(st any, optFns ...MapOptFunc) string { const defaultFieldTag = "json" -// MapOptions for convert struct to map +// MapOptions struct type MapOptions struct { - // TagName for map filed. default is "json" TagName string - // ParseDepth for parse. TODO support depth - ParseDepth int - // MergeAnonymous struct fields to parent map. default is true - MergeAnonymous bool - // ExportPrivate export private fields. default is false - ExportPrivate bool } // MapOptFunc define type MapOptFunc func(opt *MapOptions) -// WithMapTagName set tag name for map field -func WithMapTagName(tagName string) MapOptFunc { - return func(opt *MapOptions) { - opt.TagName = tagName - } -} - -// MergeAnonymous merge anonymous struct fields to parent map -func MergeAnonymous(opt *MapOptions) { - opt.MergeAnonymous = true -} - -// ExportPrivate merge anonymous struct fields to parent map -func ExportPrivate(opt *MapOptions) { - opt.ExportPrivate = true -} - // StructToMap quickly convert structs to map[string]any by reflect. // Can custom export field name by tag `json` or custom tag func StructToMap(st any, optFns ...MapOptFunc) (map[string]any, error) { @@ -104,9 +55,13 @@ func StructToMap(st any, optFns ...MapOptFunc) (map[string]any, error) { return mp, nil } - obj := reflect.Indirect(reflect.ValueOf(st)) + obj := reflect.ValueOf(st) + if obj.Kind() == reflect.Ptr { + obj = obj.Elem() + } + if obj.Kind() != reflect.Struct { - return mp, errors.New("must be an struct value") + return mp, errors.New("must be an struct") } opt := &MapOptions{TagName: defaultFieldTag} @@ -114,25 +69,23 @@ func StructToMap(st any, optFns ...MapOptFunc) (map[string]any, error) { fn(opt) } - _, err := structToMap(obj, opt, mp) + mp, err := structToMap(obj, opt.TagName) return mp, err } -func structToMap(obj reflect.Value, opt *MapOptions, mp map[string]any) (map[string]any, error) { - if mp == nil { - mp = make(map[string]any) - } - +func structToMap(obj reflect.Value, tagName string) (map[string]any, error) { refType := obj.Type() + mp := make(map[string]any) + for i := 0; i < obj.NumField(); i++ { ft := refType.Field(i) name := ft.Name - // skip un-exported field - if !opt.ExportPrivate && IsUnexported(name) { + // skip don't exported field + if name[0] >= 'a' && name[0] <= 'z' { continue } - tagVal, ok := ft.Tag.Lookup(opt.TagName) + tagVal, ok := ft.Tag.Lookup(tagName) if ok && tagVal != "" { sMap, err := ParseTagValueDefault(name, tagVal) if err != nil { @@ -140,33 +93,24 @@ func structToMap(obj reflect.Value, opt *MapOptions, mp map[string]any) (map[str } name = sMap.Default("name", name) - if name == "" { // un-exported field + // un-exported field + if name == "" { continue } } - field := reflect.Indirect(obj.Field(i)) + field := obj.Field(i) if field.Kind() == reflect.Struct { - // collect anonymous struct values to parent. - if ft.Anonymous && opt.MergeAnonymous { - _, err := structToMap(field, opt, mp) - if err != nil { - return nil, err - } - } else { // collect struct values to submap - sub, err := structToMap(field, opt, nil) - if err != nil { - return nil, err - } - mp[name] = sub + sub, err := structToMap(field, tagName) + if err != nil { + return nil, err } + mp[name] = sub continue } if field.CanInterface() { mp[name] = field.Interface() - } else if field.CanAddr() { // for unexported field - mp[name] = reflects.UnexportedValue(field) } } diff --git a/vendor/github.com/gookit/goutil/structs/copy.go b/vendor/github.com/gookit/goutil/structs/copy.go deleted file mode 100644 index d427351..0000000 --- a/vendor/github.com/gookit/goutil/structs/copy.go +++ /dev/null @@ -1,6 +0,0 @@ -package structs - -// MapStruct simple copy src struct value to dst struct -// func MapStruct(srcSt, dstSt any) { -// // TODO -// } diff --git a/vendor/github.com/gookit/goutil/structs/data.go b/vendor/github.com/gookit/goutil/structs/data.go index 9dbe098..ae00818 100644 --- a/vendor/github.com/gookit/goutil/structs/data.go +++ b/vendor/github.com/gookit/goutil/structs/data.go @@ -10,47 +10,76 @@ import ( ) // LiteData simple map[string]any struct. no lock -type LiteData = Data +type LiteData struct { + data map[string]any +} -// NewLiteData create, not lock -func NewLiteData(data map[string]any) *Data { - if data == nil { - data = make(map[string]any) - } +// Data get all +func (d *LiteData) Data() map[string]any { + return d.data +} + +// SetData set all data +func (d *LiteData) SetData(data map[string]any) { + d.data = data +} + +// Value get from data +func (d *LiteData) Value(key string) any { + return d.data[key] +} + +// GetVal get from data +func (d *LiteData) GetVal(key string) any { + return d.data[key] +} - return &LiteData{ - data: data, +// StrValue get from data +func (d *LiteData) StrValue(key string) string { + return strutil.QuietString(d.data[key]) +} + +// IntVal get from data +func (d *LiteData) IntVal(key string) int { + return mathutil.QuietInt(d.data[key]) +} + +// SetValue to data +func (d *LiteData) SetValue(key string, val any) { + if d.data == nil { + d.data = make(map[string]any) } + d.data[key] = val +} + +// ResetData all data +func (d *LiteData) ResetData() { + d.data = nil } /************************************************************* * data struct and allow enable lock *************************************************************/ -// Data struct, allow enable lock +// Data struct, allow enable lock TODO type Data struct { sync.RWMutex - lock bool + enableLock bool + // data store data map[string]any } -// NewData create new data instance +// NewData create func NewData() *Data { return &Data{ - lock: true, data: make(map[string]any), } } -// WithLock for operate data -func (d *Data) WithLock() *Data { - d.lock = true - return d -} - // EnableLock for operate data func (d *Data) EnableLock() *Data { - return d.WithLock() + d.enableLock = true + return d } // Data get all @@ -60,7 +89,7 @@ func (d *Data) Data() map[string]any { // SetData set all data func (d *Data) SetData(data map[string]any) { - if !d.lock { + if !d.enableLock { d.data = data return } @@ -80,11 +109,6 @@ func (d *Data) ResetData() { d.data = make(map[string]any) } -// Merge load new data -func (d *Data) Merge(mp map[string]any) { - d.data = maputil.SimpleMerge(d.data, mp) -} - // Set value to data func (d *Data) Set(key string, val any) { d.SetValue(key, val) @@ -92,7 +116,7 @@ func (d *Data) Set(key string, val any) { // SetValue to data func (d *Data) SetValue(key string, val any) { - if d.lock { + if d.enableLock { d.Lock() defer d.Unlock() } @@ -102,12 +126,12 @@ func (d *Data) SetValue(key string, val any) { // Value get from data func (d *Data) Value(key string) (val any, ok bool) { - if d.lock { + if d.enableLock { d.RLock() defer d.RUnlock() } - val, ok = maputil.GetByPath(key, d.data) + val, ok = d.data[key] return } @@ -118,13 +142,12 @@ func (d *Data) Get(key string) any { // GetVal get from data func (d *Data) GetVal(key string) any { - if d.lock { + if d.enableLock { d.RLock() defer d.RUnlock() } - val, _ := maputil.GetByPath(key, d.data) - return val + return d.data[key] } // StrVal get from data diff --git a/vendor/github.com/gookit/goutil/structs/init.go b/vendor/github.com/gookit/goutil/structs/init.go deleted file mode 100644 index 73aec38..0000000 --- a/vendor/github.com/gookit/goutil/structs/init.go +++ /dev/null @@ -1,194 +0,0 @@ -package structs - -import ( - "errors" - "reflect" - - "github.com/gookit/goutil/internal/comfunc" - "github.com/gookit/goutil/reflects" - "github.com/gookit/goutil/strutil" -) - -const defaultInitTag = "default" - -// InitOptFunc define -type InitOptFunc func(opt *InitOptions) - -// InitOptions struct -type InitOptions struct { - // TagName default value tag name. tag: default - TagName string - // ParseEnv var name on default value. eg: `default:"${APP_ENV}"` - // - // default: false - ParseEnv bool - // ValueHook before set value hook TODO - ValueHook func(val string) any -} - -// Init struct default value by field "default" tag. -func Init(ptr any, optFns ...InitOptFunc) error { - return InitDefaults(ptr, optFns...) -} - -// InitDefaults init struct default value by field "default" tag. -// -// TIPS: -// -// Support init field types: string, bool, intX, uintX, floatX, array, slice -// -// Example: -// -// type User1 struct { -// Name string `default:"inhere"` -// Age int32 `default:"30"` -// } -// -// u1 := &User1{} -// err = structs.InitDefaults(u1) -// fmt.Printf("%+v\n", u1) // Output: {Name:inhere Age:30} -func InitDefaults(ptr any, optFns ...InitOptFunc) error { - rv := reflect.ValueOf(ptr) - if rv.Kind() != reflect.Ptr { - return errors.New("must be provider an pointer value") - } - - rv = rv.Elem() - if rv.Kind() != reflect.Struct { - return errors.New("must be provider an struct value") - } - - opt := &InitOptions{TagName: defaultInitTag} - for _, fn := range optFns { - fn(opt) - } - - return initDefaults(rv, opt) -} - -func initDefaults(rv reflect.Value, opt *InitOptions) error { - rt := rv.Type() - - for i := 0; i < rt.NumField(); i++ { - sf := rt.Field(i) - // skip don't exported field - if IsUnexported(sf.Name) { - continue - } - - val, hasTag := sf.Tag.Lookup(opt.TagName) - if !hasTag || val == "-" { - continue - } - - fv := rv.Field(i) - if fv.Kind() == reflect.Struct { - if err := initDefaults(fv, opt); err != nil { - return err - } - continue - } - - // skip on field has value - if !fv.IsZero() { - // special: handle for pointer struct field - if fv.Kind() == reflect.Pointer { - fv = fv.Elem() - if fv.Kind() == reflect.Struct { - if err := initDefaults(fv, opt); err != nil { - return err - } - } - } else if fv.Kind() == reflect.Slice { - el := sf.Type.Elem() - if el.Kind() == reflect.Pointer { - el = el.Elem() - } - - // init sub struct in slice. like `[]SubStruct` or `[]*SubStruct` - if el.Kind() == reflect.Struct && fv.Len() > 0 { - for i := 0; i < fv.Len(); i++ { - subFv := reflect.Indirect(fv.Index(i)) - if err := initDefaults(subFv, opt); err != nil { - return err - } - } - } - } - continue - } - - // handle for pointer field - if fv.Kind() == reflect.Pointer { - if fv.IsNil() { - fv.Set(reflect.New(fv.Type().Elem())) - } - - fv = fv.Elem() - if fv.Kind() == reflect.Struct { - if err := initDefaults(fv, opt); err != nil { - return err - } - continue - } - } else if fv.Kind() == reflect.Slice { - el := sf.Type.Elem() - isPtr := el.Kind() == reflect.Pointer - if isPtr { - el = el.Elem() - } - - // init sub struct in slice. like `[]SubStruct` or `[]*SubStruct` - if el.Kind() == reflect.Struct { - // make sub-struct and init. like: `SubStruct` - subFv := reflect.New(el) - subFvE := subFv.Elem() - if err := initDefaults(subFvE, opt); err != nil { - return err - } - - // make new slice and set value. - newFv := reflect.MakeSlice(reflect.SliceOf(sf.Type.Elem()), 0, 1) - if isPtr { - newFv = reflect.Append(newFv, subFv) - } else { - newFv = reflect.Append(newFv, subFvE) - } - fv.Set(newFv) - continue - } - } - - if err := initDefaultValue(fv, val, opt.ParseEnv); err != nil { - return err - } - } - - return nil -} - -func initDefaultValue(fv reflect.Value, val string, parseEnv bool) error { - if val == "" || !fv.CanSet() { - return nil - } - - // parse env var - if parseEnv { - val = comfunc.ParseEnvVar(val, nil) - } - - var anyVal any = val - - // simple slice: convert simple kind(string,intX,uintX,...) to slice. eg: "1,2,3" => []int{1,2,3} - if reflects.IsArrayOrSlice(fv.Kind()) && reflects.IsSimpleKind(reflects.SliceElemKind(fv.Type())) { - ss := strutil.SplitTrimmed(val, ",") - valRv, err := reflects.ConvSlice(reflect.ValueOf(ss), fv.Type().Elem()) - if err == nil { - reflects.SetRValue(fv, valRv) - } - return err - } - - // set value - return reflects.SetValue(fv, anyVal) -} diff --git a/vendor/github.com/gookit/goutil/structs/setval.go b/vendor/github.com/gookit/goutil/structs/setval.go new file mode 100644 index 0000000..ce2a021 --- /dev/null +++ b/vendor/github.com/gookit/goutil/structs/setval.go @@ -0,0 +1,236 @@ +package structs + +import ( + "errors" + "fmt" + "reflect" + + "github.com/gookit/goutil/internal/comfunc" + "github.com/gookit/goutil/reflects" + "github.com/gookit/goutil/strutil" +) + +const defaultInitTag = "default" + +// InitOptFunc define +type InitOptFunc func(opt *InitOptions) + +// InitOptions struct +type InitOptions struct { + // TagName default value tag name. tag: default + TagName string + // ParseEnv var name on default value. eg: `default:"${APP_ENV}"` + // + // default: false + ParseEnv bool + // ValueHook before set value hook TODO + ValueHook func(val string) any +} + +// InitDefaults init struct default value by field "default" tag. +// +// TIPS: +// +// Support init field types: string, bool, intX, uintX, floatX, array, slice +// +// Example: +// +// type User1 struct { +// Name string `default:"inhere"` +// Age int32 `default:"30"` +// } +// +// u1 := &User1{} +// err = structs.InitDefaults(u1) +// fmt.Printf("%+v\n", u1) // Output: {Name:inhere Age:30} +func InitDefaults(ptr any, optFns ...InitOptFunc) error { + rv := reflect.ValueOf(ptr) + if rv.Kind() != reflect.Ptr { + return errors.New("must be provider an pointer value") + } + + rv = rv.Elem() + if rv.Kind() != reflect.Struct { + return errors.New("must be provider an struct value") + } + + opt := &InitOptions{TagName: defaultInitTag} + for _, fn := range optFns { + fn(opt) + } + + return initDefaults(rv, opt) +} + +func initDefaults(rv reflect.Value, opt *InitOptions) error { + rt := rv.Type() + + for i := 0; i < rt.NumField(); i++ { + ft := rt.Field(i) + // skip don't exported field + if ft.Name[0] >= 'a' && ft.Name[0] <= 'z' { + continue + } + + fv := rv.Field(i) + if fv.Kind() == reflect.Struct { + if err := initDefaults(fv, opt); err != nil { + return err + } + continue + } + + // skip on field has value + if !fv.IsZero() { + continue + } + + val := ft.Tag.Get(opt.TagName) + if err := initDefaultValue(fv, val, opt.ParseEnv); err != nil { + return err + } + } + + return nil +} + +func initDefaultValue(fv reflect.Value, val string, parseEnv bool) error { + if val == "" || !fv.CanSet() { + return nil + } + + // parse env var + if parseEnv { + val = comfunc.ParseEnvVar(val, nil) + } + + var anyVal any = val + + // convert string to slice + if reflects.IsArrayOrSlice(fv.Kind()) { + ss := strutil.SplitTrimmed(val, ",") + valRv, err := reflects.ConvSlice(reflect.ValueOf(ss), fv.Type().Elem()) + if err != nil { + return err + } + anyVal = valRv.Interface() + } + + // set value + return reflects.SetValue(fv, anyVal) +} + +/************************************************************* + * load values to a struct + *************************************************************/ + +// SetOptFunc define +type SetOptFunc func(opt *SetOptions) + +// SetOptions for set values to struct +type SetOptions struct { + // FieldTagName get field name for read value. default tag: json + FieldTagName string + // ValueHook before set value hook TODO + ValueHook func(val any) any + + // ParseDefault init default value by DefaultValTag tag value. + // default: false + // + // see InitDefaults() + ParseDefault bool + // DefaultValTag name. tag: default + DefaultValTag string + // ParseDefaultEnv parse env var on default tag. eg: `default:"${APP_ENV}"` + // + // default: false + ParseDefaultEnv bool +} + +// SetValues set data values to struct ptr +// +// TIPS: +// +// Only support set: string, bool, intX, uintX, floatX +func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error { + rv := reflect.ValueOf(ptr) + if rv.Kind() != reflect.Ptr { + return errors.New("must be provider an pointer value") + } + + rv = rv.Elem() + if rv.Kind() != reflect.Struct { + return errors.New("must be provider an struct value") + } + + opt := &SetOptions{ + FieldTagName: "json", + DefaultValTag: defaultInitTag, + } + + for _, fn := range optFns { + fn(opt) + } + return setValues(rv, data, opt) +} + +func setValues(rv reflect.Value, data map[string]any, opt *SetOptions) error { + if len(data) == 0 { + return nil + } + + rt := rv.Type() + + for i := 0; i < rt.NumField(); i++ { + ft := rt.Field(i) + name := ft.Name + // skip don't exported field + if name[0] >= 'a' && name[0] <= 'z' { + continue + } + + // get field name + tagVal, ok := ft.Tag.Lookup(opt.FieldTagName) + if ok { + info, err := ParseTagValueDefault(name, tagVal) + if err != nil { + return err + } + + name = info.Get("name") + } + + fv := rv.Field(i) + val, ok := data[name] + + // set field value by default tag. + if !ok && fv.IsZero() { + defVal := ft.Tag.Get(opt.DefaultValTag) + + if err := initDefaultValue(fv, defVal, opt.ParseDefaultEnv); err != nil { + return err + } + continue + } + + // field is struct + if fv.Kind() == reflect.Struct { + asMp, ok := val.(map[string]any) + if !ok { + return fmt.Errorf("field is struct, must provide map data value") + } + + if err := setValues(fv, asMp, opt); err != nil { + return err + } + continue + } + + // set field value + if err := reflects.SetValue(fv, val); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/gookit/goutil/structs/structs.go b/vendor/github.com/gookit/goutil/structs/structs.go index c671f21..e5cf212 100644 --- a/vendor/github.com/gookit/goutil/structs/structs.go +++ b/vendor/github.com/gookit/goutil/structs/structs.go @@ -1,15 +1,17 @@ // Package structs Provide some extends util functions for struct. eg: tag parse, struct init, value set package structs +// MapStruct simple copy src struct value to dst struct +// func MapStruct(srcSt, dstSt any) { +// // TODO +// } + // IsExported field name on struct -func IsExported(name string) bool { - return name[0] >= 'A' && name[0] <= 'Z' +func IsExported(fieldName string) bool { + return fieldName[0] >= 'A' && fieldName[0] <= 'Z' } // IsUnexported field name on struct -func IsUnexported(name string) bool { - if name[0] == '_' { - return true - } - return name[0] >= 'a' && name[0] <= 'z' +func IsUnexported(fieldName string) bool { + return !IsExported(fieldName) } diff --git a/vendor/github.com/gookit/goutil/structs/value.go b/vendor/github.com/gookit/goutil/structs/value.go index 52ae940..c6312f2 100644 --- a/vendor/github.com/gookit/goutil/structs/value.go +++ b/vendor/github.com/gookit/goutil/structs/value.go @@ -107,7 +107,7 @@ func (v *Value) Strings() (ss []string) { return } -// SplitToStrings split string value to strings. sep default is comma(,) +// SplitToStrings split string value to strings func (v *Value) SplitToStrings(sep ...string) (ss []string) { if v.V == nil { return @@ -119,7 +119,7 @@ func (v *Value) SplitToStrings(sep ...string) (ss []string) { return } -// SplitToInts split string value to []int. sep default is comma(,) +// SplitToInts split string value to []int func (v *Value) SplitToInts(sep ...string) (ss []int) { if v.V == nil { return diff --git a/vendor/github.com/gookit/goutil/structs/wrapper.go b/vendor/github.com/gookit/goutil/structs/wrapper.go deleted file mode 100644 index 59bfe3b..0000000 --- a/vendor/github.com/gookit/goutil/structs/wrapper.go +++ /dev/null @@ -1,51 +0,0 @@ -package structs - -import "reflect" - -// Wrapper struct for read or set field value TODO -type Wrapper struct { - // src any // source data struct - rv reflect.Value - - // FieldTagName field name for read/write value. default tag: json - FieldTagName string -} - -// Wrap create a struct wrapper -func Wrap(src any) *Wrapper { - return NewWrapper(src) -} - -// NewWrapper create a struct wrapper -func NewWrapper(src any) *Wrapper { - return WrapValue(reflect.ValueOf(src)) -} - -// WrapValue create a struct wrapper -func WrapValue(rv reflect.Value) *Wrapper { - rv = reflect.Indirect(rv) - if rv.Kind() != reflect.Struct { - panic("must be provider an struct value") - } - - return &Wrapper{rv: rv} -} - -// Get field value by name -func (r *Wrapper) Get(name string) any { - val, ok := r.Lookup(name) - if !ok { - return nil - } - return val -} - -// Lookup field value by name -func (r *Wrapper) Lookup(name string) (val any, ok bool) { - fv := r.rv.FieldByName(name) - if !fv.IsValid() { - return - } - - return fv.Interface(), true -} diff --git a/vendor/github.com/gookit/goutil/structs/writer.go b/vendor/github.com/gookit/goutil/structs/writer.go deleted file mode 100644 index ac306e1..0000000 --- a/vendor/github.com/gookit/goutil/structs/writer.go +++ /dev/null @@ -1,148 +0,0 @@ -package structs - -import ( - "errors" - "fmt" - "reflect" - - "github.com/gookit/goutil/maputil" - "github.com/gookit/goutil/reflects" -) - -// NewWriter create a struct writer -func NewWriter(ptr any) *Wrapper { - rv := reflect.ValueOf(ptr) - if rv.Kind() != reflect.Pointer { - panic("must be provider an pointer value") - } - - return WrapValue(rv) -} - -/************************************************************* - * set values to a struct - *************************************************************/ - -// SetOptFunc define -type SetOptFunc func(opt *SetOptions) - -// SetOptions for set values to struct -type SetOptions struct { - // FieldTagName get field name for read value. default tag: json - FieldTagName string - // ValueHook before set value hook TODO - ValueHook func(val any) any - - // ParseDefault init default value by DefaultValTag tag value. - // default: false - // - // see InitDefaults() - ParseDefault bool - - // DefaultValTag name. tag: default - DefaultValTag string - - // ParseDefaultEnv parse env var on default tag. eg: `default:"${APP_ENV}"` - // - // default: false - ParseDefaultEnv bool -} - -// WithParseDefault value by tag "default" -func WithParseDefault(opt *SetOptions) { - opt.ParseDefault = true -} - -// SetValues set values to struct ptr from map data. -// -// TIPS: -// -// Only support set: string, bool, intX, uintX, floatX -func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error { - rv := reflect.ValueOf(ptr) - if rv.Kind() != reflect.Ptr { - return errors.New("must be provider an pointer value") - } - - rv = rv.Elem() - if rv.Kind() != reflect.Struct { - return errors.New("must be provider an struct value") - } - - opt := &SetOptions{ - FieldTagName: defaultFieldTag, - DefaultValTag: defaultInitTag, - } - - for _, fn := range optFns { - fn(opt) - } - return setValues(rv, data, opt) -} - -func setValues(rv reflect.Value, data map[string]any, opt *SetOptions) error { - if len(data) == 0 { - return nil - } - - rt := rv.Type() - - for i := 0; i < rt.NumField(); i++ { - ft := rt.Field(i) - name := ft.Name - // skip don't exported field - if name[0] >= 'a' && name[0] <= 'z' { - continue - } - - // get field name - tagVal, ok := ft.Tag.Lookup(opt.FieldTagName) - if ok { - info, err := ParseTagValueDefault(name, tagVal) - if err != nil { - return err - } - name = info.Get("name") - } - - fv := rv.Field(i) - val, ok := data[name] - - // set field value by default tag. - if !ok && opt.ParseDefault && fv.IsZero() { - defVal := ft.Tag.Get(opt.DefaultValTag) - if err := initDefaultValue(fv, defVal, opt.ParseDefaultEnv); err != nil { - return err - } - continue - } - - // handle for pointer field - if fv.Kind() == reflect.Pointer { - if fv.IsNil() { - fv.Set(reflect.New(fv.Type().Elem())) - } - fv = fv.Elem() - } - - // field is struct - if fv.Kind() == reflect.Struct { - asMp, err := maputil.TryAnyMap(val) - if err != nil { - return fmt.Errorf("must provide map data for field %q, err=%v", ft.Name, err) - } - - if err := setValues(fv, asMp, opt); err != nil { - return err - } - continue - } - - // set field value - if err := reflects.SetValue(fv, val); err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/gookit/goutil/strutil/check.go b/vendor/github.com/gookit/goutil/strutil/check.go index 8654d84..f85ce92 100644 --- a/vendor/github.com/gookit/goutil/strutil/check.go +++ b/vendor/github.com/gookit/goutil/strutil/check.go @@ -113,16 +113,6 @@ func HasSuffix(s string, suffix string) bool { return strings.HasSuffix(s, suffi // IsEndOf alias of the strings.HasSuffix func IsEndOf(s, suffix string) bool { return strings.HasSuffix(s, suffix) } -// HasOneSuffix the string end withs one of the subs -func HasOneSuffix(s string, suffixes []string) bool { - for _, suffix := range suffixes { - if strings.HasSuffix(s, suffix) { - return true - } - } - return false -} - // IsValidUtf8 valid utf8 string check func IsValidUtf8(s string) bool { return utf8.ValidString(s) } @@ -202,40 +192,6 @@ func VersionCompare(v1, v2, op string) bool { } } -// SimpleMatch all sub-string in the give text string. -// -// Difference the ContainsAll: -// -// - start with ^ for exclude contains check. -// - end with $ for check end with keyword. -func SimpleMatch(s string, keywords []string) bool { - for _, keyword := range keywords { - kln := len(keyword) - if kln == 0 { - continue - } - - // exclude - if kln > 1 && keyword[0] == '^' { - if strings.Contains(s, keyword[1:]) { - return false - } - continue - } - - // end with - if kln > 1 && keyword[kln-1] == '$' { - return strings.HasSuffix(s, keyword[:kln-1]) - } - - // include - if !strings.Contains(s, keyword) { - return false - } - } - return true -} - // QuickMatch check for a string. pattern can be a sub string. func QuickMatch(pattern, s string) bool { if strings.ContainsRune(pattern, '*') { @@ -244,82 +200,8 @@ func QuickMatch(pattern, s string) bool { return strings.Contains(s, pattern) } -// PathMatch check for a string match the pattern. alias of the path.Match() -// -// TIP: `*` can match any char, not contain `/`. -func PathMatch(pattern, s string) bool { - ok, err := path.Match(pattern, s) - if err != nil { - ok = false - } - return ok -} - -// GlobMatch check for a string match the pattern. -// -// Difference with PathMatch() is: `*` can match any char, contain `/`. +// GlobMatch check for a string. func GlobMatch(pattern, s string) bool { - // replace `/` to `S` for path.Match - pattern = strings.Replace(pattern, "/", "S", -1) - s = strings.Replace(s, "/", "S", -1) - - ok, err := path.Match(pattern, s) - if err != nil { - ok = false - } - return ok -} - -// LikeMatch simple check for a string match the pattern. pattern like the SQL LIKE. -func LikeMatch(pattern, s string) bool { - ln := len(pattern) - if ln < 2 { - return false - } - - // eg `%abc` `%abc%` - if pattern[0] == '%' { - if ln > 2 && pattern[ln-1] == '%' { - return strings.Contains(s, pattern[1:ln-1]) - } else { - return strings.HasSuffix(s, pattern[1:]) - } - } - - // eg `abc%` - if pattern[ln-1] == '%' { - return strings.HasPrefix(s, pattern[:ln-1]) - } - return pattern == s -} - -// MatchNodePath check for a string match the pattern. -// -// Use on pattern: -// - `*` match any to sep -// - `**` match any to end. only allow at start or end on pattern. -// -// Example: -// -// strutil.MatchNodePath() -func MatchNodePath(pattern, s string, sep string) bool { - if pattern == "**" || pattern == s { - return true - } - if pattern == "" { - return len(s) == 0 - } - - if i := strings.Index(pattern, "**"); i >= 0 { - if i == 0 { // at start - return strings.HasSuffix(s, pattern[2:]) - } - return strings.HasPrefix(s, pattern[:len(pattern)-2]) - } - - pattern = strings.Replace(pattern, sep, "/", -1) - s = strings.Replace(s, sep, "/", -1) - ok, err := path.Match(pattern, s) if err != nil { ok = false diff --git a/vendor/github.com/gookit/goutil/strutil/convert.go b/vendor/github.com/gookit/goutil/strutil/convert.go index 067876d..9d98f45 100644 --- a/vendor/github.com/gookit/goutil/strutil/convert.go +++ b/vendor/github.com/gookit/goutil/strutil/convert.go @@ -1,6 +1,7 @@ package strutil import ( + "encoding/json" "errors" "fmt" "reflect" @@ -19,7 +20,7 @@ var ( // ErrDateLayout error ErrDateLayout = errors.New("invalid date layout string") // ErrInvalidParam error - ErrInvalidParam = errors.New("invalid input for parse time") + ErrInvalidParam = errors.New("invalid input parameter") // some regex for convert string. toSnakeReg = regexp.MustCompile("[A-Z][a-z]") @@ -169,8 +170,8 @@ func AnyToString(val any, defaultAsErr bool) (str string, err error) { case []byte: str = string(value) case time.Duration: - str = strconv.FormatInt(int64(value), 10) - case fmt.Stringer: + str = value.String() + case json.Number: str = value.String() default: if defaultAsErr { @@ -364,8 +365,87 @@ func ToSlice(s string, sep ...string) []string { // return cliutil.StringToOSArgs(s) // error: import cycle not allowed // } +// MustToTime convert date string to time.Time +func MustToTime(s string, layouts ...string) time.Time { + t, err := ToTime(s, layouts...) + if err != nil { + panic(err) + } + return t +} + +// auto match use some commonly layouts. +// key is layout length. +var layoutMap = map[int][]string{ + 6: {"200601", "060102", time.Kitchen}, + 8: {"20060102"}, + 10: {"2006-01-02"}, + 13: {"2006-01-02 15"}, + 15: {time.Stamp}, + 16: {"2006-01-02 15:04"}, + 19: {"2006-01-02 15:04:05", time.RFC822, time.StampMilli}, + 20: {"2006-01-02 15:04:05Z"}, + 21: {time.RFC822Z}, + 22: {time.StampMicro}, + 24: {time.ANSIC}, + 25: {time.RFC3339, time.StampNano}, + // 26: {time.Layout}, // must go >= 1.19 + 28: {time.UnixDate}, + 29: {time.RFC1123}, + 30: {time.RFC850}, + 31: {time.RFC1123Z}, + 35: {time.RFC3339Nano}, +} + +// ToTime convert date string to time.Time +func ToTime(s string, layouts ...string) (t time.Time, err error) { + // custom layout + if len(layouts) > 0 { + if len(layouts[0]) > 0 { + return time.Parse(layouts[0], s) + } + + err = ErrDateLayout + return + } + + // auto match use some commonly layouts. + strLn := len(s) + maybeLayouts, ok := layoutMap[strLn] + if !ok { + err = ErrInvalidParam + return + } + + var hasAlphaT bool + if pos := strings.IndexByte(s, 'T'); pos > 0 && pos < 12 { + hasAlphaT = true + } + + hasSlashR := strings.IndexByte(s, '/') > 0 + for _, layout := range maybeLayouts { + // date string has "T". eg: "2006-01-02T15:04:05" + if hasAlphaT { + layout = strings.Replace(layout, " ", "T", 1) + } + + // date string has "/". eg: "2006/01/02 15:04:05" + if hasSlashR { + layout = strings.Replace(layout, "-", "/", -1) + } + + t, err = time.Parse(layout, s) + if err == nil { + return + } + } + + // t, err = time.ParseInLocation(layout, s, time.Local) + return +} + // ToDuration parses a duration string. such as "300ms", "-1.5h" or "2h45m". // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". func ToDuration(s string) (time.Duration, error) { - return comfunc.ToDuration(s) + return time.ParseDuration(s) } diff --git a/vendor/github.com/gookit/goutil/strutil/filter.go b/vendor/github.com/gookit/goutil/strutil/filter.go index f925a44..c80f664 100644 --- a/vendor/github.com/gookit/goutil/strutil/filter.go +++ b/vendor/github.com/gookit/goutil/strutil/filter.go @@ -64,9 +64,6 @@ func FilterEmail(s string) string { return s } - // According to rfc5321, "The local-part of a mailbox MUST BE treated as case-sensitive" + // According to rfc5321, "The local-part of a mailbox MUST BE treated as case sensitive" return s[0:i] + "@" + strings.ToLower(s[i+1:]) } - -// func Filter(ss []string, fls ...comdef.StringMatchFunc) []string { -// } diff --git a/vendor/github.com/gookit/goutil/strutil/id.go b/vendor/github.com/gookit/goutil/strutil/id.go index 0e8fe65..053ba10 100644 --- a/vendor/github.com/gookit/goutil/strutil/id.go +++ b/vendor/github.com/gookit/goutil/strutil/id.go @@ -1,9 +1,6 @@ package strutil import ( - "hash/crc32" - "math/rand" - "os" "strconv" "time" @@ -36,34 +33,3 @@ func MicroTimeHexID() string { return strconv.FormatInt(ms, 16) + strconv.FormatInt(int64(ri), 16) } - -// DatetimeNo generate. can use for order-no. -// -// - No prefix, return like: 2023041410484904074285478388(len: 28) -// - With prefix, return like: prefix2023041410484904074285478388(len: 28 + len(prefix)) -func DatetimeNo(prefix string) string { - nt := time.Now() - pl := len(prefix) - bs := make([]byte, 0, 28+pl) - if pl > 0 { - bs = append(bs, prefix...) - } - - // micro datatime - bs = nt.AppendFormat(bs, "20060102150405.000000") - bs[14+pl] = '0' - - // host - name, err := os.Hostname() - if err != nil { - name = "default" - } - c32 := crc32.ChecksumIEEE([]byte(name)) // eg: 4006367001 - bs = strconv.AppendUint(bs, uint64(c32%99), 10) - - // rand 10000 - 99999 - rand.Seed(nt.UnixNano()) - bs = strconv.AppendInt(bs, 10000+rand.Int63n(89999), 10) - - return string(bs) -} diff --git a/vendor/github.com/gookit/goutil/strutil/parse.go b/vendor/github.com/gookit/goutil/strutil/parse.go deleted file mode 100644 index 82fd519..0000000 --- a/vendor/github.com/gookit/goutil/strutil/parse.go +++ /dev/null @@ -1,229 +0,0 @@ -package strutil - -import ( - "errors" - "strconv" - "strings" - "time" - "unicode" - - "github.com/gookit/goutil/byteutil" -) - -// MustToTime convert date string to time.Time -func MustToTime(s string, layouts ...string) time.Time { - t, err := ToTime(s, layouts...) - if err != nil { - panic(err) - } - return t -} - -// auto match use some commonly layouts. -// key is layout length. -var layoutMap = map[int][]string{ - 6: {"200601", "060102", time.Kitchen}, - 8: {"20060102"}, - 10: {"2006-01-02"}, - 13: {"2006-01-02 15"}, - 15: {time.Stamp}, - 16: {"2006-01-02 15:04"}, - 19: {"2006-01-02 15:04:05", time.RFC822, time.StampMilli}, - 20: {"2006-01-02 15:04:05Z"}, - 21: {time.RFC822Z}, - 22: {time.StampMicro}, - 23: {"2006-01-02 15:04:05.000", "2006-01-02 15:04:05.999"}, - 24: {time.ANSIC}, - 25: {time.RFC3339, time.StampNano}, - // time.Layout}, // must go >= 1.19 - 26: {"2006-01-02 15:04:05.000000"}, - 28: {time.UnixDate}, - 29: {time.RFC1123, "2006-01-02 15:04:05.000000000"}, - 30: {time.RFC850}, - 31: {time.RFC1123Z}, - 35: {time.RFC3339Nano}, -} - -// ToTime convert date string to time.Time -func ToTime(s string, layouts ...string) (t time.Time, err error) { - // custom layout - if len(layouts) > 0 { - if len(layouts[0]) > 0 { - return time.Parse(layouts[0], s) - } - - err = ErrDateLayout - return - } - - // auto match use some commonly layouts. - strLn := len(s) - maybeLayouts, ok := layoutMap[strLn] - if !ok { - err = ErrInvalidParam - return - } - - var hasAlphaT bool - if pos := strings.IndexByte(s, 'T'); pos > 0 && pos < 12 { - hasAlphaT = true - } - - hasSlashR := strings.IndexByte(s, '/') > 0 - for _, layout := range maybeLayouts { - // date string has "T". eg: "2006-01-02T15:04:05" - if hasAlphaT { - layout = strings.Replace(layout, " ", "T", 1) - } - - // date string has "/". eg: "2006/01/02 15:04:05" - if hasSlashR { - layout = strings.Replace(layout, "-", "/", -1) - } - - t, err = time.Parse(layout, s) - if err == nil { - return - } - } - - // t, err = time.ParseInLocation(layout, s, time.Local) - return -} - -// ParseSizeOpt parse size expression options -type ParseSizeOpt struct { - // OneAsMax if only one size value, use it as max size. default is false - OneAsMax bool - // SepChar is the separator char for time range string. default is '~' - SepChar byte - // KeywordFn is the function for parse keyword time string. - KeywordFn func(string) (min, max uint64, err error) -} - -func ensureOpt(opt *ParseSizeOpt) *ParseSizeOpt { - if opt == nil { - opt = &ParseSizeOpt{SepChar: '~'} - } else { - if opt.SepChar == 0 { - opt.SepChar = '~' - } - } - return opt -} - -// ErrInvalidSizeExpr invalid size expression error -var ErrInvalidSizeExpr = errors.New("invalid size expr") - -// ParseSizeRange parse range size expression to min and max size. -// -// Expression format: -// -// "1KB~2MB" => 1KB to 2MB -// "-1KB" => <1KB -// "~1MB" => <1MB -// "< 1KB" => <1KB -// "1KB" => >1KB -// "1KB~" => >1KB -// ">1KB" => >1KB -// "+1KB" => >1KB -func ParseSizeRange(expr string, opt *ParseSizeOpt) (min, max uint64, err error) { - opt = ensureOpt(opt) - expr = strings.TrimSpace(expr) - if expr == "" { - err = ErrInvalidSizeExpr - return - } - - // parse size range. eg: "1KB~2MB" - if strings.IndexByte(expr, '~') > -1 { - s1, s2 := TrimCut(expr, "~") - if s1 != "" { - min, err = ToByteSize(s1) - if err != nil { - return - } - } - - if s2 != "" { - max, err = ToByteSize(s2) - } - return - } - - // parse single size. eg: "1KB" - if byteutil.IsNumChar(expr[0]) { - min, err = ToByteSize(expr) - if err != nil { - return - } - if opt.OneAsMax { - max = min - } - return - } - - // parse with prefix. eg: "<1KB", ">= 1KB", "-1KB", "+1KB" - switch expr[0] { - case '<', '-': - max, err = ToByteSize(strings.Trim(expr[1:], " =")) - case '>', '+': - min, err = ToByteSize(strings.Trim(expr[1:], " =")) - default: - // parse keyword. eg: "small", "large" - if opt.KeywordFn != nil { - min, max, err = opt.KeywordFn(expr) - } else { - err = ErrInvalidSizeExpr - } - } - return -} - -// SafeByteSize converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes -func SafeByteSize(sizeStr string) uint64 { - size, _ := ToByteSize(sizeStr) - return size -} - -// ToByteSize converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes -func ToByteSize(sizeStr string) (uint64, error) { - sizeStr = strings.TrimSpace(sizeStr) - lastPos := len(sizeStr) - 1 - if lastPos < 0 { - return 0, nil - } - - if sizeStr[lastPos] == 'b' || sizeStr[lastPos] == 'B' { - // last second char is k,m,g,t - lastSec := sizeStr[lastPos-1] - if lastSec > 'A' { - lastPos-- - } - } else if IsNumChar(sizeStr[lastPos]) { // not unit suffix. eg: 346 - return strconv.ParseUint(sizeStr, 10, 32) - } - - multiplier := float64(1) - switch unicode.ToLower(rune(sizeStr[lastPos])) { - case 'k': - multiplier = 1 << 10 - case 'm': - multiplier = 1 << 20 - case 'g': - multiplier = 1 << 30 - case 't': - multiplier = 1 << 40 - case 'p': - multiplier = 1 << 50 - default: // b - multiplier = 1 - } - - sizeNum := strings.TrimSpace(sizeStr[:lastPos]) - size, err := strconv.ParseFloat(sizeNum, 64) - if err != nil { - return 0, err - } - return uint64(size * multiplier), nil -} diff --git a/vendor/github.com/gookit/goutil/strutil/random.go b/vendor/github.com/gookit/goutil/strutil/random.go index fe404a0..562039b 100644 --- a/vendor/github.com/gookit/goutil/strutil/random.go +++ b/vendor/github.com/gookit/goutil/strutil/random.go @@ -1,27 +1,20 @@ package strutil import ( + "crypto/rand" "encoding/base64" mathRand "math/rand" "time" - - "github.com/gookit/goutil/byteutil" ) // some consts string chars const ( - Numbers = "0123456789" - HexChars = "0123456789abcdef" - + Numbers = "0123456789" AlphaBet = "abcdefghijklmnopqrstuvwxyz" AlphaBet1 = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" - AlphaNum = "abcdefghijklmnopqrstuvwxyz0123456789" AlphaNum2 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" AlphaNum3 = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" - - Base62Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - Base64Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/" ) // RandomChars generate give length random chars at `a-z` @@ -65,11 +58,17 @@ func RandomCharsV3(ln int) string { // RandomBytes generate func RandomBytes(length int) ([]byte, error) { - return byteutil.Random(length) + b := make([]byte, length) + _, err := rand.Read(b) + // Note that err == nil only if we read len(b) bytes. + if err != nil { + return nil, err + } + + return b, nil } // RandomString generate. -// // Example: // // // this will give us a 44 byte, base64 encoded output @@ -82,20 +81,3 @@ func RandomString(length int) (string, error) { b, err := RandomBytes(length) return base64.URLEncoding.EncodeToString(b), err } - -// RandWithTpl generate random string with give template -func RandWithTpl(n int, letters string) string { - if len(letters) == 0 { - letters = AlphaNum2 - } - - ln := len(letters) - cs := make([]byte, n) - for i := 0; i < n; i++ { - mathRand.Seed(int64(time.Now().Nanosecond())) - idx := mathRand.Intn(ln) - cs[i] = letters[idx] - } - - return byteutil.String(cs) -} diff --git a/vendor/github.com/gookit/goutil/strutil/runes.go b/vendor/github.com/gookit/goutil/strutil/runes.go index 7acb46d..41754f5 100644 --- a/vendor/github.com/gookit/goutil/strutil/runes.go +++ b/vendor/github.com/gookit/goutil/strutil/runes.go @@ -88,9 +88,6 @@ func RunesWidth(rs []rune) (w int) { return w } -// Truncate alias of the Utf8Truncate() -func Truncate(s string, w int, tail string) string { return Utf8Truncate(s, w, tail) } - // TextTruncate alias of the Utf8Truncate() func TextTruncate(s string, w int, tail string) string { return Utf8Truncate(s, w, tail) } diff --git a/vendor/github.com/gookit/goutil/strutil/strutil.go b/vendor/github.com/gookit/goutil/strutil/strutil.go index f902293..55ba81b 100644 --- a/vendor/github.com/gookit/goutil/strutil/strutil.go +++ b/vendor/github.com/gookit/goutil/strutil/strutil.go @@ -11,7 +11,6 @@ import ( ) // OrCond return s1 on cond is True, OR return s2. -// Like: cond ? s1 : s2 func OrCond(cond bool, s1, s2 string) string { if cond { return s1 @@ -19,7 +18,7 @@ func OrCond(cond bool, s1, s2 string) string { return s2 } -// OrElse return s OR orVal(new-value) on s is empty +// OrElse return s OR nv(new-value) on s is empty func OrElse(s, orVal string) string { if s != "" { return s diff --git a/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go b/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go deleted file mode 100644 index a269b15..0000000 --- a/vendor/github.com/gookit/goutil/strutil/textutil/textutil.go +++ /dev/null @@ -1,64 +0,0 @@ -// Package textutil provide some extensions text handle util functions. -package textutil - -import ( - "fmt" - "strings" - - "github.com/gookit/goutil/arrutil" - "github.com/gookit/goutil/maputil" - "github.com/gookit/goutil/strutil" -) - -// ReplaceVars by regex replace given tpl vars. -// -// If format is empty, will use {const defaultVarFormat} -func ReplaceVars(text string, vars map[string]any, format string) string { - return NewVarReplacer(format).Replace(text, vars) -} - -// RenderSMap by regex replace given tpl vars. -// -// If format is empty, will use {const defaultVarFormat} -func RenderSMap(text string, vars map[string]string, format string) string { - return NewVarReplacer(format).RenderSimple(text, vars) -} - -// IsMatchAll keywords in the give text string. -// -// TIP: can use ^ for exclude match. -func IsMatchAll(s string, keywords []string) bool { - return strutil.SimpleMatch(s, keywords) -} - -// ParseInlineINI parse config string to string-map. it's like INI format contents. -// -// Examples: -// -// eg: "name=val0;shorts=i;required=true;desc=a message" -// => -// {name: val0, shorts: i, required: true, desc: a message} -func ParseInlineINI(tagVal string, keys ...string) (mp maputil.SMap, err error) { - ss := strutil.Split(tagVal, ";") - ln := len(ss) - if ln == 0 { - return - } - - mp = make(maputil.SMap, ln) - for _, s := range ss { - if !strings.ContainsRune(s, '=') { - err = fmt.Errorf("parse inline config error: must match `KEY=VAL`") - return - } - - key, val := strutil.TrimCut(s, "=") - if len(keys) > 0 && !arrutil.StringsHas(keys, key) { - err = fmt.Errorf("parse inline config error: invalid key name %q", key) - return - } - - mp[key] = val - } - return -} diff --git a/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go b/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go deleted file mode 100644 index 29ef2c3..0000000 --- a/vendor/github.com/gookit/goutil/strutil/textutil/var_replacer.go +++ /dev/null @@ -1,213 +0,0 @@ -package textutil - -import ( - "reflect" - "regexp" - "strings" - - "github.com/gookit/goutil/arrutil" - "github.com/gookit/goutil/internal/comfunc" - "github.com/gookit/goutil/maputil" - "github.com/gookit/goutil/strutil" -) - -const defaultVarFormat = "{{,}}" - -// FallbackFn type -type FallbackFn = func(name string) (val string, ok bool) - -// VarReplacer struct -type VarReplacer struct { - init bool - - Left, Right string - lLen, rLen int - - varReg *regexp.Regexp - // flatten sub map in vars - flatSubs bool - parseEnv bool - // support parse default value. eg: {{ name | inhere }} - parseDef bool - // keepMissVars list. default False: will clear on each replace - keepMissVars bool - // missing vars list - missVars []string - // NotFound handler - NotFound FallbackFn -} - -// NewVarReplacer instance -func NewVarReplacer(format string, opFns ...func(vp *VarReplacer)) *VarReplacer { - vp := &VarReplacer{flatSubs: true} - for _, fn := range opFns { - fn(vp) - } - return vp.WithFormat(format) -} - -// NewFullReplacer instance -func NewFullReplacer(format string) *VarReplacer { - return NewVarReplacer(format, func(vp *VarReplacer) { - vp.WithParseEnv().WithParseDefault().KeepMissingVars() - }) -} - -// DisableFlatten on the input vars map -func (r *VarReplacer) DisableFlatten() *VarReplacer { - r.flatSubs = false - return r -} - -// KeepMissingVars on the replacement handle -func (r *VarReplacer) KeepMissingVars() *VarReplacer { - r.keepMissVars = true - return r -} - -// WithParseDefault value on the input template contents -func (r *VarReplacer) WithParseDefault() *VarReplacer { - r.parseDef = true - return r -} - -// WithParseEnv on the input vars value -func (r *VarReplacer) WithParseEnv() *VarReplacer { - r.parseEnv = true - return r -} - -// OnNotFound var handle -func (r *VarReplacer) OnNotFound(fn FallbackFn) *VarReplacer { - r.NotFound = fn - return r -} - -// WithFormat custom var template -func (r *VarReplacer) WithFormat(format string) *VarReplacer { - r.Left, r.Right = strutil.QuietCut(strutil.OrElse(format, defaultVarFormat), ",") - r.Init() - return r -} - -// Init var matcher -func (r *VarReplacer) Init() *VarReplacer { - if !r.init { - r.lLen, r.rLen = len(r.Left), len(r.Right) - if r.Right != "" { - r.varReg = regexp.MustCompile(regexp.QuoteMeta(r.Left) + `([\w\s\|.-]+)` + regexp.QuoteMeta(r.Right)) - } else { - // no right tag. eg: $name, $user.age - r.varReg = regexp.MustCompile(regexp.QuoteMeta(r.Left) + `(\w[\w-]*(?:\.[\w-]+)*)`) - } - } - - return r -} - -// ParseVars the text contents and collect vars -func (r *VarReplacer) ParseVars(s string) []string { - ss := arrutil.StringsMap(r.varReg.FindAllString(s, -1), func(val string) string { - return strings.TrimSpace(val[r.lLen : len(val)-r.rLen]) - }) - - return arrutil.Unique(ss) -} - -// Render any-map vars in the text contents -func (r *VarReplacer) Render(s string, tplVars map[string]any) string { - return r.Replace(s, tplVars) -} - -// Replace any-map vars in the text contents -func (r *VarReplacer) Replace(s string, tplVars map[string]any) string { - if !strings.Contains(s, r.Left) { - return s - } - if !r.parseDef && len(tplVars) == 0 { - return s - } - - var varMap map[string]string - - if r.flatSubs { - varMap = make(map[string]string, len(tplVars)*2) - maputil.FlatWithFunc(tplVars, func(path string, val reflect.Value) { - if val.Kind() == reflect.String { - if r.parseEnv { - varMap[path] = comfunc.ParseEnvVar(val.String(), nil) - } else { - varMap[path] = val.String() - } - } else { - varMap[path] = strutil.QuietString(val.Interface()) - } - }) - } else { - varMap = maputil.ToStringMap(tplVars) - } - - return r.Init().doReplace(s, varMap) -} - -// ReplaceSMap string-map vars in the text contents -func (r *VarReplacer) ReplaceSMap(s string, varMap map[string]string) string { - return r.RenderSimple(s, varMap) -} - -// RenderSimple string-map vars in the text contents. alias of ReplaceSMap() -func (r *VarReplacer) RenderSimple(s string, varMap map[string]string) string { - if len(varMap) == 0 || !strings.Contains(s, r.Left) { - return s - } - - if r.parseEnv { - for name, val := range varMap { - varMap[name] = comfunc.ParseEnvVar(val, nil) - } - } - - return r.Init().doReplace(s, varMap) -} - -// MissVars list -func (r *VarReplacer) MissVars() []string { - return r.missVars -} - -// ResetMissVars list -func (r *VarReplacer) ResetMissVars() { - r.missVars = make([]string, 0) -} - -// Replace string-map vars in the text contents -func (r *VarReplacer) doReplace(s string, varMap map[string]string) string { - if !r.keepMissVars { - r.missVars = make([]string, 0) // clear on each replace - } - - return r.varReg.ReplaceAllStringFunc(s, func(sub string) string { - name := strings.TrimSpace(sub[r.lLen : len(sub)-r.rLen]) - - var defVal string - if r.parseDef && strings.ContainsRune(name, '|') { - name, defVal = strutil.TrimCut(name, "|") - } - - if val, ok := varMap[name]; ok { - return val - } - - if r.NotFound != nil { - if val, ok := r.NotFound(name); ok { - return val - } - } - - if len(defVal) > 0 { - return defVal - } - r.missVars = append(r.missVars, name) - return sub - }) -} diff --git a/vendor/github.com/gookit/goutil/sysutil/cmdr/cmd.go b/vendor/github.com/gookit/goutil/sysutil/cmdr/cmd.go index f91a411..8ebda44 100644 --- a/vendor/github.com/gookit/goutil/sysutil/cmdr/cmd.go +++ b/vendor/github.com/gookit/goutil/sysutil/cmdr/cmd.go @@ -21,8 +21,6 @@ type Cmd struct { Name string // DryRun if True, not real execute command DryRun bool - // Vars mapping - Vars map[string]string // BeforeRun hook BeforeRun func(c *Cmd) @@ -30,6 +28,11 @@ type Cmd struct { AfterRun func(c *Cmd, err error) } +// WrapGoCmd instance +func WrapGoCmd(cmd *exec.Cmd) *Cmd { + return &Cmd{Cmd: cmd} +} + // NewGitCmd instance func NewGitCmd(subCmd string, args ...string) *Cmd { return NewCmd("git", subCmd).AddArgs(args) @@ -40,6 +43,7 @@ func NewGitCmd(subCmd string, args ...string) *Cmd { // see exec.Command func NewCmdline(line string) *Cmd { bin, args := cmdline.NewParser(line).WithParseEnv().BinAndArgs() + return NewCmd(bin, args...) } @@ -47,21 +51,17 @@ func NewCmdline(line string) *Cmd { // // see exec.Command func NewCmd(bin string, args ...string) *Cmd { - return WrapGoCmd(exec.Command(bin, args...)) + return &Cmd{ + Cmd: exec.Command(bin, args...), + } } // CmdWithCtx create new instance with context. // // see exec.CommandContext func CmdWithCtx(ctx context.Context, bin string, args ...string) *Cmd { - return WrapGoCmd(exec.CommandContext(ctx, bin, args...)) -} - -// WrapGoCmd instance -func WrapGoCmd(cmd *exec.Cmd) *Cmd { return &Cmd{ - Cmd: cmd, - Vars: make(map[string]string), + Cmd: exec.CommandContext(ctx, bin, args...), } } @@ -260,20 +260,6 @@ func (c *Cmd) WithArgsIf(args []string, exprOk bool) *Cmd { return c } -// WithVars add vars and returns the current object -func (c *Cmd) WithVars(vs map[string]string) *Cmd { - if len(vs) > 0 { - c.Vars = vs - } - return c -} - -// SetVar add var and returns the current object -func (c *Cmd) SetVar(name, val string) *Cmd { - c.Vars[name] = val - return c -} - // ------------------------------------------------- // helper command // ------------------------------------------------- diff --git a/vendor/github.com/gookit/goutil/sysutil/cmdr/runner.go b/vendor/github.com/gookit/goutil/sysutil/cmdr/runner.go index 35f81dd..e18818e 100644 --- a/vendor/github.com/gookit/goutil/sysutil/cmdr/runner.go +++ b/vendor/github.com/gookit/goutil/sysutil/cmdr/runner.go @@ -2,7 +2,6 @@ package cmdr import ( "fmt" - "strings" "github.com/gookit/color" "github.com/gookit/goutil/arrutil" @@ -10,7 +9,6 @@ import ( "github.com/gookit/goutil/errorx" "github.com/gookit/goutil/maputil" "github.com/gookit/goutil/mathutil" - "github.com/gookit/goutil/strutil/textutil" ) // Task struct @@ -48,24 +46,6 @@ func (t *Task) ensureID(idx int) { t.ID = id } -var rpl = textutil.NewVarReplacer("$").DisableFlatten() - -// RunWith command -func (t *Task) RunWith(ctx maputil.Data) error { - cmdVars := ctx.StringMap("cmdVars") - - if len(cmdVars) > 0 { - // rpl := strutil.NewReplacer(cmdVars) - for i, val := range t.Cmd.Args { - if strings.ContainsRune(val, '$') { - t.Cmd.Args[i] = rpl.RenderSimple(val, cmdVars) - } - } - } - - return t.Run() -} - // Run command func (t *Task) Run() error { if t.BeforeRun != nil { @@ -96,9 +76,6 @@ func (t *Task) IsSuccess() bool { return t.err == nil } -// RunnerHookFn func -type RunnerHookFn func(r *Runner, t *Task) bool - // Runner use for batch run multi task commands type Runner struct { prev *Task @@ -139,19 +116,12 @@ func NewRunner(fns ...func(rr *Runner)) *Runner { Params: make(maputil.Map), } - rr.OutToStd = true for _, fn := range fns { fn(rr) } return rr } -// WithOutToStd set -func (r *Runner) WithOutToStd() *Runner { - r.OutToStd = true - return r -} - // Add multitask at once func (r *Runner) Add(tasks ...*Task) *Runner { for _, task := range tasks { @@ -242,11 +212,6 @@ func (r *Runner) Run() error { return r.Errs } -// StepRun one command -func (r *Runner) StepRun() error { - return nil // TODO -} - // RunTask command func (r *Runner) RunTask(task *Task) (goon bool) { if len(r.EnvMap) > 0 { @@ -263,7 +228,7 @@ func (r *Runner) RunTask(task *Task) (goon bool) { } // do running - if err := task.RunWith(r.Params); err != nil { + if err := task.Run(); err != nil { r.Errs[task.ID] = err color.Errorf("Task#%d run error: %s\n", task.Index()+1, err) @@ -287,14 +252,6 @@ func (r *Runner) Len() int { return len(r.tasks) } -// Reset instance -func (r *Runner) Reset() *Runner { - r.prev = nil - r.tasks = make([]*Task, 0) - r.idMap = make(map[string]int, 0) - return r -} - // TaskIDs get func (r *Runner) TaskIDs() []string { ss := make([]string, 0, len(r.idMap)) diff --git a/vendor/github.com/gookit/goutil/sysutil/sysutil.go b/vendor/github.com/gookit/goutil/sysutil/sysutil.go index 60fe67b..88c5ad1 100644 --- a/vendor/github.com/gookit/goutil/sysutil/sysutil.go +++ b/vendor/github.com/gookit/goutil/sysutil/sysutil.go @@ -3,6 +3,7 @@ package sysutil import ( "os" + "path" "path/filepath" ) @@ -14,12 +15,8 @@ func Workdir() string { // BinDir get func BinDir() string { - return filepath.Dir(os.Args[0]) -} - -// BinName get -func BinName() string { - return filepath.Base(os.Args[0]) + binFile := os.Args[0] + return path.Dir(binFile) } // BinFile get @@ -28,13 +25,13 @@ func BinFile() string { } // Open file or url address -func Open(fileOrURL string) error { - return OpenURL(fileOrURL) +func Open(fileOrUrl string) error { + return OpenURL(fileOrUrl) } // OpenBrowser file or url address -func OpenBrowser(fileOrURL string) error { - return OpenURL(fileOrURL) +func OpenBrowser(fileOrUrl string) error { + return OpenURL(fileOrUrl) } // OpenFile opens new browser window for the file path. diff --git a/vendor/github.com/gookit/goutil/sysutil/sysutil_unix.go b/vendor/github.com/gookit/goutil/sysutil/sysutil_linux.go similarity index 97% rename from vendor/github.com/gookit/goutil/sysutil/sysutil_unix.go rename to vendor/github.com/gookit/goutil/sysutil/sysutil_linux.go index 8059b09..e41fc07 100644 --- a/vendor/github.com/gookit/goutil/sysutil/sysutil_unix.go +++ b/vendor/github.com/gookit/goutil/sysutil/sysutil_linux.go @@ -1,5 +1,3 @@ -//go:build !windows && !darwin - package sysutil import ( diff --git a/vendor/github.com/gookit/goutil/sysutil/user.go b/vendor/github.com/gookit/goutil/sysutil/user.go index 7635385..4ba9c75 100644 --- a/vendor/github.com/gookit/goutil/sysutil/user.go +++ b/vendor/github.com/gookit/goutil/sysutil/user.go @@ -76,7 +76,6 @@ func UserConfigDir(subPath string) string { } // ExpandPath will parse `~` as user home dir path. -func ExpandPath(path string) string { return comfunc.ExpandHome(path) } - -// ExpandHome will parse `~` as user home dir path. -func ExpandHome(path string) string { return comfunc.ExpandHome(path) } +func ExpandPath(path string) string { + return comfunc.ExpandPath(path) +} diff --git a/vendor/github.com/gookit/goutil/sysutil/user_nonwin.go b/vendor/github.com/gookit/goutil/sysutil/user_nonwin.go index db5a00e..556ee6e 100644 --- a/vendor/github.com/gookit/goutil/sysutil/user_nonwin.go +++ b/vendor/github.com/gookit/goutil/sysutil/user_nonwin.go @@ -1,4 +1,5 @@ //go:build !windows +// +build !windows package sysutil @@ -11,19 +12,21 @@ import ( // ChangeUserByName change work user by new username. func ChangeUserByName(newUname string) (err error) { u := MustFindUser(newUname) + // syscall.Setlogin(newUname) return ChangeUserUidGid(strutil.IntOrPanic(u.Uid), strutil.IntOrPanic(u.Gid)) } // ChangeUserUidGid change work user by new username uid,gid -func ChangeUserUidGid(newUID int, newGid int) (err error) { - if newUID > 0 { - err = syscall.Setuid(newUID) +func ChangeUserUidGid(newUid int, newGid int) (err error) { + if newUid > 0 { + err = syscall.Setuid(newUid) // update group id if err == nil && newGid > 0 { err = syscall.Setgid(newGid) } } + return } diff --git a/vendor/github.com/gookit/goutil/timex/gotime.go b/vendor/github.com/gookit/goutil/timex/gotime.go deleted file mode 100644 index 03773ab..0000000 --- a/vendor/github.com/gookit/goutil/timex/gotime.go +++ /dev/null @@ -1,127 +0,0 @@ -package timex - -import "time" - -// some time layout or time -const ( - DatetimeLayout = "2006-01-02 15:04:05" - LayoutWithMs3 = "2006-01-02 15:04:05.000" - LayoutWithMs6 = "2006-01-02 15:04:05.000000" - DateOnlyLayout = "2006-01-02" - TimeOnlyLayout = "15:04:05" - - // ZeroUnix zero unix timestamp - ZeroUnix int64 = -62135596800 -) - -var ( - // DefaultLayout template for format time - DefaultLayout = DatetimeLayout - // ZeroTime zero time instance - ZeroTime = time.Time{} -) - -// SetLocalByName set local by tz name. eg: UTC, PRC -func SetLocalByName(tzName string) error { - location, err := time.LoadLocation(tzName) - if err != nil { - return err - } - - time.Local = location - return nil -} - -// NowAddDay add some day time from now -func NowAddDay(day int) time.Time { - return time.Now().AddDate(0, 0, day) -} - -// NowAddHour add some hour time from now -func NowAddHour(hour int) time.Time { - return time.Now().Add(time.Duration(hour) * OneHour) -} - -// NowAddMinutes add some minutes time from now -func NowAddMinutes(minutes int) time.Time { - return time.Now().Add(time.Duration(minutes) * OneMin) -} - -// NowAddSec add some seconds time from now. alias of NowAddSeconds() -func NowAddSec(seconds int) time.Time { - return time.Now().Add(time.Duration(seconds) * time.Second) -} - -// NowAddSeconds add some seconds time from now -func NowAddSeconds(seconds int) time.Time { - return time.Now().Add(time.Duration(seconds) * time.Second) -} - -// NowHourStart time -func NowHourStart() time.Time { - return HourStart(time.Now()) -} - -// NowHourEnd time -func NowHourEnd() time.Time { - return HourEnd(time.Now()) -} - -// AddDay add some day time for given time -func AddDay(t time.Time, day int) time.Time { - return t.AddDate(0, 0, day) -} - -// AddHour add some hour time for given time -func AddHour(t time.Time, hour int) time.Time { - return t.Add(time.Duration(hour) * OneHour) -} - -// AddMinutes add some minutes time for given time -func AddMinutes(t time.Time, minutes int) time.Time { - return t.Add(time.Duration(minutes) * OneMin) -} - -// AddSeconds add some seconds time for given time -func AddSeconds(t time.Time, seconds int) time.Time { - return t.Add(time.Duration(seconds) * time.Second) -} - -// AddSec add some seconds time for given time. alias of AddSeconds() -func AddSec(t time.Time, seconds int) time.Time { - return t.Add(time.Duration(seconds) * time.Second) -} - -// HourStart time for given time -func HourStart(t time.Time) time.Time { - y, m, d := t.Date() - return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location()) -} - -// HourEnd time for given time -func HourEnd(t time.Time) time.Time { - y, m, d := t.Date() - return time.Date(y, m, d, t.Hour(), 59, 59, int(time.Second-time.Nanosecond), t.Location()) -} - -// DayStart time for given time -func DayStart(t time.Time) time.Time { - y, m, d := t.Date() - return time.Date(y, m, d, 0, 0, 0, 0, t.Location()) -} - -// DayEnd time for given time -func DayEnd(t time.Time) time.Time { - y, m, d := t.Date() - return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location()) -} - -// TodayStart time -func TodayStart() time.Time { - return DayStart(time.Now()) -} - -// TodayEnd time -func TodayEnd() time.Time { - return DayEnd(time.Now()) -} diff --git a/vendor/github.com/gookit/goutil/timex/template.go b/vendor/github.com/gookit/goutil/timex/template.go index 85eead7..cfdc37c 100644 --- a/vendor/github.com/gookit/goutil/timex/template.go +++ b/vendor/github.com/gookit/goutil/timex/template.go @@ -6,15 +6,7 @@ import ( "github.com/gookit/goutil/strutil" ) -// some common datetime templates -const ( - DefaultTemplate = "Y-m-d H:i:s" - TemplateWithMs3 = "Y-m-d H:i:s.v" // end with ".000" - TemplateWithMs6 = "Y-m-d H:i:s.u" // end with ".000000" -) - -// char to Go date layout -// eg: "Y-m-d H:i:s" => "2006-01-02 15:04:05", +// char to Go date layout eg: "2006-01-02 15:04:05", // // # More see time.stdLongMonth // @@ -48,10 +40,10 @@ var charMap = map[byte][]byte{ 'S': []byte("05"), // 00 to 59 's': []byte("5"), // 0 to 59 // Time - 'a': []byte("pm"), // am or pm - 'A': []byte("PM"), // AM or PM - 'v': []byte("000"), // Milliseconds eg: 654 - 'u': []byte("000000"), // Microseconds eg: 654321 + 'a': []byte("pm"), // am or pm + 'A': []byte("PM"), // AM or PM + 'v': []byte(".000"), // Milliseconds eg: 654 + 'u': []byte(".000000"), // Microseconds eg: 654321 // Timezone 'e': []byte("MST"), // Timezone identifier. eg: UTC, GMT, Atlantic/Azores 'Z': []byte("Z07"), // Timezone abbreviation, if known; otherwise the GMT offset. Examples: EST, MDT, +05 @@ -64,7 +56,7 @@ var charMap = map[byte][]byte{ // ToLayout convert chars date template to Go date layout. // -// template chars see timex.charMap +// Chars see charMap func ToLayout(template string) string { if template == "" { return DefaultLayout diff --git a/vendor/github.com/gookit/goutil/timex/timex.go b/vendor/github.com/gookit/goutil/timex/timex.go index 8cbf4b8..8f029c7 100644 --- a/vendor/github.com/gookit/goutil/timex/timex.go +++ b/vendor/github.com/gookit/goutil/timex/timex.go @@ -7,7 +7,7 @@ package timex import ( "time" - "github.com/gookit/goutil/basefn" + "github.com/gookit/goutil/fmtutil" "github.com/gookit/goutil/strutil" ) @@ -19,18 +19,20 @@ const ( OneDaySec = 86400 OneWeekSec = 7 * 86400 - Microsecond = time.Microsecond - Millisecond = time.Millisecond - Second = time.Second OneMin = time.Minute - Minute = time.Minute OneHour = time.Hour - Hour = time.Hour OneDay = 24 * time.Hour - Day = OneDay OneWeek = 7 * 24 * time.Hour - Week = OneWeek + + DatetimeLayout = "2006-01-02 15:04:05" + DateOnlyLayout = "2006-01-02" + TimeOnlyLayout = "15:04:05" +) + +var ( + // DefaultLayout template for format time + DefaultLayout = "2006-01-02 15:04:05" ) // TimeX alias of Time @@ -85,12 +87,14 @@ func FromDate(s string, template ...string) (*Time, error) { return FromString(s) } -// FromString create from datetime string. see strutil.ToTime() +// FromString create from datetime string. +// see strutil.ToTime() func FromString(s string, layouts ...string) (*Time, error) { t, err := strutil.ToTime(s, layouts...) if err != nil { return nil, err } + return New(t), nil } @@ -129,25 +133,12 @@ func (t *Time) Datetime() string { } // TplFormat use input template format time to date. -// -// alias of DateFormat() func (t *Time) TplFormat(template string) string { return t.DateFormat(template) } // DateFormat use input template format time to date. -// -// Example: -// -// tn := timex.Now() -// tn.DateFormat("Y-m-d H:i:s") // Output: 2019-01-01 12:12:12 -// tn.DateFormat("Y-m-d H:i") // Output: 2019-01-01 12:12 -// tn.DateFormat("Y-m-d") // Output: 2019-01-01 -// tn.DateFormat("Y-m") // Output: 2019-01 -// tn.DateFormat("y-m-d") // Output: 19-01-01 -// tn.DateFormat("ymd") // Output: 190101 -// -// see ToLayout() for convert template to layout. +// see ToLayout() func (t *Time) DateFormat(template string) string { return t.Format(ToLayout(template)) } @@ -183,29 +174,6 @@ func (t *Time) DayAfter(day int) *Time { return t.AddDay(day) } -// AddDur some duration time -func (t *Time) AddDur(dur time.Duration) *Time { - return &Time{ - Time: t.Add(dur), - Layout: DefaultLayout, - } -} - -// AddString add duration time string. -// -// Example: -// -// tn := timex.Now() // example as "2019-01-01 12:12:12" -// nt := tn.AddString("1h") -// nt.Datetime() // Output: 2019-01-01 13:12:12 -func (t *Time) AddString(dur string) *Time { - d, err := ToDuration(dur) - if err != nil { - panic(err) - } - return t.AddDur(d) -} - // AddHour add some hour time func (t *Time) AddHour(hours int) *Time { return t.AddSeconds(hours * OneHourSec) @@ -325,14 +293,14 @@ func (t *Time) IsAfterUnix(ux int64) bool { return t.After(time.Unix(ux, 0)) } -// Timestamp value. alias of t.Unix() +// Timestamp value. alias t.Unix() func (t Time) Timestamp() int64 { return t.Unix() } // HowLongAgo format diff time to string. func (t Time) HowLongAgo(before time.Time) string { - return basefn.HowLongAgo(t.Unix() - before.Unix()) + return fmtutil.HowLongAgo(t.Unix() - before.Unix()) } // UnmarshalJSON implements the json.Unmarshaler interface. diff --git a/vendor/github.com/gookit/goutil/timex/util.go b/vendor/github.com/gookit/goutil/timex/util.go index d860341..64e9cc7 100644 --- a/vendor/github.com/gookit/goutil/timex/util.go +++ b/vendor/github.com/gookit/goutil/timex/util.go @@ -1,13 +1,9 @@ package timex import ( - "fmt" - "strings" "time" - "github.com/gookit/goutil/basefn" - "github.com/gookit/goutil/internal/comfunc" - "github.com/gookit/goutil/strutil" + "github.com/gookit/goutil/fmtutil" ) // NowUnix is short of time.Now().Unix() @@ -15,33 +11,48 @@ func NowUnix() int64 { return time.Now().Unix() } -// Format convert time to string use default layout -func Format(t time.Time) string { return t.Format(DefaultLayout) } +// SetLocalByName set local by tz name. eg: UTC, PRC +func SetLocalByName(tzName string) error { + location, err := time.LoadLocation(tzName) + if err != nil { + return err + } -// FormatBy given default layout -func FormatBy(t time.Time, layout string) string { return t.Format(layout) } + time.Local = location + return nil +} -// Date format time by given date template. see ToLayout() for template parse. -func Date(t time.Time, template ...string) string { return Datetime(t, template...) } +// Format use default layout +func Format(t time.Time) string { + return t.Format(DefaultLayout) +} + +// FormatBy given default layout +func FormatBy(t time.Time, layout string) string { + return t.Format(layout) +} -// Datetime convert time to string use template. see ToLayout() for template parse. -func Datetime(t time.Time, template ...string) string { - return FormatByTpl(t, basefn.FirstOr(template, DefaultTemplate)) +// Date format time by given date template. +// see ToLayout() +func Date(t time.Time, template string) string { + return FormatByTpl(t, template) } -// DateFormat format time by given date template. see ToLayout() +// DateFormat format time by given date template. +// see ToLayout() func DateFormat(t time.Time, template string) string { return FormatByTpl(t, template) } -// FormatByTpl format time by given date template. see ToLayout() +// FormatByTpl format time by given date template. +// see ToLayout() func FormatByTpl(t time.Time, template string) string { return t.Format(ToLayout(template)) } // FormatUnix time seconds use default layout -func FormatUnix(sec int64, layout ...string) string { - return time.Unix(sec, 0).Format(basefn.FirstOr(layout, DefaultLayout)) +func FormatUnix(sec int64) string { + return time.Unix(sec, 0).Format(DefaultLayout) } // FormatUnixBy format time seconds use given layout @@ -51,246 +62,101 @@ func FormatUnixBy(sec int64, layout string) string { // FormatUnixByTpl format time seconds use given date template. // see ToLayout() -func FormatUnixByTpl(sec int64, template ...string) string { - layout := ToLayout(basefn.FirstOr(template, DefaultTemplate)) - return time.Unix(sec, 0).Format(layout) +func FormatUnixByTpl(sec int64, template string) string { + return time.Unix(sec, 0).Format(ToLayout(template)) } -// HowLongAgo format given timestamp to string. -func HowLongAgo(sec int64) string { - return basefn.HowLongAgo(sec) +// NowAddDay add some day time from now +func NowAddDay(day int) time.Time { + return time.Now().AddDate(0, 0, day) } -// ToTime parse a datetime string. alias of strutil.ToTime() -func ToTime(s string, layouts ...string) (time.Time, error) { - return strutil.ToTime(s, layouts...) +// NowAddHour add some hour time from now +func NowAddHour(hour int) time.Time { + return time.Now().Add(time.Duration(hour) * OneHour) } -// ToDur parse a duration string. alias of ToDuration() -func ToDur(s string) (time.Duration, error) { return ToDuration(s) } - -// ToDuration parses a duration string. such as "300ms", "-1.5h" or "2h45m". -// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". -func ToDuration(s string) (time.Duration, error) { - return comfunc.ToDuration(s) +// NowAddMinutes add some minutes time from now +func NowAddMinutes(minutes int) time.Time { + return time.Now().Add(time.Duration(minutes) * OneMin) } -// IsDuration check the string is a valid duration string. alias of basefn.IsDuration() -func IsDuration(s string) bool { return comfunc.IsDuration(s) } - -// TryToTime parse a date string or duration string to time.Time. -// -// if s is empty, return zero time. -func TryToTime(s string, bt time.Time) (time.Time, error) { - if s == "" { - return ZeroTime, nil - } - if s == "now" { - return time.Now(), nil - } - - // if s is a duration string, add it to bt(base time) - if IsDuration(s) { - dur, err := ToDuration(s) - if err != nil { - return ZeroTime, err - } - return bt.Add(dur), nil - } - - // as a date string, parse it to time.Time - return ToTime(s) +// NowAddSeconds add some seconds time from now +func NowAddSeconds(seconds int) time.Time { + return time.Now().Add(time.Duration(seconds) * time.Second) } -// InRange check the dst time is in the range of start and end. -// -// if start is zero, only check dst < end, -// if end is zero, only check dst > start. -func InRange(dst, start, end time.Time) bool { - if start.IsZero() && end.IsZero() { - return false - } - - if start.IsZero() { - return dst.Before(end) - } - if end.IsZero() { - return dst.After(start) - } - - return dst.After(start) && dst.Before(end) +// NowHourStart time +func NowHourStart() time.Time { + return HourStart(time.Now()) } -// ParseRangeOpt is the option for ParseRange -type ParseRangeOpt struct { - // BaseTime is the base time for relative time string. - // if is zero, use time.Now() as base time. - BaseTime time.Time - // OneAsEnd is the option for one time range. - // - False: "-1h" => "-1h,0"; "1h" => "+1h, feature" - // - True: "-1h" => "zero,-1h"; "1h" => "zero,1h" - OneAsEnd bool - // AutoSort is the option for sort the time range. - AutoSort bool - // SepChar is the separator char for time range string. default is '~' - SepChar byte - // BeforeFn hook for before parse time string. - BeforeFn func(string) string - // KeywordFn is the function for parse keyword time string. - KeywordFn func(string) (time.Time, time.Time, error) +// NowHourEnd time +func NowHourEnd() time.Time { + return HourEnd(time.Now()) } -func ensureOpt(opt *ParseRangeOpt) *ParseRangeOpt { - if opt == nil { - opt = &ParseRangeOpt{BaseTime: time.Now(), SepChar: '~'} - } else { - if opt.BaseTime.IsZero() { - opt.BaseTime = time.Now() - } - if opt.SepChar == 0 { - opt.SepChar = '~' - } - } - - return opt +// AddDay add some day time for given time +func AddDay(t time.Time, day int) time.Time { + return t.AddDate(0, 0, day) } -// ParseRange parse time range expression string to time.Time range. -// - "0" is alias of "now" -// -// Expression format: -// -// "-5h~-1h" => 5 hours ago to 1 hour ago -// "1h~5h" => 1 hour after to 5 hours after -// "-1h~1h" => 1 hour ago to 1 hour after -// "-1h" => 1 hour ago to feature. eq "-1h," -// "-1h~0" => 1 hour ago to now. -// "< -1h" OR "~-1h" => 1 hour ago. eq ",-1h" -// "> 1h" OR "1h" => 1 hour after to feature -// // keyword: now, today, yesterday, tomorrow -// "today" => today start to today end -// "yesterday" => yesterday start to yesterday end -// "tomorrow" => tomorrow start to tomorrow end -// -// Usage: -// -// start, end, err := ParseRange("-1h~1h", nil) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Println(start, end) -func ParseRange(expr string, opt *ParseRangeOpt) (start, end time.Time, err error) { - opt = ensureOpt(opt) - expr = strings.TrimSpace(expr) - if expr == "" { - err = fmt.Errorf("invalid time range expr %q", expr) - return - } - - // parse time range. eg: "5h~1h" - if strings.IndexByte(expr, opt.SepChar) > -1 { - s1, s2 := strutil.TrimCut(expr, string(opt.SepChar)) - if s1 == "" && s2 == "" { - err = fmt.Errorf("invalid time range expr: %s", expr) - return - } - - if s1 != "" { - start, err = TryToTime(s1, opt.BaseTime) - if err != nil { - return - } - } +// AddHour add some hour time for given time +func AddHour(t time.Time, hour int) time.Time { + return t.Add(time.Duration(hour) * OneHour) +} - if s2 != "" { - end, err = TryToTime(s2, opt.BaseTime) - // auto sort range time - if opt.AutoSort && err == nil { - if !start.IsZero() && start.After(end) { - start, end = end, start - } - } - } +// AddMinutes add some minutes time for given time +func AddMinutes(t time.Time, minutes int) time.Time { + return t.Add(time.Duration(minutes) * OneMin) +} - return - } +// AddSeconds add some seconds time for given time +func AddSeconds(t time.Time, seconds int) time.Time { + return t.Add(time.Duration(seconds) * time.Second) +} - // single time. eg: "5h", "1h", "-1h" - if IsDuration(expr) { - tt, err1 := TryToTime(expr, opt.BaseTime) - if err1 != nil { - err = err1 - return - } +// HourStart time for given time +func HourStart(t time.Time) time.Time { + y, m, d := t.Date() + return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location()) +} - if opt.OneAsEnd { - end = tt - } else { - start = tt - } - return - } +// HourEnd time for given time +func HourEnd(t time.Time) time.Time { + y, m, d := t.Date() + return time.Date(y, m, d, t.Hour(), 59, 59, int(time.Second-time.Nanosecond), t.Location()) +} - // with compare operator. eg: "<1h", ">1h" - if expr[0] == '<' || expr[0] == '>' { - tt, err1 := TryToTime(strings.Trim(expr[1:], " ="), opt.BaseTime) - if err1 != nil { - err = err1 - return - } +// DayStart time for given time +func DayStart(t time.Time) time.Time { + y, m, d := t.Date() + return time.Date(y, m, d, 0, 0, 0, 0, t.Location()) +} - if expr[0] == '<' { - end = tt - } else { - start = tt - } - return - } +// DayEnd time for given time +func DayEnd(t time.Time) time.Time { + y, m, d := t.Date() + return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location()) +} - // parse keyword time string - switch expr { - case "0": - if opt.OneAsEnd { - end = opt.BaseTime - } else { - start = opt.BaseTime - } - case "now": - if opt.OneAsEnd { - end = time.Now() - } else { - start = time.Now() - } - case "today": - start = DayStart(opt.BaseTime) - end = DayEnd(opt.BaseTime) - case "yesterday": - yd := opt.BaseTime.AddDate(0, 0, -1) - start = DayStart(yd) - end = DayEnd(yd) - case "tomorrow": - td := opt.BaseTime.AddDate(0, 0, 1) - start = DayStart(td) - end = DayEnd(td) - default: - // single datetime. eg: "2019-01-01" - tt, err1 := TryToTime(expr, opt.BaseTime) - if err1 != nil { - if opt.KeywordFn == nil { - err = fmt.Errorf("invalid keyword time string: %s", expr) - return - } +// TodayStart time +func TodayStart() time.Time { + return DayStart(time.Now()) +} - start, end, err = opt.KeywordFn(expr) - return - } +// TodayEnd time +func TodayEnd() time.Time { + return DayEnd(time.Now()) +} - if opt.OneAsEnd { - end = tt - } else { - start = tt - } - } +// HowLongAgo format given timestamp to string. +func HowLongAgo(sec int64) string { + return fmtutil.HowLongAgo(sec) +} - return +// ToDuration parses a duration string. such as "300ms", "-1.5h" or "2h45m". +// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". +func ToDuration(s string) (time.Duration, error) { + return time.ParseDuration(s) } diff --git a/vendor/github.com/faiface/beep/LICENSE b/vendor/github.com/gopxl/beep/LICENSE similarity index 100% rename from vendor/github.com/faiface/beep/LICENSE rename to vendor/github.com/gopxl/beep/LICENSE diff --git a/vendor/github.com/gopxl/beep/README.md b/vendor/github.com/gopxl/beep/README.md new file mode 100644 index 0000000..195fbcc --- /dev/null +++ b/vendor/github.com/gopxl/beep/README.md @@ -0,0 +1,59 @@ +# Beep + +[![GoDoc](https://godoc.org/github.com/gopxl/beep?status.svg)](https://godoc.org/github.com/gopxl/beep) +[![Go build status](https://github.com/gopxl/beep/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/gopxl/beep/actions/workflows/go.yml?query=branch%3Amain) +[![Coverage Status](https://coveralls.io/repos/github/gopxl/beep/badge.svg?branch=main)](https://coveralls.io/github/gopxl/beep?branch=main) +[![Go Report Card](https://goreportcard.com/badge/github.com/gopxl/beep)](https://goreportcard.com/report/github.com/gopxl/beep) +[![Discord Chat](https://img.shields.io/discord/1158461233121468496)](https://discord.gg/erpa32cB) + + +A little package that brings sound to any Go application. Suitable for playback and audio-processing. + +``` +go get -u github.com/gopxl/beep +``` + +## Features + +Beep is built on top of its [Streamer](https://godoc.org/github.com/gopxl/beep#Streamer) interface, which is like [io.Reader](https://golang.org/pkg/io/#Reader), but for audio. It was one of the best design decisions I've ever made and it enabled all the rest of the features to naturally come together with not much code. + +- **Decode and play WAV, MP3, OGG, and FLAC.** +- **Encode and save WAV.** +- **Very simple API.** Limiting the support to stereo (two channel) audio made it possible to simplify the architecture and the API. +- **Rich library of compositors and effects.** Loop, pause/resume, change volume, mix, sequence, change playback speed, and more. +- **Easily create new effects.** With the `Streamer` interface, creating new effects is very easy. +- **Generate completely own artificial sounds.** Again, the `Streamer` interface enables easy sound generation. +- **Very small codebase.** The core is just ~1K LOC. + +## Tutorial + +The [Wiki](https://github.com/gopxl/beep/wiki) contains a handful of tutorials for you to get started. They teach the fundamentals and advanced topics alike. **Read them especially if you call `speaker.Init` every time you play something.** + +- [Hello, Beep!](https://github.com/gopxl/beep/wiki/Hello,-Beep!) +- [Composing and controlling](https://github.com/gopxl/beep/wiki/Composing-and-controlling) +- [To buffer, or not to buffer, that is the question](https://github.com/gopxl/beep/wiki/To-buffer,-or-not-to-buffer,-that-is-the-question) +- [Making own streamers](https://github.com/gopxl/beep/wiki/Making-own-streamers) + +## Examples + +| [Speedy Player](https://github.com/gopxl/beep/tree/main/examples/speedy-player) | [Doppler Stereo Room](https://github.com/gopxl/beep/tree/main/examples/doppler-stereo-room) | +|-------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| +| ![Speedy Player](https://github.com/gopxl/beep/blob/main/examples/speedy-player/screenshot.png) | ![Doppler Stereo Room](https://github.com/gopxl/beep/blob/main/examples/doppler-stereo-room/screenshot.png) | + +## Dependencies + +For playback, Beep uses [Oto](https://github.com/hajimehoshi/oto) under the hood. Check its requirements to see what you need to install for building your application. + +Running an already built application should work with no extra dependencies. + +## License + +[MIT](https://github.com/gopxl/beep/blob/main/LICENSE) + +## Related projects + +- [Microphone support for Beep (a wrapper around PortAudio)](https://github.com/MarkKremer/microphone) + +## Projects using Beep +- [retro](https://github.com/Malwarize/retro) +- [Mifasol music server](https://github.com/jypelle/mifasol) diff --git a/vendor/github.com/faiface/beep/buffer.go b/vendor/github.com/gopxl/beep/buffer.go similarity index 100% rename from vendor/github.com/faiface/beep/buffer.go rename to vendor/github.com/gopxl/beep/buffer.go diff --git a/vendor/github.com/faiface/beep/compositors.go b/vendor/github.com/gopxl/beep/compositors.go similarity index 100% rename from vendor/github.com/faiface/beep/compositors.go rename to vendor/github.com/gopxl/beep/compositors.go diff --git a/vendor/github.com/faiface/beep/ctrl.go b/vendor/github.com/gopxl/beep/ctrl.go similarity index 84% rename from vendor/github.com/faiface/beep/ctrl.go rename to vendor/github.com/gopxl/beep/ctrl.go index 88fd8bc..6dc7e30 100644 --- a/vendor/github.com/faiface/beep/ctrl.go +++ b/vendor/github.com/gopxl/beep/ctrl.go @@ -4,25 +4,25 @@ package beep // // Wrap a Streamer in a Ctrl. // -// ctrl := &beep.Ctrl{Streamer: s} +// ctrl := &beep.Ctrl{Streamer: s} // // Then, we can pause the streaming (this will cause Ctrl to stream silence). // -// ctrl.Paused = true +// ctrl.Paused = true // // To completely stop a Ctrl before the wrapped Streamer is drained, just set the wrapped Streamer // to nil. // -// ctrl.Streamer = nil +// ctrl.Streamer = nil // // If you're playing a Streamer wrapped in a Ctrl through the speaker, you need to lock and unlock // the speaker when modifying the Ctrl to avoid race conditions. // -// speaker.Play(ctrl) -// // ... -// speaker.Lock() -// ctrl.Paused = true -// speaker.Unlock() +// speaker.Play(ctrl) +// // ... +// speaker.Lock() +// ctrl.Paused = true +// speaker.Unlock() type Ctrl struct { Streamer Streamer Paused bool diff --git a/vendor/github.com/faiface/beep/effects/doc.go b/vendor/github.com/gopxl/beep/effects/doc.go similarity index 100% rename from vendor/github.com/faiface/beep/effects/doc.go rename to vendor/github.com/gopxl/beep/effects/doc.go diff --git a/vendor/github.com/faiface/beep/effects/doppler.go b/vendor/github.com/gopxl/beep/effects/doppler.go similarity index 82% rename from vendor/github.com/faiface/beep/effects/doppler.go rename to vendor/github.com/gopxl/beep/effects/doppler.go index 6762a07..8aa6fcf 100644 --- a/vendor/github.com/faiface/beep/effects/doppler.go +++ b/vendor/github.com/gopxl/beep/effects/doppler.go @@ -1,6 +1,6 @@ package effects -import "github.com/faiface/beep" +import "github.com/gopxl/beep" // Doppler simulates a "sound at a distance". If the sound starts at a far distance, // it'll take some time to reach the ears of the listener. @@ -11,11 +11,11 @@ import "github.com/faiface/beep" // // The arguments are: // -// quality: the quality of the underlying resampler (1 or 2 is usually okay) -// samplesPerMeter: sample rate / speed of sound -// s: the source streamer -// distance: a function to calculate the current distance; takes number of -// samples Doppler wants to stream at the moment +// quality: the quality of the underlying resampler (1 or 2 is usually okay) +// samplesPerMeter: sample rate / speed of sound +// s: the source streamer +// distance: a function to calculate the current distance; takes number of +// samples Doppler wants to stream at the moment // // This function is experimental and may change any time! func Doppler(quality int, samplesPerMeter float64, s beep.Streamer, distance func(delta int) float64) beep.Streamer { diff --git a/vendor/github.com/faiface/beep/effects/equalizer.go b/vendor/github.com/gopxl/beep/effects/equalizer.go similarity index 99% rename from vendor/github.com/faiface/beep/effects/equalizer.go rename to vendor/github.com/gopxl/beep/effects/equalizer.go index cf95073..fd49e6b 100644 --- a/vendor/github.com/faiface/beep/effects/equalizer.go +++ b/vendor/github.com/gopxl/beep/effects/equalizer.go @@ -3,7 +3,7 @@ package effects import ( "math" - "github.com/faiface/beep" + "github.com/gopxl/beep" ) type ( diff --git a/vendor/github.com/faiface/beep/effects/gain.go b/vendor/github.com/gopxl/beep/effects/gain.go similarity index 95% rename from vendor/github.com/faiface/beep/effects/gain.go rename to vendor/github.com/gopxl/beep/effects/gain.go index 148cbee..d07a4d7 100644 --- a/vendor/github.com/faiface/beep/effects/gain.go +++ b/vendor/github.com/gopxl/beep/effects/gain.go @@ -1,6 +1,6 @@ package effects -import "github.com/faiface/beep" +import "github.com/gopxl/beep" // Gain amplifies the wrapped Streamer. The output of the wrapped Streamer gets multiplied by // 1+Gain. diff --git a/vendor/github.com/faiface/beep/effects/mono.go b/vendor/github.com/gopxl/beep/effects/mono.go similarity index 94% rename from vendor/github.com/faiface/beep/effects/mono.go rename to vendor/github.com/gopxl/beep/effects/mono.go index 6d7e48e..617c1df 100644 --- a/vendor/github.com/faiface/beep/effects/mono.go +++ b/vendor/github.com/gopxl/beep/effects/mono.go @@ -1,6 +1,6 @@ package effects -import "github.com/faiface/beep" +import "github.com/gopxl/beep" // Mono converts the wrapped Streamer to a mono buffer // by downmixing the left and right channels together. diff --git a/vendor/github.com/faiface/beep/effects/pan.go b/vendor/github.com/gopxl/beep/effects/pan.go similarity index 96% rename from vendor/github.com/faiface/beep/effects/pan.go rename to vendor/github.com/gopxl/beep/effects/pan.go index ccf95c4..b9cd320 100644 --- a/vendor/github.com/faiface/beep/effects/pan.go +++ b/vendor/github.com/gopxl/beep/effects/pan.go @@ -1,6 +1,6 @@ package effects -import "github.com/faiface/beep" +import "github.com/gopxl/beep" // Pan balances the wrapped Streamer between the left and the right channel. The Pan field value of // -1 means that both original channels go through the left channel. The value of +1 means the same diff --git a/vendor/github.com/faiface/beep/effects/swap.go b/vendor/github.com/gopxl/beep/effects/swap.go similarity index 94% rename from vendor/github.com/faiface/beep/effects/swap.go rename to vendor/github.com/gopxl/beep/effects/swap.go index 6446adb..897a1a2 100644 --- a/vendor/github.com/faiface/beep/effects/swap.go +++ b/vendor/github.com/gopxl/beep/effects/swap.go @@ -1,6 +1,6 @@ package effects -import "github.com/faiface/beep" +import "github.com/gopxl/beep" // Swap swaps the left and right channel of the wrapped Streamer. // diff --git a/vendor/github.com/gopxl/beep/effects/transition.go b/vendor/github.com/gopxl/beep/effects/transition.go new file mode 100644 index 0000000..a0af349 --- /dev/null +++ b/vendor/github.com/gopxl/beep/effects/transition.go @@ -0,0 +1,80 @@ +package effects + +import ( + "math" + + "github.com/gopxl/beep" +) + +// TransitionFunc defines a function used in a transition to describe the progression curve +// from one value to the next. The input 'percent' always ranges from 0.0 to 1.0, where 0.0 +// represents the starting point and 1.0 represents the end point of the transition. +// +// The returned value from TransitionFunc is expected to be in the normalized range of [0.0, 1.0]. +// However, it may exceed this range, providing flexibility to generate curves with momentum. +// The Transition() function then maps this normalized output to the actual desired range. +type TransitionFunc func(percent float64) float64 + +// TransitionLinear transitions the gain linearly from the start to end value. +func TransitionLinear(percent float64) float64 { + return percent +} + +// TransitionEqualPower transitions the gain of a streamer in such a way that the total perceived volume stays +// constant if mixed together with another streamer doing the inverse transition. +// +// See https://www.oreilly.com/library/view/web-audio-api/9781449332679/ch03.html#s03_2 for more information. +func TransitionEqualPower(percent float64) float64 { + return math.Cos((1.0 - percent) * 0.5 * math.Pi) +} + +// Transition gradually adjusts the gain of the source streamer 's' from 'startGain' to 'endGain' +// over the entire duration of the stream, defined by the number of samples 'len'. +// The transition is defined by the provided 'transitionFunc' function, which determines the +// gain at each point during the transition. +func Transition(s beep.Streamer, len int, startGain, endGain float64, transitionfunc TransitionFunc) *TransitionStreamer { + return &TransitionStreamer{ + s: s, + len: len, + startGain: startGain, + endGain: endGain, + transitionFunc: transitionfunc, + } +} + +type TransitionStreamer struct { + s beep.Streamer + pos int + len int + startGain, endGain float64 + transitionFunc TransitionFunc +} + +// Stream fills samples with the gain-adjusted samples of the source streamer. +func (t *TransitionStreamer) Stream(samples [][2]float64) (n int, ok bool) { + n, ok = t.s.Stream(samples) + + for i := 0; i < n; i++ { + pos := t.pos + i + progress := float64(pos) / float64(t.len) + if progress < 0 { + progress = 0 + } else if progress > 1 { + progress = 1 + } + value := t.transitionFunc(progress) + gain := t.startGain + (t.endGain-t.startGain)*value + + samples[i][0] *= gain + samples[i][1] *= gain + } + + t.pos += n + + return +} + +// Err propagates the original Streamer's errors. +func (t *TransitionStreamer) Err() error { + return t.s.Err() +} diff --git a/vendor/github.com/faiface/beep/effects/volume.go b/vendor/github.com/gopxl/beep/effects/volume.go similarity index 97% rename from vendor/github.com/faiface/beep/effects/volume.go rename to vendor/github.com/gopxl/beep/effects/volume.go index 2cd53fa..3f62647 100644 --- a/vendor/github.com/faiface/beep/effects/volume.go +++ b/vendor/github.com/gopxl/beep/effects/volume.go @@ -3,7 +3,7 @@ package effects import ( "math" - "github.com/faiface/beep" + "github.com/gopxl/beep" ) // Volume adjusts the volume of the wrapped Streamer in a human-natural way. Human's perception of diff --git a/vendor/github.com/faiface/beep/interface.go b/vendor/github.com/gopxl/beep/interface.go similarity index 88% rename from vendor/github.com/faiface/beep/interface.go rename to vendor/github.com/gopxl/beep/interface.go index 8e90919..93ab4f1 100644 --- a/vendor/github.com/faiface/beep/interface.go +++ b/vendor/github.com/gopxl/beep/interface.go @@ -14,11 +14,11 @@ type Streamer interface { // samples will be produced, it returns 0 and false. Stream must not touch any samples // outside samples[:n]. // - // There are 3 valid return pattterns of the Stream method: + // There are 3 valid return patterns of the Stream method: // // 1. n == len(samples) && ok // - // Stream streamed all of the requested samples. Cases 1, 2 and 3 may occur in the following + // Stream streamed all the requested samples. Cases 1, 2 and 3 may occur in the following // calls. // // 2. 0 < n && n < len(samples) && ok @@ -86,13 +86,13 @@ type StreamSeekCloser interface { // // Example: // -// noise := StreamerFunc(func(samples [][2]float64) (n int, ok bool) { -// for i := range samples { -// samples[i][0] = rand.Float64()*2 - 1 -// samples[i][1] = rand.Float64()*2 - 1 -// } -// return len(samples), true -// }) +// noise := StreamerFunc(func(samples [][2]float64) (n int, ok bool) { +// for i := range samples { +// samples[i][0] = rand.Float64()*2 - 1 +// samples[i][1] = rand.Float64()*2 - 1 +// } +// return len(samples), true +// }) type StreamerFunc func(samples [][2]float64) (n int, ok bool) // Stream calls the wrapped streaming function. diff --git a/vendor/github.com/faiface/beep/mixer.go b/vendor/github.com/gopxl/beep/mixer.go similarity index 100% rename from vendor/github.com/faiface/beep/mixer.go rename to vendor/github.com/gopxl/beep/mixer.go diff --git a/vendor/github.com/faiface/beep/mp3/decode.go b/vendor/github.com/gopxl/beep/mp3/decode.go similarity index 98% rename from vendor/github.com/faiface/beep/mp3/decode.go rename to vendor/github.com/gopxl/beep/mp3/decode.go index a7e213a..1a10b15 100644 --- a/vendor/github.com/faiface/beep/mp3/decode.go +++ b/vendor/github.com/gopxl/beep/mp3/decode.go @@ -5,7 +5,7 @@ import ( "fmt" "io" - "github.com/faiface/beep" + "github.com/gopxl/beep" gomp3 "github.com/hajimehoshi/go-mp3" "github.com/pkg/errors" ) diff --git a/vendor/github.com/faiface/beep/resample.go b/vendor/github.com/gopxl/beep/resample.go similarity index 85% rename from vendor/github.com/faiface/beep/resample.go rename to vendor/github.com/gopxl/beep/resample.go index 902a123..28d494f 100644 --- a/vendor/github.com/faiface/beep/resample.go +++ b/vendor/github.com/gopxl/beep/resample.go @@ -1,6 +1,9 @@ package beep -import "fmt" +import ( + "fmt" + "math" +) // Resample takes a Streamer which is assumed to stream at the old sample rate and returns a // Streamer, which streams the data from the original Streamer resampled to the new sample rate. @@ -10,23 +13,23 @@ import "fmt" // Streamer which stream at a different sample rate will lead to a changed speed and pitch of the // playback. // -// sr := beep.SampleRate(48000) -// speaker.Init(sr, sr.N(time.Second/2)) -// speaker.Play(beep.Resample(3, format.SampleRate, sr, s)) +// sr := beep.SampleRate(48000) +// speaker.Init(sr, sr.N(time.Second/2)) +// speaker.Play(beep.Resample(3, format.SampleRate, sr, s)) // -// In the example, the original sample rate of the source if format.SampleRate. We want to play it -// at the speaker's native sample rate and thus we need to resample. +// In the example above, the original sample rate of the source is format.SampleRate. We want to play +// it at the speaker's native sample rate and thus we need to resample. // // The quality argument specifies the quality of the resampling process. Higher quality implies // worse performance. Values below 1 or above 64 are invalid and Resample will panic. Here's a table // for deciding which quality to pick. // -// quality | use case -// --------|--------- -// 1 | very high performance, on-the-fly resampling, low quality -// 3-4 | good performance, on-the-fly resampling, good quality -// 6 | higher CPU usage, usually not suitable for on-the-fly resampling, very good quality -// >6 | even higher CPU usage, for offline resampling, very good quality +// quality | use case +// --------|--------- +// 1 | very high performance, on-the-fly resampling, low quality +// 3-4 | good performance, on-the-fly resampling, good quality +// 6 | higher CPU usage, usually not suitable for on-the-fly resampling, very good quality +// >6 | even higher CPU usage, for offline resampling, very good quality // // Sane quality values are usually below 16. Higher values will consume too much CPU, giving // negligible quality improvements. @@ -44,6 +47,9 @@ func ResampleRatio(quality int, ratio float64, s Streamer) *Resampler { if quality < 1 || 64 < quality { panic(fmt.Errorf("resample: invalid quality: %d", quality)) } + if math.IsInf(ratio, 0) || math.IsNaN(ratio) { + panic(fmt.Errorf("resample: invalid ratio: %f", ratio)) + } return &Resampler{ s: s, ratio: ratio, @@ -148,6 +154,9 @@ func (r *Resampler) Ratio() float64 { // SetRatio sets the resampling ratio. This does not cause any glitches in the stream. func (r *Resampler) SetRatio(ratio float64) { + if math.IsInf(ratio, 0) || math.IsNaN(ratio) { + panic(fmt.Errorf("resample: invalid ratio: %f", ratio)) + } r.pos = int(float64(r.pos) * r.ratio / ratio) r.ratio = ratio } diff --git a/vendor/github.com/gopxl/beep/speaker/speaker.go b/vendor/github.com/gopxl/beep/speaker/speaker.go new file mode 100644 index 0000000..8103b7f --- /dev/null +++ b/vendor/github.com/gopxl/beep/speaker/speaker.go @@ -0,0 +1,212 @@ +// Package speaker implements playback of beep.Streamer values through physical speakers. +package speaker + +import ( + "io" + "sync" + "time" + + "github.com/ebitengine/oto/v3" + "github.com/pkg/errors" + + "github.com/gopxl/beep" +) + +const channelCount = 2 +const bitDepthInBytes = 2 +const bytesPerSample = bitDepthInBytes * channelCount +const otoFormat = oto.FormatSignedInt16LE + +var ( + mu sync.Mutex + mixer beep.Mixer + context *oto.Context + player *oto.Player + + bufferDuration time.Duration +) + +// Init initializes audio playback through speaker. Must be called before using this package. +// +// The bufferSize argument specifies the number of samples of the speaker's buffer. Bigger +// bufferSize means lower CPU usage and more reliable playback. Lower bufferSize means better +// responsiveness and less delay. +func Init(sampleRate beep.SampleRate, bufferSize int) error { + if context != nil { + return errors.New("speaker cannot be initialized more than once") + } + + mixer = beep.Mixer{} + + // We split the total amount of buffer size between the driver and the player. + // This seems to be a decent ratio on my machine, but it may have different + // results on other OS's because of different underlying implementations. + // Both buffers try to keep themselves filled, so the total buffered + // number of samples should be some number less than bufferSize. + driverBufferSize := bufferSize / 2 + playerBufferSize := bufferSize / 2 + + var err error + var readyChan chan struct{} + context, readyChan, err = oto.NewContext(&oto.NewContextOptions{ + SampleRate: int(sampleRate), + ChannelCount: channelCount, + Format: otoFormat, + BufferSize: sampleRate.D(driverBufferSize), + }) + if err != nil { + return errors.Wrap(err, "failed to initialize speaker") + } + <-readyChan + + player = context.NewPlayer(newReaderFromStreamer(&mixer)) + player.SetBufferSize(playerBufferSize * bytesPerSample) + player.Play() + + bufferDuration = sampleRate.D(bufferSize) + + return nil +} + +// Close closes audio playback. However, the underlying driver context keeps existing, because +// closing it isn't supported (https://github.com/hajimehoshi/oto/issues/149). In most cases, +// there is certainly no need to call Close even when the program doesn't play anymore, because +// in properly set systems, the default mixer handles multiple concurrent processes. +func Close() { + if player != nil { + player.Close() + player = nil + Clear() + } +} + +// Lock locks the speaker. While locked, speaker won't pull new data from the playing Streamers. Lock +// if you want to modify any currently playing Streamers to avoid race conditions. +// +// Always lock speaker for as little time as possible, to avoid playback glitches. +func Lock() { + mu.Lock() +} + +// Unlock unlocks the speaker. Call after modifying any currently playing Streamer. +func Unlock() { + mu.Unlock() +} + +// Play starts playing all provided Streamers through the speaker. +func Play(s ...beep.Streamer) { + mu.Lock() + mixer.Add(s...) + mu.Unlock() +} + +// PlayAndWait plays all provided Streamers through the speaker and waits until they have all finished playing. +func PlayAndWait(s ...beep.Streamer) { + mu.Lock() + var wg sync.WaitGroup + wg.Add(len(s)) + for _, e := range s { + mixer.Add(beep.Seq(e, beep.Callback(func() { + wg.Done() + }))) + } + mu.Unlock() + + // Wait for the streamers to drain. + wg.Wait() + + // Wait the expected time it takes for the samples to reach the driver. + time.Sleep(bufferDuration) +} + +// Suspend suspends the entire audio play. +// +// This function is intended to save resources when no audio is playing. +// To suspend individual streams, use the beep.Ctrl. +func Suspend() error { + err := context.Suspend() + if err != nil { + return errors.Wrap(err, "failed to suspend the speaker") + } + return nil +} + +// Resume resumes the entire audio play, which was suspended by Suspend. +func Resume() error { + err := context.Resume() + if err != nil { + return errors.Wrap(err, "failed to resume the speaker") + } + return nil +} + +// Clear removes all currently playing Streamers from the speaker. +// Previously buffered samples may still be played. +func Clear() { + mu.Lock() + mixer.Clear() + mu.Unlock() +} + +// sampleReader is a wrapper for beep.Streamer to implement io.Reader. +type sampleReader struct { + s beep.Streamer + buf [][2]float64 +} + +func newReaderFromStreamer(s beep.Streamer) *sampleReader { + return &sampleReader{ + s: s, + } +} + +// Read pulls samples from the streamer and fills buf with the encoded +// samples. Read expects the size of buf be divisible by the length +// of a sample (= channel count * bit depth in bytes). +func (s *sampleReader) Read(buf []byte) (n int, err error) { + // Read samples from streamer + if len(buf)%bytesPerSample != 0 { + return 0, errors.New("requested number of bytes do not align with the samples") + } + ns := len(buf) / bytesPerSample + if len(s.buf) < ns { + s.buf = make([][2]float64, ns) + } + ns, ok := s.stream(s.buf[:ns]) + if !ok { + if s.s.Err() != nil { + return 0, errors.Wrap(s.s.Err(), "streamer returned error when requesting samples") + } + if ns == 0 { + return 0, io.EOF + } + } + + // Convert samples to bytes + for i := range s.buf[:ns] { + for c := range s.buf[i] { + val := s.buf[i][c] + if val < -1 { + val = -1 + } + if val > +1 { + val = +1 + } + valInt16 := int16(val * (1<<15 - 1)) + low := byte(valInt16) + high := byte(valInt16 >> 8) + buf[i*bytesPerSample+c*bitDepthInBytes+0] = low + buf[i*bytesPerSample+c*bitDepthInBytes+1] = high + } + } + + return ns * bytesPerSample, nil +} + +// stream pull samples from the streamer while preventing concurrency +// problems by locking the global mixer. +func (s *sampleReader) stream(samples [][2]float64) (n int, ok bool) { + mu.Lock() + defer mu.Unlock() + return s.s.Stream(samples) +} diff --git a/vendor/github.com/faiface/beep/streamers.go b/vendor/github.com/gopxl/beep/streamers.go similarity index 95% rename from vendor/github.com/faiface/beep/streamers.go rename to vendor/github.com/gopxl/beep/streamers.go index 213507f..34b8e6b 100644 --- a/vendor/github.com/faiface/beep/streamers.go +++ b/vendor/github.com/gopxl/beep/streamers.go @@ -2,6 +2,8 @@ package beep // Silence returns a Streamer which streams num samples of silence. If num is negative, silence is // streamed forever. +// +// Deprecated: beep.Silence has been moved to generators.Silence func Silence(num int) Streamer { return StreamerFunc(func(samples [][2]float64) (n int, ok bool) { if num == 0 { diff --git a/vendor/github.com/faiface/beep/vorbis/decode.go b/vendor/github.com/gopxl/beep/vorbis/decode.go similarity index 81% rename from vendor/github.com/faiface/beep/vorbis/decode.go rename to vendor/github.com/gopxl/beep/vorbis/decode.go index f5c34f2..7444813 100644 --- a/vendor/github.com/faiface/beep/vorbis/decode.go +++ b/vendor/github.com/gopxl/beep/vorbis/decode.go @@ -4,14 +4,13 @@ package vorbis import ( "io" - "github.com/faiface/beep" + "github.com/gopxl/beep" "github.com/jfreymuth/oggvorbis" "github.com/pkg/errors" ) const ( - govorbisNumChannels = 2 - govorbisPrecision = 2 + govorbisPrecision = 2 ) // Decode takes a ReadCloser containing audio data in ogg/vorbis format and returns a StreamSeekCloser, @@ -31,7 +30,7 @@ func Decode(rc io.ReadCloser) (s beep.StreamSeekCloser, format beep.Format, err } format = beep.Format{ SampleRate: beep.SampleRate(d.SampleRate()), - NumChannels: govorbisNumChannels, + NumChannels: d.Channels(), Precision: govorbisPrecision, } return &decoder{rc, d, format, nil}, format, nil @@ -50,11 +49,22 @@ func (d *decoder) Stream(samples [][2]float64) (n int, ok bool) { } var tmp [2]float32 for i := range samples { - dn, err := d.d.Read(tmp[:]) - if dn == 2 { - samples[i][0], samples[i][1] = float64(tmp[0]), float64(tmp[1]) - n++ - ok = true + var err error + var dn int + if d.d.Channels() == 1 { + dn, err = d.d.Read(tmp[:1]) + if dn == 1 { + samples[i][0], samples[i][1] = float64(tmp[0]), float64(tmp[0]) + n++ + ok = true + } + } else { + dn, err = d.d.Read(tmp[:]) + if dn == 2 { + samples[i][0], samples[i][1] = float64(tmp[0]), float64(tmp[1]) + n++ + ok = true + } } if err == io.EOF { break diff --git a/vendor/github.com/hajimehoshi/oto/AUTHORS b/vendor/github.com/hajimehoshi/oto/AUTHORS deleted file mode 100644 index 62c6801..0000000 --- a/vendor/github.com/hajimehoshi/oto/AUTHORS +++ /dev/null @@ -1,14 +0,0 @@ -Bill Rose -Christopher Cooper -Diane -Hajime Hoshi -Ilya -Johnny -Medusalix <8124898+medusalix@users.noreply.github.com> -Michal Štrba -Noofbiz -skuzzymiglet <42312436+skuzzymiglet@users.noreply.github.com> -Thomas Friedel -Veikko Sariola -Yosuke Akatsuka -Yu <1095780+yuikns@users.noreply.github.com> diff --git a/vendor/github.com/hajimehoshi/oto/README.md b/vendor/github.com/hajimehoshi/oto/README.md deleted file mode 100644 index f89c36a..0000000 --- a/vendor/github.com/hajimehoshi/oto/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Oto (音) - -[![GoDoc](https://godoc.org/github.com/hajimehoshi/oto?status.svg)](http://godoc.org/github.com/hajimehoshi/oto) - -A low-level library to play sound. This package offers `io.WriteCloser` to play PCM sound. - -## Platforms - -* Windows -* macOS -* Linux -* FreeBSD -* OpenBSD -* Android -* iOS -* Web browsers ([GopherJS](https://github.com/gopherjs/gopherjs) and WebAssembly) - -## Prerequisite - -### macOS - -Oto requies `AudioToolbox.framework`, but this is automatically linked. - -### iOS - -Oto requies these frameworks: - -* `AVFoundation.framework` -* `AudioToolbox.framework` - -Add them to "Linked Frameworks and Libraries" on your Xcode project. - -### Linux - -libasound2-dev is required. On Ubuntu or Debian, run this command: - -```sh -apt install libasound2-dev -``` - -In most cases this command must be run by root user or through `sudo` command. - -#### Crosscompiling - -To crosscompile, make sure the libraries for the target architecture are installed, and set `CGO_ENABLED=1` as Go disables [Cgo](https://golang.org/cmd/cgo/#hdr-Using_cgo_with_the_go_command) on crosscompiles by default - -### FreeBSD - -OpenAL is required. Install openal-soft: - -```sh -pkg install openal-soft -``` - -### OpenBSD - -OpenAL is required. Install openal: - -```sh -pkg_add -r openal -``` diff --git a/vendor/github.com/hajimehoshi/oto/context.go b/vendor/github.com/hajimehoshi/oto/context.go deleted file mode 100644 index abeb6f8..0000000 --- a/vendor/github.com/hajimehoshi/oto/context.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oto - -import ( - "errors" - "io" - "sync" - "time" - - "github.com/hajimehoshi/oto/internal/mux" -) - -// Context is the main object in Oto. It interacts with the audio drivers. -// -// To play sound with Oto, first create a context. Then use the context to create -// an arbitrary number of players. Then use the players to play sound. -// -// There can only be one context at any time. Closing a context and opening a new one is allowed. -type Context struct { - driverWriter *driverWriter - mux *mux.Mux - errCh chan error -} - -var ( - theContext *Context - contextM sync.Mutex -) - -var errClosed = errors.New("closed") - -// NewContext creates a new context, that creates and holds ready-to-use Player objects. -// -// The sampleRate argument specifies the number of samples that should be played during one second. -// Usual numbers are 44100 or 48000. -// -// The channelNum argument specifies the number of channels. One channel is mono playback. Two -// channels are stereo playback. No other values are supported. -// -// The bitDepthInBytes argument specifies the number of bytes per sample per channel. The usual value -// is 2. Only values 1 and 2 are supported. -// -// The bufferSizeInBytes argument specifies the size of the buffer of the Context. This means, how -// many bytes can Context remember before actually playing them. Bigger buffer can reduce the number -// of Player's Write calls, thus reducing CPU time. Smaller buffer enables more precise timing. The -// longest delay between when samples were written and when they started playing is equal to the size -// of the buffer. -func NewContext(sampleRate, channelNum, bitDepthInBytes, bufferSizeInBytes int) (*Context, error) { - contextM.Lock() - defer contextM.Unlock() - - if theContext != nil { - panic("oto: NewContext can be called only once") - } - - d, err := newDriver(sampleRate, channelNum, bitDepthInBytes, bufferSizeInBytes) - if err != nil { - return nil, err - } - dw := &driverWriter{ - driver: d, - bufferSize: bufferSizeInBytes, - bytesPerSecond: sampleRate * channelNum * bitDepthInBytes, - } - c := &Context{ - driverWriter: dw, - mux: mux.New(channelNum, bitDepthInBytes), - errCh: make(chan error, 1), - } - theContext = c - go func() { - if _, err := io.Copy(c.driverWriter, c.mux); err != nil { - c.errCh <- err - } - close(c.errCh) - c.Close() - }() - return c, nil -} - -// NewPlayer creates a new, ready-to-use Player belonging to the Context. -func (c *Context) NewPlayer() *Player { - return newPlayer(c) -} - -// Close closes the Context and its Players and frees any resources associated with it. The Context is no longer -// usable after calling Close. -func (c *Context) Close() error { - if theContext == nil { - return nil - } - - contextM.Lock() - if theContext == nil { - contextM.Unlock() - return nil - } - theContext = nil - contextM.Unlock() - - if err := c.driverWriter.Close(); err != nil { - return err - } - for _, r := range c.mux.Sources() { - if err := r.(io.Closer).Close(); err != nil { - return err - } - } - if err := c.mux.Close(); err != nil { - return err - } - return nil -} - -type tryWriteCloser interface { - io.Closer - - TryWrite([]byte) (int, error) - tryWriteCanReturnWithoutWaiting() bool -} - -type driverWriter struct { - driver tryWriteCloser - bufferSize int - bytesPerSecond int - - m sync.Mutex -} - -func (d *driverWriter) Write(buf []byte) (int, error) { - d.m.Lock() - defer d.m.Unlock() - - written := 0 - for len(buf) > 0 { - if d.driver == nil { - return written, errClosed - } - n, err := d.driver.TryWrite(buf) - written += n - if err != nil { - return written, err - } - buf = buf[n:] - if d.driver.tryWriteCanReturnWithoutWaiting() { - // When not all buf is written, the underlying buffer is full. - // Mitigate the busy loop by sleeping (#10). - if len(buf) > 0 { - t := time.Second * time.Duration(d.bufferSize) / time.Duration(d.bytesPerSecond) / 8 - time.Sleep(t) - } - } - } - return written, nil -} - -func (d *driverWriter) Close() error { - d.m.Lock() - defer d.m.Unlock() - - // Close should be wait until the buffer data is consumed (#36). - // This is the simplest (but ugly) fix. - // TODO: Implement player's Close to wait the buffer played. - time.Sleep(time.Second * time.Duration(d.bufferSize) / time.Duration(d.bytesPerSecond)) - return d.driver.Close() -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_android.go b/vendor/github.com/hajimehoshi/oto/driver_android.go deleted file mode 100644 index dbc7057..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_android.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2016 Hajime Hoshi -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oto - -/* - -#include -#include - -static jclass android_media_AudioFormat; -static jclass android_media_AudioManager; -static jclass android_media_AudioTrack; - -static char* initAudioTrack(uintptr_t java_vm, uintptr_t jni_env, - int sampleRate, int channelNum, int bitDepthInBytes, jobject* audioTrack, int bufferSize) { - JavaVM* vm = (JavaVM*)java_vm; - JNIEnv* env = (JNIEnv*)jni_env; - - jclass android_os_Build_VERSION = (*env)->FindClass(env, "android/os/Build$VERSION"); - const jint availableSDK = - (*env)->GetStaticIntField( - env, android_os_Build_VERSION, - (*env)->GetStaticFieldID(env, android_os_Build_VERSION, "SDK_INT", "I")); - (*env)->DeleteLocalRef(env, android_os_Build_VERSION); - - jclass local = (*env)->FindClass(env, "android/media/AudioFormat"); - android_media_AudioFormat = (*env)->NewGlobalRef(env, local); - (*env)->DeleteLocalRef(env, local); - - local = (*env)->FindClass(env, "android/media/AudioManager"); - android_media_AudioManager = (*env)->NewGlobalRef(env, local); - (*env)->DeleteLocalRef(env, local); - - local = (*env)->FindClass(env, "android/media/AudioTrack"); - android_media_AudioTrack = (*env)->NewGlobalRef(env, local); - (*env)->DeleteLocalRef(env, local); - - const jint android_media_AudioManager_STREAM_MUSIC = - (*env)->GetStaticIntField( - env, android_media_AudioManager, - (*env)->GetStaticFieldID(env, android_media_AudioManager, "STREAM_MUSIC", "I")); - const jint android_media_AudioTrack_MODE_STREAM = - (*env)->GetStaticIntField( - env, android_media_AudioTrack, - (*env)->GetStaticFieldID(env, android_media_AudioTrack, "MODE_STREAM", "I")); - const jint android_media_AudioFormat_CHANNEL_OUT_MONO = - (*env)->GetStaticIntField( - env, android_media_AudioFormat, - (*env)->GetStaticFieldID(env, android_media_AudioFormat, "CHANNEL_OUT_MONO", "I")); - const jint android_media_AudioFormat_CHANNEL_OUT_STEREO = - (*env)->GetStaticIntField( - env, android_media_AudioFormat, - (*env)->GetStaticFieldID(env, android_media_AudioFormat, "CHANNEL_OUT_STEREO", "I")); - const jint android_media_AudioFormat_ENCODING_PCM_8BIT = - (*env)->GetStaticIntField( - env, android_media_AudioFormat, - (*env)->GetStaticFieldID(env, android_media_AudioFormat, "ENCODING_PCM_8BIT", "I")); - const jint android_media_AudioFormat_ENCODING_PCM_16BIT = - (*env)->GetStaticIntField( - env, android_media_AudioFormat, - (*env)->GetStaticFieldID(env, android_media_AudioFormat, "ENCODING_PCM_16BIT", "I")); - - jint channel = android_media_AudioFormat_CHANNEL_OUT_MONO; - switch (channelNum) { - case 1: - channel = android_media_AudioFormat_CHANNEL_OUT_MONO; - break; - case 2: - channel = android_media_AudioFormat_CHANNEL_OUT_STEREO; - break; - default: - return "invalid channel"; - } - - jint encoding = android_media_AudioFormat_ENCODING_PCM_8BIT; - switch (bitDepthInBytes) { - case 1: - encoding = android_media_AudioFormat_ENCODING_PCM_8BIT; - break; - case 2: - encoding = android_media_AudioFormat_ENCODING_PCM_16BIT; - break; - default: - return "invalid bitDepthInBytes"; - } - - // If the available Android SDK is at least 24 (7.0 Nougat), the FLAG_LOW_LATENCY is available. - // This requires a different constructor. - if (availableSDK >= 24) { - jclass android_media_AudioAttributes_Builder; - jclass android_media_AudioFormat_Builder; - jclass android_media_AudioAttributes; - - local = (*env)->FindClass(env, "android/media/AudioAttributes$Builder"); - android_media_AudioAttributes_Builder = (*env)->NewGlobalRef(env, local); - (*env)->DeleteLocalRef(env, local); - - local = (*env)->FindClass(env, "android/media/AudioFormat$Builder"); - android_media_AudioFormat_Builder = (*env)->NewGlobalRef(env, local); - (*env)->DeleteLocalRef(env, local); - - local = (*env)->FindClass(env, "android/media/AudioAttributes"); - android_media_AudioAttributes = (*env)->NewGlobalRef(env, local); - (*env)->DeleteLocalRef(env, local); - - jint android_media_AudioAttributes_USAGE_UNKNOWN = - (*env)->GetStaticIntField( - env, android_media_AudioAttributes, - (*env)->GetStaticFieldID(env, android_media_AudioAttributes, "USAGE_UNKNOWN", "I")); - jint android_media_AudioAttributes_CONTENT_TYPE_UNKNOWN = - (*env)->GetStaticIntField( - env, android_media_AudioAttributes, - (*env)->GetStaticFieldID(env, android_media_AudioAttributes, "CONTENT_TYPE_UNKNOWN", "I")); - jint android_media_AudioAttributes_FLAG_LOW_LATENCY = - (*env)->GetStaticIntField( - env, android_media_AudioAttributes, - (*env)->GetStaticFieldID(env, android_media_AudioAttributes, "FLAG_LOW_LATENCY", "I")); - - const jobject aattrBld = - (*env)->NewObject( - env, android_media_AudioAttributes_Builder, - (*env)->GetMethodID(env, android_media_AudioAttributes_Builder, "", "()V")); - - (*env)->CallObjectMethod( - env, aattrBld, - (*env)->GetMethodID(env, android_media_AudioAttributes_Builder, "setUsage", "(I)Landroid/media/AudioAttributes$Builder;"), - android_media_AudioAttributes_USAGE_UNKNOWN); - (*env)->CallObjectMethod( - env, aattrBld, - (*env)->GetMethodID(env, android_media_AudioAttributes_Builder, "setContentType", "(I)Landroid/media/AudioAttributes$Builder;"), - android_media_AudioAttributes_CONTENT_TYPE_UNKNOWN); - (*env)->CallObjectMethod( - env, aattrBld, - (*env)->GetMethodID(env, android_media_AudioAttributes_Builder, "setFlags", "(I)Landroid/media/AudioAttributes$Builder;"), - android_media_AudioAttributes_FLAG_LOW_LATENCY); - const jobject aattr = - (*env)->CallObjectMethod( - env, aattrBld, - (*env)->GetMethodID(env, android_media_AudioAttributes_Builder, "build", "()Landroid/media/AudioAttributes;")); - (*env)->DeleteLocalRef(env, aattrBld); - - const jobject afmtBld = - (*env)->NewObject( - env, android_media_AudioFormat_Builder, - (*env)->GetMethodID(env, android_media_AudioFormat_Builder, "", "()V")); - (*env)->CallObjectMethod( - env, afmtBld, - (*env)->GetMethodID(env, android_media_AudioFormat_Builder, "setSampleRate", "(I)Landroid/media/AudioFormat$Builder;"), - sampleRate); - (*env)->CallObjectMethod( - env, afmtBld, - (*env)->GetMethodID(env, android_media_AudioFormat_Builder, "setEncoding", "(I)Landroid/media/AudioFormat$Builder;"), - encoding); - (*env)->CallObjectMethod( - env, afmtBld, - (*env)->GetMethodID(env, android_media_AudioFormat_Builder, "setChannelMask", "(I)Landroid/media/AudioFormat$Builder;"), - channel); - const jobject afmt = - (*env)->CallObjectMethod( - env, afmtBld, - (*env)->GetMethodID(env, android_media_AudioFormat_Builder, "build", "()Landroid/media/AudioFormat;")); - (*env)->DeleteLocalRef(env, afmtBld); - - const jobject tmpAudioTrack = - (*env)->NewObject( - env, android_media_AudioTrack, - (*env)->GetMethodID(env, android_media_AudioTrack, "", "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;III)V"), - aattr, afmt, bufferSize, android_media_AudioTrack_MODE_STREAM, 0); - *audioTrack = (*env)->NewGlobalRef(env, tmpAudioTrack); - (*env)->DeleteLocalRef(env, tmpAudioTrack); - (*env)->DeleteLocalRef(env, aattr); - (*env)->DeleteLocalRef(env, afmt); - } else { - const jobject tmpAudioTrack = - (*env)->NewObject( - env, android_media_AudioTrack, - (*env)->GetMethodID(env, android_media_AudioTrack, "", "(IIIIII)V"), - android_media_AudioManager_STREAM_MUSIC, - sampleRate, channel, encoding, bufferSize, - android_media_AudioTrack_MODE_STREAM); - *audioTrack = (*env)->NewGlobalRef(env, tmpAudioTrack); - (*env)->DeleteLocalRef(env, tmpAudioTrack); - } - - (*env)->CallVoidMethod( - env, *audioTrack, - (*env)->GetMethodID(env, android_media_AudioTrack, "play", "()V")); - - return NULL; -} - -static char* writeToAudioTrack(uintptr_t java_vm, uintptr_t jni_env, - jobject audioTrack, int bitDepthInBytes, void* data, int length) { - JavaVM* vm = (JavaVM*)java_vm; - JNIEnv* env = (JNIEnv*)jni_env; - - jbyteArray arrInBytes; - jshortArray arrInShorts; - switch (bitDepthInBytes) { - case 1: - arrInBytes = (*env)->NewByteArray(env, length); - (*env)->SetByteArrayRegion(env, arrInBytes, 0, length, data); - break; - case 2: - arrInShorts = (*env)->NewShortArray(env, length); - (*env)->SetShortArrayRegion(env, arrInShorts, 0, length, data); - break; - } - - jint result; - static jmethodID write1 = NULL; - static jmethodID write2 = NULL; - if (!write1) { - write1 = (*env)->GetMethodID(env, android_media_AudioTrack, "write", "([BII)I"); - } - if (!write2) { - write2 = (*env)->GetMethodID(env, android_media_AudioTrack, "write", "([SII)I"); - } - switch (bitDepthInBytes) { - case 1: - result = (*env)->CallIntMethod(env, audioTrack, write1, arrInBytes, 0, length); - (*env)->DeleteLocalRef(env, arrInBytes); - break; - case 2: - result = (*env)->CallIntMethod(env, audioTrack, write2, arrInShorts, 0, length); - (*env)->DeleteLocalRef(env, arrInShorts); - break; - } - - switch (result) { - case -3: // ERROR_INVALID_OPERATION - return "invalid operation"; - case -2: // ERROR_BAD_VALUE - return "bad value"; - case -1: // ERROR - return "error"; - } - if (result < 0) { - return "unknown error"; - } - return NULL; -} - -static char* releaseAudioTrack(uintptr_t java_vm, uintptr_t jni_env, - jobject audioTrack) { - JavaVM* vm = (JavaVM*)java_vm; - JNIEnv* env = (JNIEnv*)jni_env; - - (*env)->CallVoidMethod( - env, audioTrack, - (*env)->GetMethodID(env, android_media_AudioTrack, "release", "()V")); - return NULL; -} - -*/ -import "C" - -import ( - "errors" - "runtime" - "unsafe" - - "golang.org/x/mobile/app" -) - -type driver struct { - sampleRate int - channelNum int - bitDepthInBytes int - audioTrack C.jobject - chErr chan error - chBuffer chan []byte - tmp []byte - bufferSize int -} - -func newDriver(sampleRate, channelNum, bitDepthInBytes, bufferSizeInBytes int) (tryWriteCloser, error) { - p := &driver{ - sampleRate: sampleRate, - channelNum: channelNum, - bitDepthInBytes: bitDepthInBytes, - chErr: make(chan error), - chBuffer: make(chan []byte), - } - runtime.SetFinalizer(p, (*driver).Close) - - if err := app.RunOnJVM(func(vm, env, ctx uintptr) error { - audioTrack := C.jobject(0) - bufferSize := C.int(bufferSizeInBytes) - if msg := C.initAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), - C.int(sampleRate), C.int(channelNum), C.int(bitDepthInBytes), - &audioTrack, bufferSize); msg != nil { - return errors.New("oto: initAutioTrack failed: " + C.GoString(msg)) - } - p.audioTrack = audioTrack - p.bufferSize = int(bufferSize) - return nil - }); err != nil { - return nil, err - } - - go p.loop() - return p, nil -} - -func (p *driver) loop() { - for bufInBytes := range p.chBuffer { - var bufInShorts []int16 - if p.bitDepthInBytes == 2 { - bufInShorts = make([]int16, len(bufInBytes)/2) - for i := 0; i < len(bufInShorts); i++ { - bufInShorts[i] = int16(bufInBytes[2*i]) | (int16(bufInBytes[2*i+1]) << 8) - } - } - if err := app.RunOnJVM(func(vm, env, ctx uintptr) error { - msg := (*C.char)(nil) - switch p.bitDepthInBytes { - case 1: - msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), - p.audioTrack, C.int(p.bitDepthInBytes), - unsafe.Pointer(&bufInBytes[0]), C.int(len(bufInBytes))) - case 2: - msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), - p.audioTrack, C.int(p.bitDepthInBytes), - unsafe.Pointer(&bufInShorts[0]), C.int(len(bufInShorts))) - default: - panic("not reach") - } - if msg != nil { - return errors.New("oto: loop failed: " + C.GoString(msg)) - } - return nil - }); err != nil { - p.chErr <- err - return - } - } -} - -func (p *driver) TryWrite(data []byte) (int, error) { - n := min(len(data), p.bufferSize-len(p.tmp)) - p.tmp = append(p.tmp, data[:n]...) - - if len(p.tmp) < p.bufferSize { - return n, nil - } - - select { - case p.chBuffer <- p.tmp: - case err := <-p.chErr: - return 0, err - } - - p.tmp = nil - return n, nil -} - -func (p *driver) Close() error { - if p.audioTrack == 0 { - return nil - } - - runtime.SetFinalizer(p, nil) - err := app.RunOnJVM(func(vm, env, ctx uintptr) error { - if msg := C.releaseAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), - p.audioTrack); msg != nil { - return errors.New("oto: release failed: " + C.GoString(msg)) - } - return nil - }) - - p.audioTrack = 0 - return err -} - -func (d *driver) tryWriteCanReturnWithoutWaiting() bool { - return true -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_darwin.go b/vendor/github.com/hajimehoshi/oto/driver_darwin.go deleted file mode 100644 index 8294125..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_darwin.go +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !js -// +build !js - -package oto - -// #cgo LDFLAGS: -framework AudioToolbox -// -// #import -// -// void oto_render(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer); -// -// void oto_setNotificationHandler(); -// bool oto_isBackground(void); -import "C" - -import ( - "context" - "fmt" - "runtime" - "sync" - "time" - "unsafe" -) - -const baseQueueBufferSize = 1024 - -type audioInfo struct { - channelNum int - bitDepthInBytes int -} - -type driver struct { - ctx context.Context - cancel context.CancelFunc - audioQueue C.AudioQueueRef - buf []byte - bufSize int - sampleRate int - audioInfo *audioInfo - buffers []C.AudioQueueBufferRef - paused bool - lastPauseTime time.Time - - err error - - chWrite chan []byte - chWritten chan int - - m sync.Mutex -} - -var ( - theDriver *driver - driverM sync.Mutex -) - -func setDriver(d *driver) { - driverM.Lock() - defer driverM.Unlock() - - if theDriver != nil && d != nil { - panic("oto: at most one driver object can exist") - } - theDriver = d - - if d != nil { - setNotificationHandler(d) - } -} - -func getDriver() *driver { - driverM.Lock() - defer driverM.Unlock() - - return theDriver -} - -// TOOD: Convert the error code correctly. -// See https://stackoverflow.com/questions/2196869/how-do-you-convert-an-iphone-osstatus-code-to-something-useful - -func newDriver(sampleRate, channelNum, bitDepthInBytes, bufferSizeInBytes int) (tryWriteCloser, error) { - flags := C.kAudioFormatFlagIsPacked - if bitDepthInBytes != 1 { - flags |= C.kAudioFormatFlagIsSignedInteger - } - desc := C.AudioStreamBasicDescription{ - mSampleRate: C.double(sampleRate), - mFormatID: C.kAudioFormatLinearPCM, - mFormatFlags: C.UInt32(flags), - mBytesPerPacket: C.UInt32(channelNum * bitDepthInBytes), - mFramesPerPacket: 1, - mBytesPerFrame: C.UInt32(channelNum * bitDepthInBytes), - mChannelsPerFrame: C.UInt32(channelNum), - mBitsPerChannel: C.UInt32(8 * bitDepthInBytes), - } - - audioInfo := &audioInfo{ - channelNum: channelNum, - bitDepthInBytes: bitDepthInBytes, - } - - var audioQueue C.AudioQueueRef - if osstatus := C.AudioQueueNewOutput( - &desc, - (C.AudioQueueOutputCallback)(C.oto_render), - unsafe.Pointer(audioInfo), - (C.CFRunLoopRef)(0), - (C.CFStringRef)(0), - 0, - &audioQueue); osstatus != C.noErr { - return nil, fmt.Errorf("oto: AudioQueueNewFormat with StreamFormat failed: %d", osstatus) - } - - queueBufferSize := baseQueueBufferSize * channelNum * bitDepthInBytes - nbuf := bufferSizeInBytes / queueBufferSize - if nbuf <= 1 { - nbuf = 2 - } - - ctx, cancel := context.WithCancel(context.Background()) - d := &driver{ - ctx: ctx, - cancel: cancel, - audioQueue: audioQueue, - sampleRate: sampleRate, - audioInfo: audioInfo, - bufSize: nbuf * queueBufferSize, - buffers: make([]C.AudioQueueBufferRef, nbuf), - chWrite: make(chan []byte), - chWritten: make(chan int), - } - runtime.SetFinalizer(d, (*driver).Close) - // Set the driver before setting the rendering callback. - setDriver(d) - - for i := 0; i < len(d.buffers); i++ { - var buf C.AudioQueueBufferRef - if osstatus := C.AudioQueueAllocateBuffer(audioQueue, C.UInt32(queueBufferSize), &buf); osstatus != C.noErr { - return nil, fmt.Errorf("oto: AudioQueueAllocateBuffer failed: %d", osstatus) - } - d.buffers[i] = buf - d.buffers[i].mAudioDataByteSize = C.UInt32(queueBufferSize) - for j := 0; j < queueBufferSize; j++ { - *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(d.buffers[i].mAudioData)) + uintptr(j))) = 0 - } - if osstatus := C.AudioQueueEnqueueBuffer(audioQueue, d.buffers[i], 0, nil); osstatus != C.noErr { - return nil, fmt.Errorf("oto: AudioQueueEnqueueBuffer failed: %d", osstatus) - } - } - - for C.oto_isBackground() { - time.Sleep(time.Second) - } - - if osstatus := C.AudioQueueStart(audioQueue, nil); osstatus != C.noErr { - return nil, fmt.Errorf("oto: AudioQueueStart failed: %d", osstatus) - } - - return d, nil -} - -//export oto_render -func oto_render(inUserData unsafe.Pointer, inAQ C.AudioQueueRef, inBuffer C.AudioQueueBufferRef) { - audioInfo := (*audioInfo)(inUserData) - queueBufferSize := baseQueueBufferSize * audioInfo.channelNum * audioInfo.bitDepthInBytes - - d := getDriver() - - var buf []byte - - // Set the timer. When the input does not come, the audio must be paused. - s := time.Second * time.Duration(queueBufferSize) / time.Duration(d.sampleRate*d.audioInfo.channelNum*d.audioInfo.bitDepthInBytes) - t := time.NewTicker(s) - defer t.Stop() - ch := t.C - - for len(buf) < queueBufferSize && d.ctx.Err() == nil { - select { - case dbuf := <-d.chWrite: - for !d.resume(false) { - d.m.Lock() - err := d.err - d.m.Unlock() - if err != nil { - return - } - - time.Sleep(time.Second) - } - n := queueBufferSize - len(buf) - if n > len(dbuf) { - n = len(dbuf) - } - buf = append(buf, dbuf[:n]...) - d.chWritten <- n - case <-ch: - d.pause() - ch = nil - case <-d.ctx.Done(): - // AudioQueue was closed, return immediately - return - } - } - - // oto_render is a callback for AudioQueueNewOutput. - // According to the observation, it may still called once after drvier.Close called. - // - // In most case, the assumption len(buf) == queueBufferSize may always be true. - // - // However, here is a special case: - // After the `Close` called, and it is receiving chWrite and it may noticed - // `d.ctx.Err() != nil`, it will jump out from loop directly. - // - // At this moment, since d.audioQueue is nil and the inBuffer may not processed, - // We don't need to do any process to the inBuffer. - // - // Another consideration is when len(buf) != queueBufferSize, we may return directly. - // In this case we still need to check whether d.audioQueue is valid inside enqueueBuffer - // It may worthless. - for i := 0; i < len(buf); i++ { - *(*byte)(unsafe.Pointer(uintptr(inBuffer.mAudioData) + uintptr(i))) = buf[i] - } - // Do not update mAudioDataByteSize, or the buffer is not used correctly any more. - - d.enqueueBuffer(inBuffer) -} - -func (d *driver) TryWrite(data []byte) (int, error) { - d.m.Lock() - err := d.err - d.m.Unlock() - if err != nil { - return 0, err - } - - n := d.bufSize - len(d.buf) - if n > len(data) { - n = len(data) - } - d.buf = append(d.buf, data[:n]...) - // Use the buffer only when the buffer length is enough to avoid choppy sound. - queueBufferSize := baseQueueBufferSize * d.audioInfo.channelNum * d.audioInfo.bitDepthInBytes - for len(d.buf) >= queueBufferSize { - d.chWrite <- d.buf - n := <-d.chWritten - d.buf = d.buf[n:] - } - return n, nil -} - -func (d *driver) Close() error { - d.m.Lock() - defer d.m.Unlock() - - runtime.SetFinalizer(d, nil) - - // notify to close any (oto_render in this case) running progress - d.cancel() - - if osstatus := C.AudioQueueStop(d.audioQueue, C.false); osstatus != C.noErr { - return fmt.Errorf("oto: AudioQueueStop failed: %d", osstatus) - } - if osstatus := C.AudioQueueDispose(d.audioQueue, C.false); osstatus != C.noErr { - return fmt.Errorf("oto: AudioQueueDispose failed: %d", osstatus) - } - d.audioQueue = nil - setDriver(nil) - return nil -} - -func (d *driver) enqueueBuffer(buffer C.AudioQueueBufferRef) { - d.m.Lock() - defer d.m.Unlock() - - // avoid to enqueue buffer to a closed audio queue - if d.ctx.Err() != nil { - return - } - - if osstatus := C.AudioQueueEnqueueBuffer(d.audioQueue, buffer, 0, nil); osstatus != C.noErr && d.err == nil { - d.err = fmt.Errorf("oto: AudioQueueEnqueueBuffer failed: %d", osstatus) - return - } -} - -func (d *driver) resume(afterSleep bool) bool { - d.m.Lock() - defer d.m.Unlock() - - // Audio doesn't work soon after recovering from sleeping. Wait for a while - // (hajimehoshi/ebiten#1259). - if afterSleep { - // After short-time sleeping, 500ms more sleeping is enough. However, after long-time sleeping, it - // looks like 1 second more sleeping are required (hajimehoshi/ebiten#1280). - // This is tested on MacBook Pro 2020 macOS 10.15.6. - if time.Now().Sub(d.lastPauseTime) < 30*time.Second { - time.Sleep(500 * time.Millisecond) - } else { - time.Sleep(time.Second) - } - } - - if C.oto_isBackground() { - return false - } - - if osstatus := C.AudioQueueStart(d.audioQueue, nil); osstatus != C.noErr && d.err == nil { - d.err = fmt.Errorf("oto: AudioQueueStart for resuming failed: %d", osstatus) - return false - } - d.paused = false - return true -} - -func (d *driver) pause() { - d.m.Lock() - defer d.m.Unlock() - - if d.paused { - return - } - if osstatus := C.AudioQueuePause(d.audioQueue); osstatus != C.noErr && d.err == nil { - d.err = fmt.Errorf("oto: AudioQueuePause failed: %d", osstatus) - return - } - d.paused = true - d.lastPauseTime = time.Now() -} - -func (d *driver) setError(err error) { - d.m.Lock() - defer d.m.Unlock() - - if theDriver.err != nil { - return - } - theDriver.err = err -} - -func (d *driver) tryWriteCanReturnWithoutWaiting() bool { - return true -} - -func setNotificationHandler(driver *driver) { - C.oto_setNotificationHandler() -} - -//export oto_setGlobalPause -func oto_setGlobalPause() { - theDriver.pause() -} - -//export oto_setGlobalResume -func oto_setGlobalResume() { - theDriver.resume(true) -} - -//export oto_setErrorByNotification -func oto_setErrorByNotification(s C.OSStatus, from *C.char) { - gofrom := C.GoString(from) - theDriver.setError(fmt.Errorf("oto: %s at notification failed: %d", gofrom, s)) -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_ios.m b/vendor/github.com/hajimehoshi/oto/driver_ios.m deleted file mode 100644 index 13ca9f9..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_ios.m +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build darwin && ios -// +build darwin,ios - -#import -#import -#import - -#include "_cgo_export.h" - -@interface OtoNotificationObserver : NSObject { -} - -- (void)onAudioSessionInterruption:(NSNotification *)notification; - -@end - -@implementation OtoNotificationObserver { -} - -- (void)onAudioSessionInterruption:(NSNotification *)notification { - if (![notification.name isEqualToString:AVAudioSessionInterruptionNotification]) { - return; - } - - NSObject* value = [notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey]; - AVAudioSessionInterruptionType interruptionType = [(NSNumber*)value intValue]; - switch (interruptionType) { - case AVAudioSessionInterruptionTypeBegan: { - oto_setGlobalPause(); - break; - } - case AVAudioSessionInterruptionTypeEnded: { - // AVAudioSessionInterruptionTypeBegan and Ended might not be paired when - // Siri is used. Then, incrementing and decrementing a counter with this - // notification doesn't work. - oto_setGlobalResume(); - break; - } - default: - NSAssert(NO, @"unexpected AVAudioSessionInterruptionType: %lu", - (unsigned long)(interruptionType)); - break; - } -} - -@end - -// oto_setNotificationHandler sets a handler for interruption events. -// Without the handler, Siri would stop the audio (#80). -void oto_setNotificationHandler() { - AVAudioSession* session = [AVAudioSession sharedInstance]; - OtoNotificationObserver *observer = [[OtoNotificationObserver alloc] init]; - [[NSNotificationCenter defaultCenter] - addObserver:observer - selector:@selector(onAudioSessionInterruption:) - name:AVAudioSessionInterruptionNotification - object:session]; - - // The notifications UIApplicationDidEnterBackgroundNotification and - // UIApplicationWillEnterForegroundNotification were not reliable: at least, - // they were not notified at iPod touch A2178. - // - // Instead, check the background state via UIApplication actively. -} - -bool oto_isBackground(void) { - if ([NSThread isMainThread]) { - return [[UIApplication sharedApplication] applicationState] == - UIApplicationStateBackground; - } - - __block bool background = false; - dispatch_sync(dispatch_get_main_queue(), ^{ - background = oto_isBackground(); - }); - return background; -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_js.go b/vendor/github.com/hajimehoshi/oto/driver_js.go deleted file mode 100644 index d605ac4..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_js.go +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2015 Hajime Hoshi -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build js -// +build js - -package oto - -import ( - "encoding/base64" - "errors" - "fmt" - "sync" - "syscall/js" -) - -type driver struct { - sampleRate int - channelNum int - bitDepthInBytes int - nextPos float64 - tmp []byte - bufferSize int - context js.Value - ready bool - callbacks map[string]js.Func - - // For Audio Worklet - workletNode js.Value - workletNodePost js.Value - messageArray js.Value - transferArray js.Value - bufs [][]js.Value - cond *sync.Cond -} - -type warn struct { - msg string -} - -func (w *warn) Error() string { - return w.msg -} - -const audioBufferSamples = 3200 - -func tryAudioWorklet(context js.Value, channelNum int) (js.Value, error) { - if !js.Global().Get("AudioWorkletNode").Truthy() { - return js.Undefined(), nil - } - - worklet := context.Get("audioWorklet") - if !worklet.Truthy() { - return js.Undefined(), &warn{ - msg: "AudioWorklet is not available due to the insecure context. See https://developer.mozilla.org/en-US/docs/Web/API/AudioWorklet", - } - } - - script := ` -class EbitenAudioWorkletProcessor extends AudioWorkletProcessor { - constructor() { - super(); - - this.buffers_ = [[], []]; - this.offsets_ = [0, 0]; - this.offsetsInArray_ = [0, 0]; - this.consumed_ = []; - - this.port.onmessage = (e) => { - const bufs = e.data; - for (let ch = 0; ch < bufs.length; ch++) { - const buf = bufs[ch]; - this.buffers_[ch].push(new Float32Array(buf.buffer, buf.byteOffset, buf.byteLength / 4)); - } - }; - } - - bufferTotalLength(ch) { - const sum = this.buffers_[ch].reduce((total, buf) => total + buf.length, 0); - return sum - this.offsetsInArray_[ch]; - } - - consume(ch, i) { - while (this.buffers_[ch][0].length <= i - this.offsets_[ch]) { - this.offsets_[ch] += this.buffers_[ch][0].length; - this.offsetsInArray_[ch] = 0; - const buf = this.buffers_[ch].shift(); - this.appendConsumedBuffer(ch, buf); - } - this.offsetsInArray_[ch]++; - return this.buffers_[ch][0][i - this.offsets_[ch]]; - } - - appendConsumedBuffer(ch, buf) { - let idx = this.consumed_.length - 1; - if (idx < 0 || this.consumed_[idx][ch]) { - this.consumed_.push([]); - idx++; - } - this.consumed_[idx][ch] = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); - } - - process(inputs, outputs, parameters) { - const out = outputs[0]; - - if (this.bufferTotalLength(0) < out[0].length) { - for (let ch = 0; ch < out.length; ch++) { - for (let i = 0; i < out[ch].length; i++) { - out[ch][i] = 0; - } - } - return true; - } - - for (let ch = 0; ch < out.length; ch++) { - const offset = this.offsets_[ch] + this.offsetsInArray_[ch]; - for (let i = 0; i < out[ch].length; i++) { - out[ch][i] = this.consume(ch, i + offset); - } - } - - for (let bufs of this.consumed_) { - this.port.postMessage(bufs, bufs.map(buf => buf.buffer)); - } - this.consumed_ = []; - - return true; - } -} - -registerProcessor('ebiten-audio-worklet-processor', EbitenAudioWorkletProcessor);` - scriptURL := "data:application/javascript;base64," + base64.StdEncoding.EncodeToString([]byte(script)) - - ch := make(chan error) - worklet.Call("addModule", scriptURL).Call("then", js.FuncOf(func(js.Value, []js.Value) interface{} { - close(ch) - return nil - })).Call("catch", js.FuncOf(func(this js.Value, args []js.Value) interface{} { - err := args[0] - ch <- fmt.Errorf("oto: error at addModule: %s: %s", err.Get("name").String(), err.Get("message").String()) - close(ch) - return nil - })) - if err := <-ch; err != nil { - return js.Undefined(), err - } - - options := js.Global().Get("Object").New() - arr := js.Global().Get("Array").New() - arr.Call("push", channelNum) - options.Set("outputChannelCount", arr) - - node := js.Global().Get("AudioWorkletNode").New(context, "ebiten-audio-worklet-processor", options) - node.Call("connect", context.Get("destination")) - - return node, nil -} - -func newDriver(sampleRate, channelNum, bitDepthInBytes, bufferSize int) (tryWriteCloser, error) { - class := js.Global().Get("AudioContext") - if !class.Truthy() { - class = js.Global().Get("webkitAudioContext") - } - if !class.Truthy() { - return nil, errors.New("oto: audio couldn't be initialized") - } - - options := js.Global().Get("Object").New() - options.Set("sampleRate", sampleRate) - context := class.New(options) - - node, err := tryAudioWorklet(context, channelNum) - if err != nil { - w, ok := err.(*warn) - if !ok { - return nil, err - } - js.Global().Get("console").Call("warn", w.Error()) - } - - bs := bufferSize - if !node.Truthy() { - bs = max(bufferSize, audioBufferSamples*channelNum*bitDepthInBytes) - } else { - bs = max(bufferSize, 4096) - } - - p := &driver{ - sampleRate: sampleRate, - channelNum: channelNum, - bitDepthInBytes: bitDepthInBytes, - context: context, - workletNode: node, - bufferSize: bs, - } - - if node.Truthy() { - port := node.Get("port") - p.workletNodePost = port.Get("postMessage").Call("bind", port) - p.messageArray = js.Global().Get("Array").New(2) - p.transferArray = js.Global().Get("Array").New(2) - p.cond = sync.NewCond(&sync.Mutex{}) - - s := p.bufferSize / p.channelNum / p.bitDepthInBytes * 4 - p.bufs = [][]js.Value{ - { - js.Global().Get("Uint8Array").New(s), - js.Global().Get("Uint8Array").New(s), - }, - { - js.Global().Get("Uint8Array").New(s), - js.Global().Get("Uint8Array").New(s), - }, - } - - node.Get("port").Set("onmessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} { - p.cond.L.Lock() - defer p.cond.L.Unlock() - - bufs := args[0].Get("data") - var arr []js.Value - for i := 0; i < bufs.Length(); i++ { - arr = append(arr, bufs.Index(i)) - } - - notify := len(p.bufs) == 0 - p.bufs = append(p.bufs, arr) - if notify { - p.cond.Signal() - } - - return nil - })) - } - - setCallback := func(event string) js.Func { - var f js.Func - f = js.FuncOf(func(this js.Value, arguments []js.Value) interface{} { - if !p.ready { - p.context.Call("resume") - p.ready = true - } - js.Global().Get("document").Call("removeEventListener", event, f) - return nil - }) - js.Global().Get("document").Call("addEventListener", event, f) - p.callbacks[event] = f - return f - } - - // Browsers require user interaction to start the audio. - // https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio - p.callbacks = map[string]js.Func{} - setCallback("touchend") - setCallback("keyup") - setCallback("mouseup") - return p, nil -} - -func toLR(data []byte) ([]float32, []float32) { - const max = 1 << 15 - - l := make([]float32, len(data)/4) - r := make([]float32, len(data)/4) - for i := 0; i < len(data)/4; i++ { - l[i] = float32(int16(data[4*i])|int16(data[4*i+1])<<8) / max - r[i] = float32(int16(data[4*i+2])|int16(data[4*i+3])<<8) / max - } - return l, r -} - -func (p *driver) TryWrite(data []byte) (int, error) { - if !p.ready { - return 0, nil - } - - if p.workletNode.Truthy() { - p.cond.L.Lock() - defer p.cond.L.Unlock() - - n := min(len(data), max(0, p.bufferSize-len(p.tmp))) - p.tmp = append(p.tmp, data[:n]...) - - if len(p.tmp) < p.bufferSize { - return n, nil - } - - for len(p.bufs) == 0 { - p.cond.Wait() - } - - l, r := toLR(p.tmp[:p.bufferSize]) - tl := p.bufs[0][0] - tr := p.bufs[0][1] - copyFloat32sToJS(tl, l) - copyFloat32sToJS(tr, r) - p.tmp = p.tmp[p.bufferSize:] - - bufs := p.messageArray - bufs.SetIndex(0, tl) - bufs.SetIndex(1, tr) - transfers := p.transferArray - transfers.SetIndex(0, tl.Get("buffer")) - transfers.SetIndex(1, tr.Get("buffer")) - - p.workletNodePost.Invoke(bufs, transfers) - - p.bufs = p.bufs[1:] - - return n, nil - } - - n := min(len(data), max(0, p.bufferSize-len(p.tmp))) - p.tmp = append(p.tmp, data[:n]...) - - c := p.context.Get("currentTime").Float() - - if p.nextPos < c { - p.nextPos = c - } - - // It's too early to enqueue a buffer. - // Highly likely, there are two playing buffers now. - if c+float64(p.bufferSize/p.bitDepthInBytes/p.channelNum)/float64(p.sampleRate) < p.nextPos { - return n, nil - } - - le := audioBufferSamples * p.bitDepthInBytes * p.channelNum - if len(p.tmp) < le { - return n, nil - } - - buf := p.context.Call("createBuffer", p.channelNum, audioBufferSamples, p.sampleRate) - l, r := toLR(p.tmp[:le]) - tl, freel := float32SliceToTypedArray(l) - tr, freer := float32SliceToTypedArray(r) - if buf.Get("copyToChannel").Truthy() { - buf.Call("copyToChannel", tl, 0, 0) - buf.Call("copyToChannel", tr, 1, 0) - } else { - // copyToChannel is not defined on Safari 11 - buf.Call("getChannelData", 0).Call("set", tl) - buf.Call("getChannelData", 1).Call("set", tr) - } - freel() - freer() - - s := p.context.Call("createBufferSource") - s.Set("buffer", buf) - s.Call("connect", p.context.Get("destination")) - s.Call("start", p.nextPos) - p.nextPos += buf.Get("duration").Float() - - p.tmp = p.tmp[le:] - return n, nil -} - -func (p *driver) Close() error { - for event, f := range p.callbacks { - // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener - // "Calling removeEventListener() with arguments that do not identify any currently registered EventListener on the EventTarget has no effect." - js.Global().Get("document").Call("removeEventListener", event, f) - f.Release() - } - p.callbacks = nil - return nil -} - -func (d *driver) tryWriteCanReturnWithoutWaiting() bool { - return true -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_linux.go b/vendor/github.com/hajimehoshi/oto/driver_linux.go deleted file mode 100644 index c5029b2..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_linux.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2017 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !js && !android && !ios -// +build !js,!android,!ios - -package oto - -/* -#cgo pkg-config: alsa - -#include - -static void check(int *err, int newErr) { - if (*err) { - return; - } - *err = newErr; -} - -static int ALSA_hw_params( - snd_pcm_t *pcm, - unsigned sampleRate, - unsigned numChans, - snd_pcm_format_t format, - snd_pcm_uframes_t* buffer_size, - snd_pcm_uframes_t* period_size) { - snd_pcm_hw_params_t* params = NULL; - int err = 0; - snd_pcm_hw_params_alloca(¶ms); - check(&err, snd_pcm_hw_params_any(pcm, params)); - - check(&err, snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED)); - check(&err, snd_pcm_hw_params_set_format(pcm, params, format)); - check(&err, snd_pcm_hw_params_set_channels(pcm, params, numChans)); - check(&err, snd_pcm_hw_params_set_rate_resample(pcm, params, 1)); - check(&err, snd_pcm_hw_params_set_rate_near(pcm, params, &sampleRate, NULL)); - check(&err, snd_pcm_hw_params_set_buffer_size_near(pcm, params, buffer_size)); - check(&err, snd_pcm_hw_params_set_period_size_near(pcm, params, period_size, NULL)); - - check(&err, snd_pcm_hw_params(pcm, params)); - - return err; -} -*/ -import "C" - -import ( - "fmt" - "unsafe" -) - -type driver struct { - handle *C.snd_pcm_t - buf []byte - bufSamples int - numChans int - bitDepthInBytes int -} - -func alsaError(err C.int) error { - return fmt.Errorf("oto: ALSA error: %s", C.GoString(C.snd_strerror(err))) -} - -func newDriver(sampleRate, numChans, bitDepthInBytes, bufferSizeInBytes int) (tryWriteCloser, error) { - p := &driver{ - numChans: numChans, - bitDepthInBytes: bitDepthInBytes, - } - - // open a default ALSA audio device for blocking stream playback - cs := C.CString("default") - defer C.free(unsafe.Pointer(cs)) - if errCode := C.snd_pcm_open(&p.handle, cs, C.SND_PCM_STREAM_PLAYBACK, 0); errCode < 0 { - return nil, alsaError(errCode) - } - - // bufferSize is the total size of the main circular buffer fullness of this buffer - // oscilates somewhere between bufferSize and bufferSize-periodSize - bufferSize := C.snd_pcm_uframes_t(bufferSizeInBytes / (numChans * bitDepthInBytes)) - // periodSize is the number of samples that will be taken from the main circular - // buffer at once, we leave this value to bufferSize, because ALSA will change that - // to the maximum viable number, obviously lower than bufferSize - periodSize := bufferSize - - // choose the correct sample format according to bitDepthInBytes - var format C.snd_pcm_format_t - switch bitDepthInBytes { - case 1: - format = C.SND_PCM_FORMAT_U8 - case 2: - format = C.SND_PCM_FORMAT_S16_LE - default: - panic(fmt.Errorf("oto: bitDepthInBytes must be 1 or 2, got %d", bitDepthInBytes)) - } - - // set the device hardware parameters according to sampleRate, numChans, format, bufferSize - // and periodSize - // - // bufferSize and periodSize are passed as pointers, because they may be changed according - // to the wisdom of ALSA - // - // ALSA will try too keep them as close to what was requested as possible - if errCode := C.ALSA_hw_params(p.handle, C.uint(sampleRate), C.uint(numChans), format, &bufferSize, &periodSize); errCode < 0 { - p.Close() - return nil, alsaError(errCode) - } - - // Raspberry Pi 400 fix - for some reason the call to ALSA_hw_params can result in the bufferSize and periodSize - // being the same (this could be becuase the rpi driver does not drop the periodSize below 1024, whereas desktop - // Linux is happy to go lower). When the bufferSize and periodSize are the same it causes constant buffer underruns - // that stutter the audio continuously. - // - // So in the case where an RPi (or any other driver) returns the same buffer and period size we will change the - // buffer size to twice that of the period size and re-request hw params. - if bufferSize == periodSize { - bufferSize = periodSize * 2 - if errCode := C.ALSA_hw_params(p.handle, C.uint(sampleRate), C.uint(numChans), format, &bufferSize, &periodSize); errCode < 0 { - p.Close() - return nil, alsaError(errCode) - } - } - - // allocate the buffer of the size of the period, use the periodSize that we've got back - // from ALSA after it's wise decision - p.bufSamples = int(periodSize) - p.buf = []byte{} - - return p, nil -} - -func (p *driver) TryWrite(data []byte) (n int, err error) { - if p.handle == nil { - return - } - bufSize := p.bufSamples * p.numChans * p.bitDepthInBytes - for len(data) > 0 { - toWrite := min(len(data), max(0, bufSize-len(p.buf))) - p.buf = append(p.buf, data[:toWrite]...) - data = data[toWrite:] - n += toWrite - - // our buffer is not full and we've used up all the data, we'll keep them and finish - if len(p.buf) < bufSize { - break - } - - // write samples to the main circular buffer - wrote := C.snd_pcm_writei(p.handle, unsafe.Pointer(&p.buf[0]), C.snd_pcm_uframes_t(p.bufSamples)) - if wrote == -C.EPIPE { - // Underrun! - if errCode := C.snd_pcm_prepare(p.handle); errCode < 0 { - return 0, alsaError(errCode) - } - continue - } - if wrote < 0 { - // an error occurred while writing samples - return 0, alsaError(C.int(wrote)) - } - p.buf = p.buf[int(wrote)*p.numChans*p.bitDepthInBytes:] - } - return n, nil -} - -func (p *driver) Close() error { - // drop the remaining unprocessed samples in the main circular buffer - if errCode := C.snd_pcm_drop(p.handle); errCode < 0 { - return alsaError(errCode) - } - if errCode := C.snd_pcm_close(p.handle); errCode < 0 { - return alsaError(errCode) - } - p.handle = nil - return nil -} - -func (d *driver) tryWriteCanReturnWithoutWaiting() bool { - return true -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_macos.m b/vendor/github.com/hajimehoshi/oto/driver_macos.m deleted file mode 100644 index 5a069c8..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_macos.m +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2020 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build darwin && !ios && !js -// +build darwin,!ios,!js - -#import - -#include "_cgo_export.h" - -@interface OtoNotificationObserver : NSObject { -} - -@end - -@implementation OtoNotificationObserver { -} - -- (void)receiveSleepNote:(NSNotification *)note { - oto_setGlobalPause(); -} - -- (void)receiveWakeNote:(NSNotification *)note { - oto_setGlobalResume(); -} - -@end - -// oto_setNotificationHandler sets a handler for sleep/wake notifications. -void oto_setNotificationHandler() { - OtoNotificationObserver *observer = [[OtoNotificationObserver alloc] init]; - - [[[NSWorkspace sharedWorkspace] notificationCenter] - addObserver:observer - selector:@selector(receiveSleepNote:) - name:NSWorkspaceWillSleepNotification - object:NULL]; - [[[NSWorkspace sharedWorkspace] notificationCenter] - addObserver:observer - selector:@selector(receiveWakeNote:) - name:NSWorkspaceDidWakeNotification - object:NULL]; -} - -bool oto_isBackground(void) { - // TODO: Should this be implemented? - return false; -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_openal.go b/vendor/github.com/hajimehoshi/oto/driver_openal.go deleted file mode 100644 index ac04c6e..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_openal.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2015 Hajime Hoshi -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build (freebsd || openbsd) && !js && !android -// +build freebsd openbsd -// +build !js -// +build !android - -package oto - -// #cgo freebsd pkg-config: openal -// #cgo openbsd pkg-config: openal -// -// #include -// -// #ifdef __APPLE__ -// #include -// #include -// #else -// #include -// #include -// #endif -// -// static uintptr_t _alcOpenDevice(const ALCchar* name) { -// return (uintptr_t)alcOpenDevice(name); -// } -// -// static ALCboolean _alcCloseDevice(uintptr_t device) { -// return alcCloseDevice((void*)device); -// } -// -// static uintptr_t _alcCreateContext(uintptr_t device, const ALCint* attrList) { -// return (uintptr_t)alcCreateContext((void*)device, attrList); -// } -// -// static ALCenum _alcGetError(uintptr_t device) { -// return alcGetError((void*)device); -// } -// -// static void _alcMakeContextCurrent(uintptr_t context) { -// alcMakeContextCurrent((void*)context); -// } -// -// static void _alcDestroyContext(uintptr_t context) { -// alcDestroyContext((void*)context); -// } -import "C" - -import ( - "errors" - "fmt" - "runtime" - "unsafe" -) - -// As x/mobile/exp/audio/al is broken on macOS (https://github.com/golang/go/issues/15075), -// and that doesn't support FreeBSD, use OpenAL directly here. - -type driver struct { - // alContext represents a pointer to ALCcontext. The type is uintptr since the value - // can be 0x18 on macOS, which is invalid as a pointer value, and this might cause - // GC errors. - alContext alContext - alDevice alDevice - alDeviceName string - alSource C.ALuint - sampleRate int - isClosed bool - alFormat C.ALenum - - bufs []C.ALuint - tmp []byte - bufferSize int -} - -// alContext is a pointer to OpenAL context. -// The value is not unsafe.Pointer for C.ALCcontext but uintptr, -// because device pointer value can be an invalid value as a pointer on macOS, -// and Cgo pointer checker complains (#65). -type alContext uintptr - -// alDevice is a pointer to OpenAL device. -type alDevice uintptr - -func (a alDevice) getError() error { - switch c := C._alcGetError(C.uintptr_t(a)); c { - case C.ALC_NO_ERROR: - return nil - case C.ALC_INVALID_DEVICE: - return errors.New("OpenAL error: invalid device") - case C.ALC_INVALID_CONTEXT: - return errors.New("OpenAL error: invalid context") - case C.ALC_INVALID_ENUM: - return errors.New("OpenAL error: invalid enum") - case C.ALC_INVALID_VALUE: - return errors.New("OpenAL error: invalid value") - case C.ALC_OUT_OF_MEMORY: - return errors.New("OpenAL error: out of memory") - default: - return fmt.Errorf("OpenAL error: code %d", c) - } -} - -func alFormat(channelNum, bitDepthInBytes int) C.ALenum { - switch { - case channelNum == 1 && bitDepthInBytes == 1: - return C.AL_FORMAT_MONO8 - case channelNum == 1 && bitDepthInBytes == 2: - return C.AL_FORMAT_MONO16 - case channelNum == 2 && bitDepthInBytes == 1: - return C.AL_FORMAT_STEREO8 - case channelNum == 2 && bitDepthInBytes == 2: - return C.AL_FORMAT_STEREO16 - } - panic(fmt.Sprintf("oto: invalid channel num (%d) or bytes per sample (%d)", channelNum, bitDepthInBytes)) -} - -const numBufs = 2 - -func newDriver(sampleRate, channelNum, bitDepthInBytes, bufferSizeInBytes int) (tryWriteCloser, error) { - name := C.alcGetString(nil, C.ALC_DEFAULT_DEVICE_SPECIFIER) - d := alDevice(C._alcOpenDevice((*C.ALCchar)(name))) - if d == 0 { - return nil, fmt.Errorf("oto: alcOpenDevice must not return null") - } - c := alContext(C._alcCreateContext(C.uintptr_t(d), nil)) - if c == 0 { - return nil, fmt.Errorf("oto: alcCreateContext must not return null") - } - - // Don't check getError until making the current context is done. - // Linux might fail this check even though it succeeds (hajimehoshi/ebiten#204). - C._alcMakeContextCurrent(C.uintptr_t(c)) - if err := d.getError(); err != nil { - return nil, fmt.Errorf("oto: Activate: %v", err) - } - - s := C.ALuint(0) - C.alGenSources(1, &s) - if err := d.getError(); err != nil { - return nil, fmt.Errorf("oto: NewSource: %v", err) - } - - p := &driver{ - alContext: c, - alDevice: d, - alSource: s, - alDeviceName: C.GoString((*C.char)(name)), - sampleRate: sampleRate, - alFormat: alFormat(channelNum, bitDepthInBytes), - bufs: make([]C.ALuint, numBufs), - bufferSize: bufferSizeInBytes, - } - runtime.SetFinalizer(p, (*driver).Close) - C.alGenBuffers(C.ALsizei(numBufs), &p.bufs[0]) - C.alSourcePlay(p.alSource) - - if err := d.getError(); err != nil { - return nil, fmt.Errorf("oto: Play: %v", err) - } - - return p, nil -} - -func (p *driver) TryWrite(data []byte) (int, error) { - if err := p.alDevice.getError(); err != nil { - return 0, fmt.Errorf("oto: starting Write: %v", err) - } - n := min(len(data), max(0, p.bufferSize-len(p.tmp))) - p.tmp = append(p.tmp, data[:n]...) - if len(p.tmp) < p.bufferSize { - return n, nil - } - - pn := C.ALint(0) - C.alGetSourcei(p.alSource, C.AL_BUFFERS_PROCESSED, &pn) - - if pn > 0 { - bufs := make([]C.ALuint, pn) - C.alSourceUnqueueBuffers(p.alSource, C.ALsizei(len(bufs)), &bufs[0]) - if err := p.alDevice.getError(); err != nil { - return 0, fmt.Errorf("oto: UnqueueBuffers: %v", err) - } - p.bufs = append(p.bufs, bufs...) - } - - if len(p.bufs) == 0 { - return n, nil - } - - buf := p.bufs[0] - p.bufs = p.bufs[1:] - C.alBufferData(buf, p.alFormat, unsafe.Pointer(&p.tmp[0]), C.ALsizei(p.bufferSize), C.ALsizei(p.sampleRate)) - C.alSourceQueueBuffers(p.alSource, 1, &buf) - if err := p.alDevice.getError(); err != nil { - return 0, fmt.Errorf("oto: QueueBuffer: %v", err) - } - - state := C.ALint(0) - C.alGetSourcei(p.alSource, C.AL_SOURCE_STATE, &state) - if state == C.AL_STOPPED || state == C.AL_INITIAL { - C.alSourceRewind(p.alSource) - C.alSourcePlay(p.alSource) - if err := p.alDevice.getError(); err != nil { - return 0, fmt.Errorf("oto: Rewind or Play: %v", err) - } - } - - p.tmp = nil - return n, nil -} - -func (p *driver) Close() error { - if err := p.alDevice.getError(); err != nil { - return fmt.Errorf("oto: starting Close: %v", err) - } - if p.isClosed { - return nil - } - - n := C.ALint(0) - C.alGetSourcei(p.alSource, C.AL_BUFFERS_QUEUED, &n) - if 0 < n { - bs := make([]C.ALuint, n) - C.alSourceUnqueueBuffers(p.alSource, C.ALsizei(len(bs)), &bs[0]) - p.bufs = append(p.bufs, bs...) - } - - C.alSourceStop(p.alSource) - C.alDeleteSources(1, &p.alSource) - if len(p.bufs) != 0 { - C.alDeleteBuffers(C.ALsizei(numBufs), &p.bufs[0]) - } - C._alcDestroyContext(C.uintptr_t(p.alContext)) - - if err := p.alDevice.getError(); err != nil { - return fmt.Errorf("oto: CloseDevice: %v", err) - } - - b := C._alcCloseDevice(C.uintptr_t(p.alDevice)) - if b == C.ALC_FALSE { - return fmt.Errorf("oto: CloseDevice: %s failed to close", p.alDeviceName) - } - - p.isClosed = true - runtime.SetFinalizer(p, nil) - return nil -} - -func (d *driver) tryWriteCanReturnWithoutWaiting() bool { - return true -} diff --git a/vendor/github.com/hajimehoshi/oto/driver_windows.go b/vendor/github.com/hajimehoshi/oto/driver_windows.go deleted file mode 100644 index 8f295e0..0000000 --- a/vendor/github.com/hajimehoshi/oto/driver_windows.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2015 Hajime Hoshi -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !js -// +build !js - -package oto - -import ( - "errors" - "runtime" - "unsafe" -) - -type header struct { - buffer []byte - waveHdr *wavehdr -} - -func newHeader(waveOut uintptr, bufferSize int) (*header, error) { - h := &header{ - buffer: make([]byte, bufferSize), - } - h.waveHdr = &wavehdr{ - lpData: uintptr(unsafe.Pointer(&h.buffer[0])), - dwBufferLength: uint32(bufferSize), - } - if err := waveOutPrepareHeader(waveOut, h.waveHdr); err != nil { - return nil, err - } - return h, nil -} - -func (h *header) Write(waveOut uintptr, data []byte) error { - if len(data) != len(h.buffer) { - return errors.New("oto: len(data) must equal to len(h.buffer)") - } - copy(h.buffer, data) - if err := waveOutWrite(waveOut, h.waveHdr); err != nil { - return err - } - return nil -} - -type driver struct { - out uintptr - headers []*header - tmp []byte - bufferSize int -} - -func newDriver(sampleRate, channelNum, bitDepthInBytes, bufferSizeInBytes int) (tryWriteCloser, error) { - numBlockAlign := channelNum * bitDepthInBytes - f := &waveformatex{ - wFormatTag: waveFormatPCM, - nChannels: uint16(channelNum), - nSamplesPerSec: uint32(sampleRate), - nAvgBytesPerSec: uint32(sampleRate * numBlockAlign), - wBitsPerSample: uint16(bitDepthInBytes * 8), - nBlockAlign: uint16(numBlockAlign), - } - w, err := waveOutOpen(f) - const elementNotFound = 1168 - if e, ok := err.(*winmmError); ok && e.errno == elementNotFound { - // No device was found. Return the dummy device. - // TODO: Retry to open the device when possible. - return newDummyDriver(sampleRate, channelNum, bitDepthInBytes), nil - } - if err != nil { - return nil, err - } - - const numBufs = 2 - p := &driver{ - out: w, - headers: make([]*header, numBufs), - bufferSize: bufferSizeInBytes, - } - runtime.SetFinalizer(p, (*driver).Close) - for i := range p.headers { - var err error - p.headers[i], err = newHeader(w, p.bufferSize) - if err != nil { - return nil, err - } - } - return p, nil -} - -func (p *driver) TryWrite(data []byte) (int, error) { - n := min(len(data), max(0, p.bufferSize-len(p.tmp))) - p.tmp = append(p.tmp, data[:n]...) - if len(p.tmp) < p.bufferSize { - return n, nil - } - - var headerToWrite *header - for _, h := range p.headers { - // TODO: Need to check WHDR_DONE? - if h.waveHdr.dwFlags&whdrInqueue == 0 { - headerToWrite = h - break - } - } - if headerToWrite == nil { - return n, nil - } - - if err := headerToWrite.Write(p.out, p.tmp); err != nil { - // This error can happen when e.g. a new HDMI connection is detected (#51). - const errorNotFound = 1168 - werr := err.(*winmmError) - if werr.fname == "waveOutWrite" && werr.errno == errorNotFound { - return 0, nil - } - return 0, err - } - - p.tmp = p.tmp[:0] - return n, nil -} - -func (p *driver) Close() error { - runtime.SetFinalizer(p, nil) - - // TODO: Call waveOutUnprepareHeader here - - if err := waveOutReset(p.out); err != nil { - return err - } - - if err := waveOutClose(p.out); err != nil { - return err - } - - return nil -} - -func (d *driver) tryWriteCanReturnWithoutWaiting() bool { - return true -} diff --git a/vendor/github.com/hajimehoshi/oto/dummy.go b/vendor/github.com/hajimehoshi/oto/dummy.go deleted file mode 100644 index 258d807..0000000 --- a/vendor/github.com/hajimehoshi/oto/dummy.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package oto - -import ( - "time" -) - -type dummyDriver struct { - sampleRate int - channelNum int - bitDepthInBytes int - - current int -} - -func newDummyDriver(sampleRate, channelNum, bitDepthInBytes int) *dummyDriver { - return &dummyDriver{ - sampleRate: sampleRate, - channelNum: channelNum, - bitDepthInBytes: bitDepthInBytes, - } -} - -func (d *dummyDriver) bytes(t time.Duration) int { - return int(float64(d.sampleRate*d.channelNum*d.bitDepthInBytes) * float64(t) / float64(time.Second)) -} - -func (d *dummyDriver) TryWrite(buf []byte) (int, error) { - d.current += len(buf) - b := d.bytes(100 * time.Millisecond) - for d.current >= b { - time.Sleep(time.Second) - d.current -= b - } - return len(buf), nil -} - -func (d *dummyDriver) Close() error { - return nil -} - -func (d *dummyDriver) tryWriteCanReturnWithoutWaiting() bool { - return false -} diff --git a/vendor/github.com/hajimehoshi/oto/internal/mux/mux.go b/vendor/github.com/hajimehoshi/oto/internal/mux/mux.go deleted file mode 100644 index b60d38b..0000000 --- a/vendor/github.com/hajimehoshi/oto/internal/mux/mux.go +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package mux - -import ( - "bufio" - "io" - "runtime" - "sync" -) - -// Mux is a multiplexer for multiple io.Reader objects. -type Mux struct { - channelNum int - bitDepthInBytes int - readers map[io.Reader]*bufio.Reader - closed bool - - m sync.RWMutex -} - -// New creates a new Mux with the specified number of channels and bit depth. -func New(channelNum, bitDepthInBytes int) *Mux { - m := &Mux{ - channelNum: channelNum, - bitDepthInBytes: bitDepthInBytes, - readers: map[io.Reader]*bufio.Reader{}, - } - runtime.SetFinalizer(m, (*Mux).Close) - return m -} - -// Read reads data from all of its readers, interprets it as samples with the bit depth -// specified during its creation, then adds all of the samples together and fills the buf -// slice with the result of this. -// -// If there are no readers, Read fills in some zeros to prevent a program from freezing. -func (m *Mux) Read(buf []byte) (int, error) { - m.m.Lock() - defer m.m.Unlock() - - if m.closed { - return 0, io.EOF - } - - if len(m.readers) == 0 { - // When there is no reader, Read should return with 0s or Read caller can block forever. - // See https://github.com/hajimehoshi/go-mp3/issues/28 - n := 256 - if len(buf) < 256 { - n = len(buf) - } - - switch m.bitDepthInBytes { - case 1: - const offset = 128 - for i := 0; i < n; i++ { - buf[i] = offset - } - return n, nil - case 2: - for i := 0; i < n; i++ { - buf[i] = 0 - } - return n, nil - default: - panic("not reached") - } - } - - bs := m.channelNum * m.bitDepthInBytes - l := len(buf) - l = l / bs * bs // Adjust the length in order not to mix different channels. - - var bufs [][]byte - for _, p := range m.readers { - peeked, err := p.Peek(l) - if err != nil && err != bufio.ErrBufferFull && err != io.EOF { - return 0, err - } - if l > len(peeked) { - l = len(peeked) - l = l / bs * bs - } - bufs = append(bufs, peeked[:l]) - } - - if l == 0 { - // Returning 0 without error can block the caller of Read forever. Call Gosched to encourage context switching. - runtime.Gosched() - return 0, nil - } - - for _, p := range m.readers { - if _, err := p.Discard(l); err != nil && err != io.EOF { - return 0, err - } - } - - switch m.bitDepthInBytes { - case 1: - const ( - max = 127 - min = -128 - offset = 128 - ) - for i := 0; i < l; i++ { - x := 0 - for _, b := range bufs { - x += int(b[i]) - offset - } - if x > max { - x = max - } - if x < min { - x = min - } - buf[i] = byte(x + offset) - } - case 2: - const ( - max = (1 << 15) - 1 - min = -(1 << 15) - ) - for i := 0; i < l/2; i++ { - x := 0 - for _, b := range bufs { - x += int(int16(b[2*i]) | (int16(b[2*i+1]) << 8)) - } - if x > max { - x = max - } - if x < min { - x = min - } - buf[2*i] = byte(x) - buf[2*i+1] = byte(x >> 8) - } - default: - panic("not reached") - } - - return l, nil -} - -// Close invalidates the Mux. It doesn't close its readers. -func (m *Mux) Close() error { - m.m.Lock() - runtime.SetFinalizer(m, nil) - m.readers = nil - m.closed = true - m.m.Unlock() - return nil -} - -// AddSource adds a reader to the Mux. -func (m *Mux) AddSource(source io.Reader) { - m.m.Lock() - if m.closed { - panic("mux: already closed") - } - if _, ok := m.readers[source]; ok { - panic("mux: the io.Reader cannot be added multiple times") - } - m.readers[source] = bufio.NewReaderSize(source, 256) - m.m.Unlock() -} - -// RemoveSource removes a reader from the Mux. -func (m *Mux) RemoveSource(source io.Reader) { - m.m.Lock() - if m.closed { - panic("mux: already closed") - } - if _, ok := m.readers[source]; !ok { - panic("mux: the io.Reader is already removed") - } - delete(m.readers, source) - m.m.Unlock() -} - -// Sources returns all the registered readers. -func (m *Mux) Sources() []io.Reader { - m.m.Lock() - defer m.m.Unlock() - - var rs []io.Reader - for r := range m.readers { - rs = append(rs, r) - } - return rs -} diff --git a/vendor/github.com/hajimehoshi/oto/pipe_gopherjs.go b/vendor/github.com/hajimehoshi/oto/pipe_gopherjs.go deleted file mode 100644 index b8467de..0000000 --- a/vendor/github.com/hajimehoshi/oto/pipe_gopherjs.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build js && !wasm -// +build js,!wasm - -package oto - -import ( - "io" -) - -const pipeBufSize = 4096 - -// pipe returns a set of an io.ReadCloser and an io.WriteCloser. -// -// This is basically same as io.Pipe, but is implemented in more effient way under the assumption that -// this works on a single thread environment so that locks are not required. -func pipe() (io.ReadCloser, io.WriteCloser) { - w := &pipeWriter{ - consumed: make(chan struct{}), - provided: make(chan struct{}), - closed: make(chan struct{}), - } - r := &pipeReader{ - w: w, - closed: make(chan struct{}), - } - w.r = r - return r, w -} - -type pipeReader struct { - w *pipeWriter - closed chan struct{} -} - -func (r *pipeReader) Read(buf []byte) (int, error) { - // If this returns 0 with no errors, the caller might block forever on browsers. - // For example, bufio.Reader tries to Read until any byte can be read, but context switch never happens on browsers. - for len(r.w.buf) == 0 { - select { - case <-r.w.provided: - case <-r.w.closed: - if len(r.w.buf) == 0 { - return 0, io.EOF - } - case <-r.closed: - return 0, io.ErrClosedPipe - } - } - notify := len(r.w.buf) >= pipeBufSize && len(buf) > 0 - n := copy(buf, r.w.buf) - r.w.buf = r.w.buf[n:] - if notify { - go func() { - r.w.consumed <- struct{}{} - }() - } - return n, nil -} - -func (r *pipeReader) Close() error { - close(r.closed) - return nil -} - -type pipeWriter struct { - r *pipeReader - buf []byte - closed chan struct{} - consumed chan struct{} - provided chan struct{} -} - -func (w *pipeWriter) Write(buf []byte) (int, error) { - for len(w.buf) >= pipeBufSize { - select { - case <-w.consumed: - case <-w.r.closed: - return 0, io.ErrClosedPipe - case <-w.closed: - return 0, io.ErrClosedPipe - } - } - notify := len(w.buf) == 0 && len(buf) > 0 - w.buf = append(w.buf, buf...) - if notify { - w.provided <- struct{}{} - } - return len(buf), nil -} - -func (w *pipeWriter) Close() error { - close(w.closed) - return nil -} diff --git a/vendor/github.com/hajimehoshi/oto/player.go b/vendor/github.com/hajimehoshi/oto/player.go deleted file mode 100644 index 2cb6abd..0000000 --- a/vendor/github.com/hajimehoshi/oto/player.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2017 Hajime Hoshi -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package oto offers io.Writer to play sound on multiple platforms. -package oto - -import ( - "io" - "runtime" -) - -// Player is a PCM (pulse-code modulation) audio player. -// Player implements io.WriteCloser. -// Use Write method to play samples. -type Player struct { - context *Context - r io.ReadCloser - w io.WriteCloser -} - -func newPlayer(context *Context) *Player { - r, w := pipe() - p := &Player{ - context: context, - r: r, - w: w, - } - context.mux.AddSource(r) - runtime.SetFinalizer(p, (*Player).Close) - return p -} - -// Write writes PCM samples to the Player. -// -// The format is as follows: -// [data] = [sample 1] [sample 2] [sample 3] ... -// [sample *] = [channel 1] ... -// [channel *] = [byte 1] [byte 2] ... -// Byte ordering is little endian. -// -// The data is first put into the Player's buffer. Once the buffer is full, Player starts playing -// the data and empties the buffer. -// -// If the supplied data doesn't fit into the Player's buffer, Write block until a sufficient amount -// of data has been played (or at least started playing) and the remaining unplayed data fits into -// the buffer. -// -// Note, that the Player won't start playing anything until the buffer is full. -func (p *Player) Write(buf []byte) (int, error) { - select { - case err := <-p.context.errCh: - return 0, err - default: - } - n, err := p.w.Write(buf) - // When the error is io.ErrClosedPipe, the context is already closed. - if err == io.ErrClosedPipe { - select { - case err := <-p.context.errCh: - return n, err - default: - } - } - return n, err -} - -// Close closes the Player and frees any resources associated with it. The Player is no longer -// usable after calling Close. -func (p *Player) Close() error { - runtime.SetFinalizer(p, nil) - - // Already closed - if p.context == nil { - return nil - } - - select { - case err := <-p.context.errCh: - return err - default: - } - - // Close the pipe writer before RemoveSource, or Read-ing in the mux takes forever. - if err := p.w.Close(); err != nil { - return err - } - - p.context.mux.RemoveSource(p.r) - p.context = nil - - // Close the pipe reader after RemoveSource, or ErrClosedPipe happens at Read-ing. - return p.r.Close() -} - -func max(a, b int) int { - if a < b { - return b - } - return a -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/github.com/hajimehoshi/oto/slice_js.go b/vendor/github.com/hajimehoshi/oto/slice_js.go deleted file mode 100644 index 973a7a5..0000000 --- a/vendor/github.com/hajimehoshi/oto/slice_js.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019 The Oto Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build go1.13 -// +build go1.13 - -package oto - -import ( - "reflect" - "runtime" - "syscall/js" - "unsafe" -) - -func float32SliceToTypedArray(s []float32) (js.Value, func()) { - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 4 - h.Cap *= 4 - bs := *(*[]byte)(unsafe.Pointer(h)) - - a := js.Global().Get("Uint8Array").New(len(bs)) - js.CopyBytesToJS(a, bs) - runtime.KeepAlive(s) - buf := a.Get("buffer") - return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {} -} - -func copyFloat32sToJS(v js.Value, s []float32) { - h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) - h.Len *= 4 - h.Cap *= 4 - bs := *(*[]byte)(unsafe.Pointer(h)) - - js.CopyBytesToJS(v, bs) - runtime.KeepAlive(s) -} diff --git a/vendor/github.com/hajimehoshi/oto/winmm_windows.go b/vendor/github.com/hajimehoshi/oto/winmm_windows.go deleted file mode 100644 index 73aae06..0000000 --- a/vendor/github.com/hajimehoshi/oto/winmm_windows.go +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2017 Hajime Hoshi -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !js -// +build !js - -package oto - -import ( - "fmt" - "runtime" - "unsafe" - - "golang.org/x/sys/windows" -) - -var ( - winmm = windows.NewLazySystemDLL("winmm") -) - -var ( - procWaveOutOpen = winmm.NewProc("waveOutOpen") - procWaveOutClose = winmm.NewProc("waveOutClose") - procWaveOutPrepareHeader = winmm.NewProc("waveOutPrepareHeader") - procWaveOutReset = winmm.NewProc("waveOutReset") - procWaveOutWrite = winmm.NewProc("waveOutWrite") -) - -type wavehdr struct { - lpData uintptr - dwBufferLength uint32 - dwBytesRecorded uint32 - dwUser uintptr - dwFlags uint32 - dwLoops uint32 - lpNext uintptr - reserved uintptr -} - -type waveformatex struct { - wFormatTag uint16 - nChannels uint16 - nSamplesPerSec uint32 - nAvgBytesPerSec uint32 - nBlockAlign uint16 - wBitsPerSample uint16 - cbSize uint16 -} - -const ( - waveFormatPCM = 1 - whdrInqueue = 16 -) - -type mmresult uint - -const ( - mmsyserrNoerror mmresult = 0 - mmsyserrError mmresult = 1 - mmsyserrBaddeviceid mmresult = 2 - mmsyserrAllocated mmresult = 4 - mmsyserrInvalidhandle mmresult = 5 - mmsyserrNodriver mmresult = 6 - mmsyserrNomem mmresult = 7 - waveerrBadformat mmresult = 32 - waveerrStillplaying mmresult = 33 - waveerrUnprepared mmresult = 34 - waveerrSync mmresult = 35 -) - -func (m mmresult) String() string { - switch m { - case mmsyserrNoerror: - return "MMSYSERR_NOERROR" - case mmsyserrError: - return "MMSYSERR_ERROR" - case mmsyserrBaddeviceid: - return "MMSYSERR_BADDEVICEID" - case mmsyserrAllocated: - return "MMSYSERR_ALLOCATED" - case mmsyserrInvalidhandle: - return "MMSYSERR_INVALIDHANDLE" - case mmsyserrNodriver: - return "MMSYSERR_NODRIVER" - case mmsyserrNomem: - return "MMSYSERR_NOMEM" - case waveerrBadformat: - return "WAVEERR_BADFORMAT" - case waveerrStillplaying: - return "WAVEERR_STILLPLAYING" - case waveerrUnprepared: - return "WAVEERR_UNPREPARED" - case waveerrSync: - return "WAVEERR_SYNC" - } - return fmt.Sprintf("MMRESULT (%d)", m) -} - -type winmmError struct { - fname string - errno windows.Errno - mmresult mmresult -} - -func (e *winmmError) Error() string { - if e.errno != 0 { - return fmt.Sprintf("winmm error at %s: Errno: %d", e.fname, e.errno) - } - if e.mmresult != mmsyserrNoerror { - return fmt.Sprintf("winmm error at %s: %s", e.fname, e.mmresult) - } - return fmt.Sprintf("winmm error at %s", e.fname) -} - -func waveOutOpen(f *waveformatex) (uintptr, error) { - const ( - waveMapper = 0xffffffff - callbackNull = 0 - ) - var w uintptr - r, _, e := procWaveOutOpen.Call(uintptr(unsafe.Pointer(&w)), waveMapper, uintptr(unsafe.Pointer(f)), - 0, 0, callbackNull) - runtime.KeepAlive(f) - if e.(windows.Errno) != 0 { - return 0, &winmmError{ - fname: "waveOutOpen", - errno: e.(windows.Errno), - } - } - if mmresult(r) != mmsyserrNoerror { - return 0, &winmmError{ - fname: "waveOutOpen", - mmresult: mmresult(r), - } - } - return w, nil -} - -func waveOutClose(hwo uintptr) error { - r, _, e := procWaveOutClose.Call(hwo) - if e.(windows.Errno) != 0 { - return &winmmError{ - fname: "waveOutClose", - errno: e.(windows.Errno), - } - } - // WAVERR_STILLPLAYING is ignored. - if mmresult(r) != mmsyserrNoerror && mmresult(r) != waveerrStillplaying { - return &winmmError{ - fname: "waveOutClose", - mmresult: mmresult(r), - } - } - return nil -} - -func waveOutPrepareHeader(hwo uintptr, pwh *wavehdr) error { - r, _, e := procWaveOutPrepareHeader.Call(hwo, uintptr(unsafe.Pointer(pwh)), unsafe.Sizeof(wavehdr{})) - runtime.KeepAlive(pwh) - if e.(windows.Errno) != 0 { - return &winmmError{ - fname: "waveOutPrepareHeader", - errno: e.(windows.Errno), - } - } - if mmresult(r) != mmsyserrNoerror { - return &winmmError{ - fname: "waveOutPrepareHeader", - mmresult: mmresult(r), - } - } - return nil -} - -func waveOutReset(hwo uintptr) error { - r, _, e := procWaveOutReset.Call(hwo) - if e.(windows.Errno) != 0 { - return &winmmError{ - fname: "waveOutReset", - errno: e.(windows.Errno), - } - } - - if mmresult(r) != mmsyserrNoerror { - return &winmmError{ - fname: "waveOutReset", - mmresult: mmresult(r), - } - } - - return nil -} - -func waveOutWrite(hwo uintptr, pwh *wavehdr) error { - r, _, e := procWaveOutWrite.Call(hwo, uintptr(unsafe.Pointer(pwh)), unsafe.Sizeof(wavehdr{})) - runtime.KeepAlive(pwh) - if e.(windows.Errno) != 0 { - return &winmmError{ - fname: "waveOutWrite", - errno: e.(windows.Errno), - } - } - if mmresult(r) != mmsyserrNoerror { - return &winmmError{ - fname: "waveOutWrite", - mmresult: mmresult(r), - } - } - return nil -} diff --git a/vendor/github.com/rivo/uniseg/README.md b/vendor/github.com/rivo/uniseg/README.md index 25e9346..a8191b8 100644 --- a/vendor/github.com/rivo/uniseg/README.md +++ b/vendor/github.com/rivo/uniseg/README.md @@ -3,7 +3,7 @@ [![Go Reference](https://pkg.go.dev/badge/github.com/rivo/uniseg.svg)](https://pkg.go.dev/github.com/rivo/uniseg) [![Go Report](https://img.shields.io/badge/go%20report-A%2B-brightgreen.svg)](https://goreportcard.com/report/github.com/rivo/uniseg) -This Go package implements Unicode Text Segmentation according to [Unicode Standard Annex #29](https://unicode.org/reports/tr29/), Unicode Line Breaking according to [Unicode Standard Annex #14](https://unicode.org/reports/tr14/) (Unicode version 14.0.0), and monospace font string width calculation similar to [wcwidth](https://man7.org/linux/man-pages/man3/wcwidth.3.html). +This Go package implements Unicode Text Segmentation according to [Unicode Standard Annex #29](https://unicode.org/reports/tr29/), Unicode Line Breaking according to [Unicode Standard Annex #14](https://unicode.org/reports/tr14/) (Unicode version 15.0.0), and monospace font string width calculation similar to [wcwidth](https://man7.org/linux/man-pages/man3/wcwidth.3.html). ## Background @@ -73,7 +73,7 @@ for gr.Next() { ### Using the [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step) or [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString) Function -This is orders of magnitude faster than the `Graphemes` class, but it requires the handling of states and boundaries: +This avoids allocating a new `Graphemes` object but it requires the handling of states and boundaries: ```go str := "🇩🇪🏳️‍🌈" @@ -88,29 +88,7 @@ for len(str) > 0 { ### Advanced Examples -Breaking into grapheme clusters and evaluating line breaks: - -```go -str := "First line.\nSecond line." -state := -1 -var ( - c string - boundaries int -) -for len(str) > 0 { - c, str, boundaries, state = uniseg.StepString(str, state) - fmt.Print(c) - if boundaries&uniseg.MaskLine == uniseg.LineCanBreak { - fmt.Print("|") - } else if boundaries&uniseg.MaskLine == uniseg.LineMustBreak { - fmt.Print("‖") - } -} -// First |line. -// ‖Second |line.‖ -``` - -If you're only interested in word segmentation, use [`FirstWord`](https://pkg.go.dev/github.com/rivo/uniseg#FirstWord) or [`FirstWordInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstWordInString): +The [`Graphemes`](https://pkg.go.dev/github.com/rivo/uniseg#Graphemes) class offers the most convenient way to access all functionality of this package. But in some cases, it may be better to use the specialized functions directly. For example, if you're only interested in word segmentation, use [`FirstWord`](https://pkg.go.dev/github.com/rivo/uniseg#FirstWord) or [`FirstWordInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstWordInString): ```go str := "Hello, world!" @@ -133,6 +111,8 @@ Similarly, use - [`FirstSentence`](https://pkg.go.dev/github.com/rivo/uniseg#FirstSentence) or [`FirstSentenceInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstSentenceInString) for sentence segmentation only, and - [`FirstLineSegment`](https://pkg.go.dev/github.com/rivo/uniseg#FirstLineSegment) or [`FirstLineSegmentInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstLineSegmentInString) for line breaking / word wrapping (although using [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step) or [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString) is preferred as it will observe grapheme cluster boundaries). +If you're only interested in the width of characters, use [`FirstGraphemeCluster`](https://pkg.go.dev/github.com/rivo/uniseg#FirstGraphemeCluster) or [`FirstGraphemeClusterInString`](https://pkg.go.dev/github.com/rivo/uniseg#FirstGraphemeClusterInString). It is much faster than using [`Step`](https://pkg.go.dev/github.com/rivo/uniseg#Step), [`StepString`](https://pkg.go.dev/github.com/rivo/uniseg#StepString), or the [`Graphemes`](https://pkg.go.dev/github.com/rivo/uniseg#Graphemes) class because it does not include the logic for word / sentence / line boundaries. + Finally, if you need to reverse a string while preserving grapheme clusters, use [`ReverseString`](https://pkg.go.dev/github.com/rivo/uniseg#ReverseString): ```go diff --git a/vendor/github.com/rivo/uniseg/eastasianwidth.go b/vendor/github.com/rivo/uniseg/eastasianwidth.go index 661934a..5fc54d9 100644 --- a/vendor/github.com/rivo/uniseg/eastasianwidth.go +++ b/vendor/github.com/rivo/uniseg/eastasianwidth.go @@ -1,13 +1,13 @@ -package uniseg - // Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg + // eastAsianWidth are taken from -// https://www.unicode.org/Public/14.0.0/ucd/EastAsianWidth.txt +// https://www.unicode.org/Public/15.0.0/ucd/EastAsianWidth.txt // and -// https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt // ("Extended_Pictographic" only) -// on September 10, 2022. See https://www.unicode.org/license.html for the Unicode +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode // license agreement. var eastAsianWidth = [][3]int{ {0x0000, 0x001F, prN}, // Cc [32] .. @@ -504,6 +504,7 @@ var eastAsianWidth = [][3]int{ {0x0CE2, 0x0CE3, prN}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL {0x0CE6, 0x0CEF, prN}, // Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE {0x0CF1, 0x0CF2, prN}, // Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prN}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT {0x0D00, 0x0D01, prN}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU {0x0D02, 0x0D03, prN}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA {0x0D04, 0x0D0C, prN}, // Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L @@ -565,7 +566,7 @@ var eastAsianWidth = [][3]int{ {0x0EBD, 0x0EBD, prN}, // Lo LAO SEMIVOWEL SIGN NYO {0x0EC0, 0x0EC4, prN}, // Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI {0x0EC6, 0x0EC6, prN}, // Lm LAO KO LA - {0x0EC8, 0x0ECD, prN}, // Mn [6] LAO TONE MAI EK..LAO NIGGAHITA + {0x0EC8, 0x0ECE, prN}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN {0x0ED0, 0x0ED9, prN}, // Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE {0x0EDC, 0x0EDF, prN}, // Lo [4] LAO HO NO..LAO LETTER KHMU NYO {0x0F00, 0x0F00, prN}, // Lo TIBETAN SYLLABLE OM @@ -1916,6 +1917,7 @@ var eastAsianWidth = [][3]int{ {0x10EAB, 0x10EAC, prN}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK {0x10EAD, 0x10EAD, prN}, // Pd YEZIDI HYPHENATION MARK {0x10EB0, 0x10EB1, prN}, // Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prN}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA {0x10F00, 0x10F1C, prN}, // Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL {0x10F1D, 0x10F26, prN}, // No [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF {0x10F27, 0x10F27, prN}, // Lo OLD SOGDIAN LIGATURE AYIN-DALETH @@ -1998,6 +2000,8 @@ var eastAsianWidth = [][3]int{ {0x11236, 0x11237, prN}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA {0x11238, 0x1123D, prN}, // Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN {0x1123E, 0x1123E, prN}, // Mn KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prN}, // Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prN}, // Mn KHOJKI VOWEL SIGN VOCALIC R {0x11280, 0x11286, prN}, // Lo [7] MULTANI LETTER A..MULTANI LETTER GA {0x11288, 0x11288, prN}, // Lo MULTANI LETTER GHA {0x1128A, 0x1128D, prN}, // Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA @@ -2160,6 +2164,7 @@ var eastAsianWidth = [][3]int{ {0x11A9E, 0x11AA2, prN}, // Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2 {0x11AB0, 0x11ABF, prN}, // Lo [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA {0x11AC0, 0x11AF8, prN}, // Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL + {0x11B00, 0x11B09, prN}, // Po [10] DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU {0x11C00, 0x11C08, prN}, // Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L {0x11C0A, 0x11C2E, prN}, // Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA {0x11C2F, 0x11C2F, prN}, // Mc BHAIKSUKI VOWEL SIGN AA @@ -2205,6 +2210,19 @@ var eastAsianWidth = [][3]int{ {0x11EF3, 0x11EF4, prN}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U {0x11EF5, 0x11EF6, prN}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O {0x11EF7, 0x11EF8, prN}, // Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION + {0x11F00, 0x11F01, prN}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prN}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prN}, // Mc KAWI SIGN VISARGA + {0x11F04, 0x11F10, prN}, // Lo [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prN}, // Lo [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prN}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prN}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prN}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prN}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prN}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prN}, // Mn KAWI CONJOINER + {0x11F43, 0x11F4F, prN}, // Po [13] KAWI DANDA..KAWI PUNCTUATION CLOSING SPIRAL + {0x11F50, 0x11F59, prN}, // Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE {0x11FB0, 0x11FB0, prN}, // Lo LISU LETTER YHA {0x11FC0, 0x11FD4, prN}, // No [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH {0x11FD5, 0x11FDC, prN}, // So [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI @@ -2217,8 +2235,11 @@ var eastAsianWidth = [][3]int{ {0x12480, 0x12543, prN}, // Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU {0x12F90, 0x12FF0, prN}, // Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 {0x12FF1, 0x12FF2, prN}, // Po [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302 - {0x13000, 0x1342E, prN}, // Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 - {0x13430, 0x13438, prN}, // Cf [9] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT + {0x13000, 0x1342F, prN}, // Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x1343F, prN}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prN}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prN}, // Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prN}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED {0x14400, 0x14646, prN}, // Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 {0x16800, 0x16A38, prN}, // Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ {0x16A40, 0x16A5E, prN}, // Lo [31] MRO LETTER TA..MRO LETTER TEK @@ -2263,7 +2284,9 @@ var eastAsianWidth = [][3]int{ {0x1AFFD, 0x1AFFE, prW}, // Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 {0x1B000, 0x1B0FF, prW}, // Lo [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2 {0x1B100, 0x1B122, prW}, // Lo [35] HENTAIGANA LETTER RE-3..KATAKANA LETTER ARCHAIC WU + {0x1B132, 0x1B132, prW}, // Lo HIRAGANA LETTER SMALL KO {0x1B150, 0x1B152, prW}, // Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO + {0x1B155, 0x1B155, prW}, // Lo KATAKANA LETTER SMALL KO {0x1B164, 0x1B167, prW}, // Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N {0x1B170, 0x1B2FB, prW}, // Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB {0x1BC00, 0x1BC6A, prN}, // Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M @@ -2294,6 +2317,7 @@ var eastAsianWidth = [][3]int{ {0x1D200, 0x1D241, prN}, // So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 {0x1D242, 0x1D244, prN}, // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME {0x1D245, 0x1D245, prN}, // So GREEK MUSICAL LEIMMA + {0x1D2C0, 0x1D2D3, prN}, // No [20] KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN {0x1D2E0, 0x1D2F3, prN}, // No [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN {0x1D300, 0x1D356, prN}, // So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING {0x1D360, 0x1D378, prN}, // No [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE @@ -2353,11 +2377,14 @@ var eastAsianWidth = [][3]int{ {0x1DF00, 0x1DF09, prN}, // Ll [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK {0x1DF0A, 0x1DF0A, prN}, // Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK {0x1DF0B, 0x1DF1E, prN}, // Ll [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prN}, // Ll [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK {0x1E000, 0x1E006, prN}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE {0x1E008, 0x1E018, prN}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU {0x1E01B, 0x1E021, prN}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI {0x1E023, 0x1E024, prN}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS {0x1E026, 0x1E02A, prN}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prN}, // Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prN}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I {0x1E100, 0x1E12C, prN}, // Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W {0x1E130, 0x1E136, prN}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D {0x1E137, 0x1E13D, prN}, // Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER @@ -2370,6 +2397,10 @@ var eastAsianWidth = [][3]int{ {0x1E2EC, 0x1E2EF, prN}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI {0x1E2F0, 0x1E2F9, prN}, // Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE {0x1E2FF, 0x1E2FF, prN}, // Sc WANCHO NGUN SIGN + {0x1E4D0, 0x1E4EA, prN}, // Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prN}, // Lm NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prN}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prN}, // Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE {0x1E7E0, 0x1E7E6, prN}, // Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO {0x1E7E8, 0x1E7EB, prN}, // Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE {0x1E7ED, 0x1E7EE, prN}, // Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE @@ -2498,13 +2529,14 @@ var eastAsianWidth = [][3]int{ {0x1F6D0, 0x1F6D2, prW}, // So [3] PLACE OF WORSHIP..SHOPPING TROLLEY {0x1F6D3, 0x1F6D4, prN}, // So [2] STUPA..PAGODA {0x1F6D5, 0x1F6D7, prW}, // So [3] HINDU TEMPLE..ELEVATOR - {0x1F6DD, 0x1F6DF, prW}, // So [3] PLAYGROUND SLIDE..RING BUOY + {0x1F6DC, 0x1F6DF, prW}, // So [4] WIRELESS..RING BUOY {0x1F6E0, 0x1F6EA, prN}, // So [11] HAMMER AND WRENCH..NORTHEAST-POINTING AIRPLANE {0x1F6EB, 0x1F6EC, prW}, // So [2] AIRPLANE DEPARTURE..AIRPLANE ARRIVING {0x1F6F0, 0x1F6F3, prN}, // So [4] SATELLITE..PASSENGER SHIP {0x1F6F4, 0x1F6FC, prW}, // So [9] SCOOTER..ROLLER SKATE - {0x1F700, 0x1F773, prN}, // So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE - {0x1F780, 0x1F7D8, prN}, // So [89] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NEGATIVE CIRCLED SQUARE + {0x1F700, 0x1F776, prN}, // So [119] ALCHEMICAL SYMBOL FOR QUINTESSENCE..LUNAR ECLIPSE + {0x1F77B, 0x1F77F, prN}, // So [5] HAUMEA..ORCUS + {0x1F780, 0x1F7D9, prN}, // So [90] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NINE POINTED WHITE STAR {0x1F7E0, 0x1F7EB, prW}, // So [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE {0x1F7F0, 0x1F7F0, prW}, // So HEAVY EQUALS SIGN {0x1F800, 0x1F80B, prN}, // So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD @@ -2521,22 +2553,20 @@ var eastAsianWidth = [][3]int{ {0x1F947, 0x1F9FF, prW}, // So [185] FIRST PLACE MEDAL..NAZAR AMULET {0x1FA00, 0x1FA53, prN}, // So [84] NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP {0x1FA60, 0x1FA6D, prN}, // So [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER - {0x1FA70, 0x1FA74, prW}, // So [5] BALLET SHOES..THONG SANDAL - {0x1FA78, 0x1FA7C, prW}, // So [5] DROP OF BLOOD..CRUTCH - {0x1FA80, 0x1FA86, prW}, // So [7] YO-YO..NESTING DOLLS - {0x1FA90, 0x1FAAC, prW}, // So [29] RINGED PLANET..HAMSA - {0x1FAB0, 0x1FABA, prW}, // So [11] FLY..NEST WITH EGGS - {0x1FAC0, 0x1FAC5, prW}, // So [6] ANATOMICAL HEART..PERSON WITH CROWN - {0x1FAD0, 0x1FAD9, prW}, // So [10] BLUEBERRIES..JAR - {0x1FAE0, 0x1FAE7, prW}, // So [8] MELTING FACE..BUBBLES - {0x1FAF0, 0x1FAF6, prW}, // So [7] HAND WITH INDEX FINGER AND THUMB CROSSED..HEART HANDS + {0x1FA70, 0x1FA7C, prW}, // So [13] BALLET SHOES..CRUTCH + {0x1FA80, 0x1FA88, prW}, // So [9] YO-YO..FLUTE + {0x1FA90, 0x1FABD, prW}, // So [46] RINGED PLANET..WING + {0x1FABF, 0x1FAC5, prW}, // So [7] GOOSE..PERSON WITH CROWN + {0x1FACE, 0x1FADB, prW}, // So [14] MOOSE..PEA POD + {0x1FAE0, 0x1FAE8, prW}, // So [9] MELTING FACE..SHAKING FACE + {0x1FAF0, 0x1FAF8, prW}, // So [9] HAND WITH INDEX FINGER AND THUMB CROSSED..RIGHTWARDS PUSHING HAND {0x1FB00, 0x1FB92, prN}, // So [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK {0x1FB94, 0x1FBCA, prN}, // So [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON {0x1FBF0, 0x1FBF9, prN}, // Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE {0x20000, 0x2A6DF, prW}, // Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF {0x2A6E0, 0x2A6FF, prW}, // Cn [32] .. - {0x2A700, 0x2B738, prW}, // Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 - {0x2B739, 0x2B73F, prW}, // Cn [7] .. + {0x2A700, 0x2B739, prW}, // Lo [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739 + {0x2B73A, 0x2B73F, prW}, // Cn [6] .. {0x2B740, 0x2B81D, prW}, // Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D {0x2B81E, 0x2B81F, prW}, // Cn [2] .. {0x2B820, 0x2CEA1, prW}, // Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 @@ -2547,7 +2577,9 @@ var eastAsianWidth = [][3]int{ {0x2FA1E, 0x2FA1F, prW}, // Cn [2] .. {0x2FA20, 0x2FFFD, prW}, // Cn [1502] .. {0x30000, 0x3134A, prW}, // Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A - {0x3134B, 0x3FFFD, prW}, // Cn [60595] .. + {0x3134B, 0x3134F, prW}, // Cn [5] .. + {0x31350, 0x323AF, prW}, // Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF + {0x323B0, 0x3FFFD, prW}, // Cn [56398] .. {0xE0001, 0xE0001, prN}, // Cf LANGUAGE TAG {0xE0020, 0xE007F, prN}, // Cf [96] TAG SPACE..CANCEL TAG {0xE0100, 0xE01EF, prA}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 diff --git a/vendor/github.com/rivo/uniseg/emojipresentation.go b/vendor/github.com/rivo/uniseg/emojipresentation.go index fd0f745..9b5f499 100644 --- a/vendor/github.com/rivo/uniseg/emojipresentation.go +++ b/vendor/github.com/rivo/uniseg/emojipresentation.go @@ -1,13 +1,13 @@ -package uniseg - // Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg + // emojiPresentation are taken from // // and -// https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt // ("Extended_Pictographic" only) -// on September 10, 2022. See https://www.unicode.org/license.html for the Unicode +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode // license agreement. var emojiPresentation = [][3]int{ {0x231A, 0x231B, prEmojiPresentation}, // E0.6 [2] (⌚..⌛) watch..hourglass done @@ -211,6 +211,7 @@ var emojiPresentation = [][3]int{ {0x1F6D1, 0x1F6D2, prEmojiPresentation}, // E3.0 [2] (🛑..🛒) stop sign..shopping cart {0x1F6D5, 0x1F6D5, prEmojiPresentation}, // E12.0 [1] (🛕) hindu temple {0x1F6D6, 0x1F6D7, prEmojiPresentation}, // E13.0 [2] (🛖..🛗) hut..elevator + {0x1F6DC, 0x1F6DC, prEmojiPresentation}, // E15.0 [1] (🛜) wireless {0x1F6DD, 0x1F6DF, prEmojiPresentation}, // E14.0 [3] (🛝..🛟) playground slide..ring buoy {0x1F6EB, 0x1F6EC, prEmojiPresentation}, // E1.0 [2] (🛫..🛬) airplane departure..airplane arrival {0x1F6F4, 0x1F6F6, prEmojiPresentation}, // E3.0 [3] (🛴..🛶) kick scooter..canoe @@ -267,19 +268,28 @@ var emojiPresentation = [][3]int{ {0x1F9E7, 0x1F9FF, prEmojiPresentation}, // E11.0 [25] (🧧..🧿) red envelope..nazar amulet {0x1FA70, 0x1FA73, prEmojiPresentation}, // E12.0 [4] (🩰..🩳) ballet shoes..shorts {0x1FA74, 0x1FA74, prEmojiPresentation}, // E13.0 [1] (🩴) thong sandal + {0x1FA75, 0x1FA77, prEmojiPresentation}, // E15.0 [3] (🩵..🩷) light blue heart..pink heart {0x1FA78, 0x1FA7A, prEmojiPresentation}, // E12.0 [3] (🩸..🩺) drop of blood..stethoscope {0x1FA7B, 0x1FA7C, prEmojiPresentation}, // E14.0 [2] (🩻..🩼) x-ray..crutch {0x1FA80, 0x1FA82, prEmojiPresentation}, // E12.0 [3] (🪀..🪂) yo-yo..parachute {0x1FA83, 0x1FA86, prEmojiPresentation}, // E13.0 [4] (🪃..🪆) boomerang..nesting dolls + {0x1FA87, 0x1FA88, prEmojiPresentation}, // E15.0 [2] (🪇..🪈) maracas..flute {0x1FA90, 0x1FA95, prEmojiPresentation}, // E12.0 [6] (🪐..🪕) ringed planet..banjo {0x1FA96, 0x1FAA8, prEmojiPresentation}, // E13.0 [19] (🪖..🪨) military helmet..rock {0x1FAA9, 0x1FAAC, prEmojiPresentation}, // E14.0 [4] (🪩..🪬) mirror ball..hamsa + {0x1FAAD, 0x1FAAF, prEmojiPresentation}, // E15.0 [3] (🪭..🪯) folding hand fan..khanda {0x1FAB0, 0x1FAB6, prEmojiPresentation}, // E13.0 [7] (🪰..🪶) fly..feather {0x1FAB7, 0x1FABA, prEmojiPresentation}, // E14.0 [4] (🪷..🪺) lotus..nest with eggs + {0x1FABB, 0x1FABD, prEmojiPresentation}, // E15.0 [3] (🪻..🪽) hyacinth..wing + {0x1FABF, 0x1FABF, prEmojiPresentation}, // E15.0 [1] (🪿) goose {0x1FAC0, 0x1FAC2, prEmojiPresentation}, // E13.0 [3] (🫀..🫂) anatomical heart..people hugging {0x1FAC3, 0x1FAC5, prEmojiPresentation}, // E14.0 [3] (🫃..🫅) pregnant man..person with crown + {0x1FACE, 0x1FACF, prEmojiPresentation}, // E15.0 [2] (🫎..🫏) moose..donkey {0x1FAD0, 0x1FAD6, prEmojiPresentation}, // E13.0 [7] (🫐..🫖) blueberries..teapot {0x1FAD7, 0x1FAD9, prEmojiPresentation}, // E14.0 [3] (🫗..🫙) pouring liquid..jar + {0x1FADA, 0x1FADB, prEmojiPresentation}, // E15.0 [2] (🫚..🫛) ginger root..pea pod {0x1FAE0, 0x1FAE7, prEmojiPresentation}, // E14.0 [8] (🫠..🫧) melting face..bubbles + {0x1FAE8, 0x1FAE8, prEmojiPresentation}, // E15.0 [1] (🫨) shaking face {0x1FAF0, 0x1FAF6, prEmojiPresentation}, // E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands + {0x1FAF7, 0x1FAF8, prEmojiPresentation}, // E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand } diff --git a/vendor/github.com/rivo/uniseg/gen_breaktest.go b/vendor/github.com/rivo/uniseg/gen_breaktest.go index e613c4c..6bfbeb5 100644 --- a/vendor/github.com/rivo/uniseg/gen_breaktest.go +++ b/vendor/github.com/rivo/uniseg/gen_breaktest.go @@ -32,7 +32,7 @@ import ( // We want to test against a specific version rather than the latest. When the // package is upgraded to a new version, change these to generate new tests. const ( - testCaseURL = `https://www.unicode.org/Public/14.0.0/ucd/auxiliary/%s.txt` + testCaseURL = `https://www.unicode.org/Public/15.0.0/ucd/auxiliary/%s.txt` ) func main() { @@ -76,9 +76,9 @@ func parse(url string) ([]byte, error) { buf := new(bytes.Buffer) buf.Grow(120 << 10) - buf.WriteString(`package uniseg + buf.WriteString(`// Code generated via go generate from gen_breaktest.go. DO NOT EDIT. -// Code generated via go generate from gen_breaktest.go. DO NOT EDIT. +package uniseg // ` + os.Args[3] + ` are Grapheme testcases taken from // ` + url + ` @@ -136,7 +136,9 @@ var ( // // E.g. for the input b="÷ 0020 × 0308 ÷ 1F1E6 ÷" // it will append -// "\u0020\u0308\U0001F1E6" +// +// "\u0020\u0308\U0001F1E6" +// // and "[][]rune{{0x0020,0x0308},{0x1F1E6},}" // to orig and exp respectively. // diff --git a/vendor/github.com/rivo/uniseg/gen_properties.go b/vendor/github.com/rivo/uniseg/gen_properties.go index 999d5ef..8992d2c 100644 --- a/vendor/github.com/rivo/uniseg/gen_properties.go +++ b/vendor/github.com/rivo/uniseg/gen_properties.go @@ -41,8 +41,8 @@ import ( // We want to test against a specific version rather than the latest. When the // package is upgraded to a new version, change these to generate new tests. const ( - propertyURL = `https://www.unicode.org/Public/14.0.0/ucd/%s.txt` - emojiURL = `https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt` + propertyURL = `https://www.unicode.org/Public/15.0.0/ucd/%s.txt` + emojiURL = `https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt` ) // The regular expression for a line containing a code point range property. @@ -178,6 +178,11 @@ func parse(propertyURL, emojiProperty string, includeGeneralCategory bool) (stri } } + // Avoid overflow during binary search. + if len(properties) >= 1<<31 { + return "", errors.New("too many properties") + } + // Sort properties. sort.Slice(properties, func(i, j int) bool { left, _ := strconv.ParseUint(properties[i][0], 16, 64) @@ -200,9 +205,9 @@ func parse(propertyURL, emojiProperty string, includeGeneralCategory bool) (stri // ` + emojiURL + ` // ("Extended_Pictographic" only)` } - buf.WriteString(`package uniseg + buf.WriteString(`// Code generated via go generate from gen_properties.go. DO NOT EDIT. -// Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg // ` + os.Args[3] + ` are taken from // ` + propertyURL + emojiComment + ` diff --git a/vendor/github.com/rivo/uniseg/grapheme.go b/vendor/github.com/rivo/uniseg/grapheme.go index 0086fc1..a0bcc55 100644 --- a/vendor/github.com/rivo/uniseg/grapheme.go +++ b/vendor/github.com/rivo/uniseg/grapheme.go @@ -222,7 +222,7 @@ func FirstGraphemeCluster(b []byte, state int) (cluster, rest []byte, width, new if len(b) <= length { // If we're already past the end, there is nothing else to parse. var prop int if state < 0 { - prop = property(graphemeCodePoints, r) + prop = propertyGraphemes(r) } else { prop = state >> shiftGraphemePropState } @@ -284,7 +284,7 @@ func FirstGraphemeClusterInString(str string, state int) (cluster, rest string, if len(str) <= length { // If we're already past the end, there is nothing else to parse. var prop int if state < 0 { - prop = property(graphemeCodePoints, r) + prop = propertyGraphemes(r) } else { prop = state >> shiftGraphemePropState } diff --git a/vendor/github.com/rivo/uniseg/graphemeproperties.go b/vendor/github.com/rivo/uniseg/graphemeproperties.go index a87d140..0aff4a6 100644 --- a/vendor/github.com/rivo/uniseg/graphemeproperties.go +++ b/vendor/github.com/rivo/uniseg/graphemeproperties.go @@ -1,13 +1,13 @@ -package uniseg - // Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg + // graphemeCodePoints are taken from -// https://www.unicode.org/Public/14.0.0/ucd/auxiliary/GraphemeBreakProperty.txt +// https://www.unicode.org/Public/15.0.0/ucd/auxiliary/GraphemeBreakProperty.txt // and -// https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt // ("Extended_Pictographic" only) -// on September 10, 2022. See https://www.unicode.org/license.html for the Unicode +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode // license agreement. var graphemeCodePoints = [][3]int{ {0x0000, 0x0009, prControl}, // Cc [10] .. @@ -143,6 +143,7 @@ var graphemeCodePoints = [][3]int{ {0x0CCC, 0x0CCD, prExtend}, // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA {0x0CD5, 0x0CD6, prExtend}, // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL + {0x0CF3, 0x0CF3, prSpacingMark}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU {0x0D02, 0x0D03, prSpacingMark}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA {0x0D3B, 0x0D3C, prExtend}, // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA @@ -172,7 +173,7 @@ var graphemeCodePoints = [][3]int{ {0x0EB1, 0x0EB1, prExtend}, // Mn LAO VOWEL SIGN MAI KAN {0x0EB3, 0x0EB3, prSpacingMark}, // Lo LAO VOWEL SIGN AM {0x0EB4, 0x0EBC, prExtend}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO - {0x0EC8, 0x0ECD, prExtend}, // Mn [6] LAO TONE MAI EK..LAO NIGGAHITA + {0x0EC8, 0x0ECE, prExtend}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN {0x0F18, 0x0F19, prExtend}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS {0x0F35, 0x0F35, prExtend}, // Mn TIBETAN MARK NGAS BZUNG NYI ZLA {0x0F37, 0x0F37, prExtend}, // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS @@ -1336,6 +1337,7 @@ var graphemeCodePoints = [][3]int{ {0x10AE5, 0x10AE6, prExtend}, // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW {0x10D24, 0x10D27, prExtend}, // Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI {0x10EAB, 0x10EAC, prExtend}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK + {0x10EFD, 0x10EFF, prExtend}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA {0x10F46, 0x10F50, prExtend}, // Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW {0x10F82, 0x10F85, prExtend}, // Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW {0x11000, 0x11000, prSpacingMark}, // Mc BRAHMI SIGN CANDRABINDU @@ -1375,6 +1377,7 @@ var graphemeCodePoints = [][3]int{ {0x11235, 0x11235, prSpacingMark}, // Mc KHOJKI SIGN VIRAMA {0x11236, 0x11237, prExtend}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x11241, 0x11241, prExtend}, // Mn KHOJKI VOWEL SIGN VOCALIC R {0x112DF, 0x112DF, prExtend}, // Mn KHUDAWADI SIGN ANUSVARA {0x112E0, 0x112E2, prSpacingMark}, // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II {0x112E3, 0x112EA, prExtend}, // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA @@ -1494,7 +1497,18 @@ var graphemeCodePoints = [][3]int{ {0x11D97, 0x11D97, prExtend}, // Mn GUNJALA GONDI VIRAMA {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U {0x11EF5, 0x11EF6, prSpacingMark}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O - {0x13430, 0x13438, prControl}, // Cf [9] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT + {0x11F00, 0x11F01, prExtend}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prPrepend}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prSpacingMark}, // Mc KAWI SIGN VISARGA + {0x11F34, 0x11F35, prSpacingMark}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prExtend}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prSpacingMark}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prExtend}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prSpacingMark}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prExtend}, // Mn KAWI CONJOINER + {0x13430, 0x1343F, prControl}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prExtend}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13447, 0x13455, prExtend}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED {0x16AF0, 0x16AF4, prExtend}, // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE {0x16B30, 0x16B36, prExtend}, // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM {0x16F4F, 0x16F4F, prExtend}, // Mn MIAO SIGN CONSONANT MODIFIER BAR @@ -1527,9 +1541,11 @@ var graphemeCodePoints = [][3]int{ {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E08F, 0x1E08F, prExtend}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D {0x1E2AE, 0x1E2AE, prExtend}, // Mn TOTO SIGN RISING TONE {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI + {0x1E4EC, 0x1E4EF, prExtend}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH {0x1E8D0, 0x1E8D6, prExtend}, // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS {0x1E944, 0x1E94A, prExtend}, // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA {0x1F000, 0x1F003, prExtendedPictographic}, // E0.0 [4] (🀀..🀃) MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND @@ -1780,7 +1796,8 @@ var graphemeCodePoints = [][3]int{ {0x1F6D3, 0x1F6D4, prExtendedPictographic}, // E0.0 [2] (🛓..🛔) STUPA..PAGODA {0x1F6D5, 0x1F6D5, prExtendedPictographic}, // E12.0 [1] (🛕) hindu temple {0x1F6D6, 0x1F6D7, prExtendedPictographic}, // E13.0 [2] (🛖..🛗) hut..elevator - {0x1F6D8, 0x1F6DC, prExtendedPictographic}, // E0.0 [5] (🛘..🛜) .. + {0x1F6D8, 0x1F6DB, prExtendedPictographic}, // E0.0 [4] (🛘..🛛) .. + {0x1F6DC, 0x1F6DC, prExtendedPictographic}, // E15.0 [1] (🛜) wireless {0x1F6DD, 0x1F6DF, prExtendedPictographic}, // E14.0 [3] (🛝..🛟) playground slide..ring buoy {0x1F6E0, 0x1F6E5, prExtendedPictographic}, // E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat {0x1F6E6, 0x1F6E8, prExtendedPictographic}, // E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE @@ -1797,7 +1814,7 @@ var graphemeCodePoints = [][3]int{ {0x1F6FA, 0x1F6FA, prExtendedPictographic}, // E12.0 [1] (🛺) auto rickshaw {0x1F6FB, 0x1F6FC, prExtendedPictographic}, // E13.0 [2] (🛻..🛼) pickup truck..roller skate {0x1F6FD, 0x1F6FF, prExtendedPictographic}, // E0.0 [3] (🛽..🛿) .. - {0x1F774, 0x1F77F, prExtendedPictographic}, // E0.0 [12] (🝴..🝿) .. + {0x1F774, 0x1F77F, prExtendedPictographic}, // E0.0 [12] (🝴..🝿) LOT OF FORTUNE..ORCUS {0x1F7D5, 0x1F7DF, prExtendedPictographic}, // E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE.. {0x1F7E0, 0x1F7EB, prExtendedPictographic}, // E12.0 [12] (🟠..🟫) orange circle..brown square {0x1F7EC, 0x1F7EF, prExtendedPictographic}, // E0.0 [4] (🟬..🟯) .. @@ -1856,30 +1873,37 @@ var graphemeCodePoints = [][3]int{ {0x1FA00, 0x1FA6F, prExtendedPictographic}, // E0.0 [112] (🨀..🩯) NEUTRAL CHESS KING.. {0x1FA70, 0x1FA73, prExtendedPictographic}, // E12.0 [4] (🩰..🩳) ballet shoes..shorts {0x1FA74, 0x1FA74, prExtendedPictographic}, // E13.0 [1] (🩴) thong sandal - {0x1FA75, 0x1FA77, prExtendedPictographic}, // E0.0 [3] (🩵..🩷) .. + {0x1FA75, 0x1FA77, prExtendedPictographic}, // E15.0 [3] (🩵..🩷) light blue heart..pink heart {0x1FA78, 0x1FA7A, prExtendedPictographic}, // E12.0 [3] (🩸..🩺) drop of blood..stethoscope {0x1FA7B, 0x1FA7C, prExtendedPictographic}, // E14.0 [2] (🩻..🩼) x-ray..crutch {0x1FA7D, 0x1FA7F, prExtendedPictographic}, // E0.0 [3] (🩽..🩿) .. {0x1FA80, 0x1FA82, prExtendedPictographic}, // E12.0 [3] (🪀..🪂) yo-yo..parachute {0x1FA83, 0x1FA86, prExtendedPictographic}, // E13.0 [4] (🪃..🪆) boomerang..nesting dolls - {0x1FA87, 0x1FA8F, prExtendedPictographic}, // E0.0 [9] (🪇..🪏) .. + {0x1FA87, 0x1FA88, prExtendedPictographic}, // E15.0 [2] (🪇..🪈) maracas..flute + {0x1FA89, 0x1FA8F, prExtendedPictographic}, // E0.0 [7] (🪉..🪏) .. {0x1FA90, 0x1FA95, prExtendedPictographic}, // E12.0 [6] (🪐..🪕) ringed planet..banjo {0x1FA96, 0x1FAA8, prExtendedPictographic}, // E13.0 [19] (🪖..🪨) military helmet..rock {0x1FAA9, 0x1FAAC, prExtendedPictographic}, // E14.0 [4] (🪩..🪬) mirror ball..hamsa - {0x1FAAD, 0x1FAAF, prExtendedPictographic}, // E0.0 [3] (🪭..🪯) .. + {0x1FAAD, 0x1FAAF, prExtendedPictographic}, // E15.0 [3] (🪭..🪯) folding hand fan..khanda {0x1FAB0, 0x1FAB6, prExtendedPictographic}, // E13.0 [7] (🪰..🪶) fly..feather {0x1FAB7, 0x1FABA, prExtendedPictographic}, // E14.0 [4] (🪷..🪺) lotus..nest with eggs - {0x1FABB, 0x1FABF, prExtendedPictographic}, // E0.0 [5] (🪻..🪿) .. + {0x1FABB, 0x1FABD, prExtendedPictographic}, // E15.0 [3] (🪻..🪽) hyacinth..wing + {0x1FABE, 0x1FABE, prExtendedPictographic}, // E0.0 [1] (🪾) + {0x1FABF, 0x1FABF, prExtendedPictographic}, // E15.0 [1] (🪿) goose {0x1FAC0, 0x1FAC2, prExtendedPictographic}, // E13.0 [3] (🫀..🫂) anatomical heart..people hugging {0x1FAC3, 0x1FAC5, prExtendedPictographic}, // E14.0 [3] (🫃..🫅) pregnant man..person with crown - {0x1FAC6, 0x1FACF, prExtendedPictographic}, // E0.0 [10] (🫆..🫏) .. + {0x1FAC6, 0x1FACD, prExtendedPictographic}, // E0.0 [8] (🫆..🫍) .. + {0x1FACE, 0x1FACF, prExtendedPictographic}, // E15.0 [2] (🫎..🫏) moose..donkey {0x1FAD0, 0x1FAD6, prExtendedPictographic}, // E13.0 [7] (🫐..🫖) blueberries..teapot {0x1FAD7, 0x1FAD9, prExtendedPictographic}, // E14.0 [3] (🫗..🫙) pouring liquid..jar - {0x1FADA, 0x1FADF, prExtendedPictographic}, // E0.0 [6] (🫚..🫟) .. + {0x1FADA, 0x1FADB, prExtendedPictographic}, // E15.0 [2] (🫚..🫛) ginger root..pea pod + {0x1FADC, 0x1FADF, prExtendedPictographic}, // E0.0 [4] (🫜..🫟) .. {0x1FAE0, 0x1FAE7, prExtendedPictographic}, // E14.0 [8] (🫠..🫧) melting face..bubbles - {0x1FAE8, 0x1FAEF, prExtendedPictographic}, // E0.0 [8] (🫨..🫯) .. + {0x1FAE8, 0x1FAE8, prExtendedPictographic}, // E15.0 [1] (🫨) shaking face + {0x1FAE9, 0x1FAEF, prExtendedPictographic}, // E0.0 [7] (🫩..🫯) .. {0x1FAF0, 0x1FAF6, prExtendedPictographic}, // E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands - {0x1FAF7, 0x1FAFF, prExtendedPictographic}, // E0.0 [9] (🫷..🫿) .. + {0x1FAF7, 0x1FAF8, prExtendedPictographic}, // E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + {0x1FAF9, 0x1FAFF, prExtendedPictographic}, // E0.0 [7] (🫹..🫿) .. {0x1FC00, 0x1FFFD, prExtendedPictographic}, // E0.0[1022] (🰀..🿽) .. {0xE0000, 0xE0000, prControl}, // Cn {0xE0001, 0xE0001, prControl}, // Cf LANGUAGE TAG diff --git a/vendor/github.com/rivo/uniseg/graphemerules.go b/vendor/github.com/rivo/uniseg/graphemerules.go index 9f46b57..5d399d2 100644 --- a/vendor/github.com/rivo/uniseg/graphemerules.go +++ b/vendor/github.com/rivo/uniseg/graphemerules.go @@ -21,11 +21,12 @@ const ( grBoundary ) -// The grapheme cluster parser's state transitions. Maps (state, property) to -// (new state, breaking instruction, rule number). The breaking instruction -// always refers to the boundary between the last and next code point. +// grTransitions implements the grapheme cluster parser's state transitions. +// Maps state and property to a new state, a breaking instruction, and rule +// number. The breaking instruction always refers to the boundary between the +// last and next code point. Returns negative values if no transition is found. // -// This map is queried as follows: +// This function is used as follows: // // 1. Find specific state + specific property. Stop if found. // 2. Find specific state + any property. @@ -36,59 +37,96 @@ const ( // are equal. Stop. // 6. Assume grAny and grBoundary. // -// Unicode version 14.0.0. -var grTransitions = map[[2]int][3]int{ +// Unicode version 15.0.0. +func grTransitions(state, prop int) (newState int, newProp int, boundary int) { + // It turns out that using a big switch statement is much faster than using + // a map. + + switch uint64(state) | uint64(prop)<<32 { // GB5 - {grAny, prCR}: {grCR, grBoundary, 50}, - {grAny, prLF}: {grControlLF, grBoundary, 50}, - {grAny, prControl}: {grControlLF, grBoundary, 50}, + case grAny | prCR<<32: + return grCR, grBoundary, 50 + case grAny | prLF<<32: + return grControlLF, grBoundary, 50 + case grAny | prControl<<32: + return grControlLF, grBoundary, 50 // GB4 - {grCR, prAny}: {grAny, grBoundary, 40}, - {grControlLF, prAny}: {grAny, grBoundary, 40}, - - // GB3. - {grCR, prLF}: {grControlLF, grNoBoundary, 30}, - - // GB6. - {grAny, prL}: {grL, grBoundary, 9990}, - {grL, prL}: {grL, grNoBoundary, 60}, - {grL, prV}: {grLVV, grNoBoundary, 60}, - {grL, prLV}: {grLVV, grNoBoundary, 60}, - {grL, prLVT}: {grLVTT, grNoBoundary, 60}, - - // GB7. - {grAny, prLV}: {grLVV, grBoundary, 9990}, - {grAny, prV}: {grLVV, grBoundary, 9990}, - {grLVV, prV}: {grLVV, grNoBoundary, 70}, - {grLVV, prT}: {grLVTT, grNoBoundary, 70}, - - // GB8. - {grAny, prLVT}: {grLVTT, grBoundary, 9990}, - {grAny, prT}: {grLVTT, grBoundary, 9990}, - {grLVTT, prT}: {grLVTT, grNoBoundary, 80}, - - // GB9. - {grAny, prExtend}: {grAny, grNoBoundary, 90}, - {grAny, prZWJ}: {grAny, grNoBoundary, 90}, - - // GB9a. - {grAny, prSpacingMark}: {grAny, grNoBoundary, 91}, - - // GB9b. - {grAny, prPrepend}: {grPrepend, grBoundary, 9990}, - {grPrepend, prAny}: {grAny, grNoBoundary, 92}, - - // GB11. - {grAny, prExtendedPictographic}: {grExtendedPictographic, grBoundary, 9990}, - {grExtendedPictographic, prExtend}: {grExtendedPictographic, grNoBoundary, 110}, - {grExtendedPictographic, prZWJ}: {grExtendedPictographicZWJ, grNoBoundary, 110}, - {grExtendedPictographicZWJ, prExtendedPictographic}: {grExtendedPictographic, grNoBoundary, 110}, - - // GB12 / GB13. - {grAny, prRegionalIndicator}: {grRIOdd, grBoundary, 9990}, - {grRIOdd, prRegionalIndicator}: {grRIEven, grNoBoundary, 120}, - {grRIEven, prRegionalIndicator}: {grRIOdd, grBoundary, 120}, + case grCR | prAny<<32: + return grAny, grBoundary, 40 + case grControlLF | prAny<<32: + return grAny, grBoundary, 40 + + // GB3 + case grCR | prLF<<32: + return grControlLF, grNoBoundary, 30 + + // GB6 + case grAny | prL<<32: + return grL, grBoundary, 9990 + case grL | prL<<32: + return grL, grNoBoundary, 60 + case grL | prV<<32: + return grLVV, grNoBoundary, 60 + case grL | prLV<<32: + return grLVV, grNoBoundary, 60 + case grL | prLVT<<32: + return grLVTT, grNoBoundary, 60 + + // GB7 + case grAny | prLV<<32: + return grLVV, grBoundary, 9990 + case grAny | prV<<32: + return grLVV, grBoundary, 9990 + case grLVV | prV<<32: + return grLVV, grNoBoundary, 70 + case grLVV | prT<<32: + return grLVTT, grNoBoundary, 70 + + // GB8 + case grAny | prLVT<<32: + return grLVTT, grBoundary, 9990 + case grAny | prT<<32: + return grLVTT, grBoundary, 9990 + case grLVTT | prT<<32: + return grLVTT, grNoBoundary, 80 + + // GB9 + case grAny | prExtend<<32: + return grAny, grNoBoundary, 90 + case grAny | prZWJ<<32: + return grAny, grNoBoundary, 90 + + // GB9a + case grAny | prSpacingMark<<32: + return grAny, grNoBoundary, 91 + + // GB9b + case grAny | prPrepend<<32: + return grPrepend, grBoundary, 9990 + case grPrepend | prAny<<32: + return grAny, grNoBoundary, 92 + + // GB11 + case grAny | prExtendedPictographic<<32: + return grExtendedPictographic, grBoundary, 9990 + case grExtendedPictographic | prExtend<<32: + return grExtendedPictographic, grNoBoundary, 110 + case grExtendedPictographic | prZWJ<<32: + return grExtendedPictographicZWJ, grNoBoundary, 110 + case grExtendedPictographicZWJ | prExtendedPictographic<<32: + return grExtendedPictographic, grNoBoundary, 110 + + // GB12 / GB13 + case grAny | prRegionalIndicator<<32: + return grRIOdd, grBoundary, 9990 + case grRIOdd | prRegionalIndicator<<32: + return grRIEven, grNoBoundary, 120 + case grRIEven | prRegionalIndicator<<32: + return grRIOdd, grBoundary, 120 + default: + return -1, -1, -1 + } } // transitionGraphemeState determines the new state of the grapheme cluster @@ -97,40 +135,40 @@ var grTransitions = map[[2]int][3]int{ // table) and whether a cluster boundary was detected. func transitionGraphemeState(state int, r rune) (newState, prop int, boundary bool) { // Determine the property of the next character. - prop = property(graphemeCodePoints, r) + prop = propertyGraphemes(r) // Find the applicable transition. - transition, ok := grTransitions[[2]int{state, prop}] - if ok { + nextState, nextProp, _ := grTransitions(state, prop) + if nextState >= 0 { // We have a specific transition. We'll use it. - return transition[0], prop, transition[1] == grBoundary + return nextState, prop, nextProp == grBoundary } // No specific transition found. Try the less specific ones. - transAnyProp, okAnyProp := grTransitions[[2]int{state, prAny}] - transAnyState, okAnyState := grTransitions[[2]int{grAny, prop}] - if okAnyProp && okAnyState { + anyPropState, anyPropProp, anyPropRule := grTransitions(state, prAny) + anyStateState, anyStateProp, anyStateRule := grTransitions(grAny, prop) + if anyPropState >= 0 && anyStateState >= 0 { // Both apply. We'll use a mix (see comments for grTransitions). - newState = transAnyState[0] - boundary = transAnyState[1] == grBoundary - if transAnyProp[2] < transAnyState[2] { - boundary = transAnyProp[1] == grBoundary + newState = anyStateState + boundary = anyStateProp == grBoundary + if anyPropRule < anyStateRule { + boundary = anyPropProp == grBoundary } return } - if okAnyProp { + if anyPropState >= 0 { // We only have a specific state. - return transAnyProp[0], prop, transAnyProp[1] == grBoundary + return anyPropState, prop, anyPropProp == grBoundary // This branch will probably never be reached because okAnyState will // always be true given the current transition map. But we keep it here // for future modifications to the transition map where this may not be // true anymore. } - if okAnyState { + if anyStateState >= 0 { // We only have a specific property. - return transAnyState[0], prop, transAnyState[1] == grBoundary + return anyStateState, prop, anyStateProp == grBoundary } // No known transition. GB999: Any ÷ Any. diff --git a/vendor/github.com/rivo/uniseg/line.go b/vendor/github.com/rivo/uniseg/line.go index 87f2850..7a46318 100644 --- a/vendor/github.com/rivo/uniseg/line.go +++ b/vendor/github.com/rivo/uniseg/line.go @@ -80,7 +80,7 @@ func FirstLineSegment(b []byte, state int) (segment, rest []byte, mustBreak bool } } -// FirstLineSegmentInString is like FirstLineSegment() but its input and outputs +// FirstLineSegmentInString is like [FirstLineSegment] but its input and outputs // are strings. func FirstLineSegmentInString(str string, state int) (segment, rest string, mustBreak bool, newState int) { // An empty byte slice returns nothing. @@ -122,13 +122,13 @@ func FirstLineSegmentInString(str string, state int) (segment, rest string, must // [UAX #14]: https://www.unicode.org/reports/tr14/#Algorithm func HasTrailingLineBreak(b []byte) bool { r, _ := utf8.DecodeLastRune(b) - property, _ := propertyWithGenCat(lineBreakCodePoints, r) - return property == lbBK || property == lbCR || property == lbLF || property == lbNL + property, _ := propertyLineBreak(r) + return property == prBK || property == prCR || property == prLF || property == prNL } // HasTrailingLineBreakInString is like [HasTrailingLineBreak] but for a string. func HasTrailingLineBreakInString(str string) bool { r, _ := utf8.DecodeLastRuneInString(str) - property, _ := propertyWithGenCat(lineBreakCodePoints, r) - return property == lbBK || property == lbCR || property == lbLF || property == lbNL + property, _ := propertyLineBreak(r) + return property == prBK || property == prCR || property == prLF || property == prNL } diff --git a/vendor/github.com/rivo/uniseg/lineproperties.go b/vendor/github.com/rivo/uniseg/lineproperties.go index 3216930..ac7fac4 100644 --- a/vendor/github.com/rivo/uniseg/lineproperties.go +++ b/vendor/github.com/rivo/uniseg/lineproperties.go @@ -1,13 +1,13 @@ -package uniseg - // Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg + // lineBreakCodePoints are taken from -// https://www.unicode.org/Public/14.0.0/ucd/LineBreak.txt +// https://www.unicode.org/Public/15.0.0/ucd/LineBreak.txt // and -// https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt // ("Extended_Pictographic" only) -// on September 10, 2022. See https://www.unicode.org/license.html for the Unicode +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode // license agreement. var lineBreakCodePoints = [][4]int{ {0x0000, 0x0008, prCM, gcCc}, // [9] .. @@ -439,6 +439,7 @@ var lineBreakCodePoints = [][4]int{ {0x0CE2, 0x0CE3, prCM, gcMn}, // [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL {0x0CE6, 0x0CEF, prNU, gcNd}, // [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE {0x0CF1, 0x0CF2, prAL, gcLo}, // [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prCM, gcMc}, // KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT {0x0D00, 0x0D01, prCM, gcMn}, // [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU {0x0D02, 0x0D03, prCM, gcMc}, // [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA {0x0D04, 0x0D0C, prAL, gcLo}, // [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L @@ -500,7 +501,7 @@ var lineBreakCodePoints = [][4]int{ {0x0EBD, 0x0EBD, prSA, gcLo}, // LAO SEMIVOWEL SIGN NYO {0x0EC0, 0x0EC4, prSA, gcLo}, // [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI {0x0EC6, 0x0EC6, prSA, gcLm}, // LAO KO LA - {0x0EC8, 0x0ECD, prSA, gcMn}, // [6] LAO TONE MAI EK..LAO NIGGAHITA + {0x0EC8, 0x0ECE, prSA, gcMn}, // [7] LAO TONE MAI EK..LAO YAMAKKAN {0x0ED0, 0x0ED9, prNU, gcNd}, // [10] LAO DIGIT ZERO..LAO DIGIT NINE {0x0EDC, 0x0EDF, prSA, gcLo}, // [4] LAO HO NO..LAO LETTER KHMU NYO {0x0F00, 0x0F00, prAL, gcLo}, // TIBETAN SYLLABLE OM @@ -813,7 +814,11 @@ var lineBreakCodePoints = [][4]int{ {0x1D79, 0x1D7F, prAL, gcLl}, // [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE {0x1D80, 0x1D9A, prAL, gcLl}, // [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK {0x1D9B, 0x1DBF, prAL, gcLm}, // [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA - {0x1DC0, 0x1DFF, prCM, gcMn}, // [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW + {0x1DC0, 0x1DCC, prCM, gcMn}, // [13] COMBINING DOTTED GRAVE ACCENT..COMBINING MACRON-BREVE + {0x1DCD, 0x1DCD, prGL, gcMn}, // COMBINING DOUBLE CIRCUMFLEX ABOVE + {0x1DCE, 0x1DFB, prCM, gcMn}, // [46] COMBINING OGONEK ABOVE..COMBINING DELETION MARK + {0x1DFC, 0x1DFC, prGL, gcMn}, // COMBINING DOUBLE INVERTED BREVE BELOW + {0x1DFD, 0x1DFF, prCM, gcMn}, // [3] COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW {0x1E00, 0x1EFF, prAL, gcLC}, // [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP {0x1F00, 0x1F15, prAL, gcLC}, // [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA {0x1F18, 0x1F1D, prAL, gcLu}, // [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA @@ -889,7 +894,7 @@ var lineBreakCodePoints = [][4]int{ {0x2054, 0x2054, prAL, gcPc}, // INVERTED UNDERTIE {0x2055, 0x2055, prAL, gcPo}, // FLOWER PUNCTUATION MARK {0x2056, 0x2056, prBA, gcPo}, // THREE DOT PUNCTUATION - {0x2057, 0x2057, prAL, gcPo}, // QUADRUPLE PRIME + {0x2057, 0x2057, prPO, gcPo}, // QUADRUPLE PRIME {0x2058, 0x205B, prBA, gcPo}, // [4] FOUR DOT PUNCTUATION..FOUR DOT MARK {0x205C, 0x205C, prAL, gcPo}, // DOTTED CROSS {0x205D, 0x205E, prBA, gcPo}, // [2] TRICOLON..VERTICAL FOUR DOTS @@ -2751,6 +2756,7 @@ var lineBreakCodePoints = [][4]int{ {0x10EAB, 0x10EAC, prCM, gcMn}, // [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK {0x10EAD, 0x10EAD, prBA, gcPd}, // YEZIDI HYPHENATION MARK {0x10EB0, 0x10EB1, prAL, gcLo}, // [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prCM, gcMn}, // [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA {0x10F00, 0x10F1C, prAL, gcLo}, // [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL {0x10F1D, 0x10F26, prAL, gcNo}, // [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF {0x10F27, 0x10F27, prAL, gcLo}, // OLD SOGDIAN LIGATURE AYIN-DALETH @@ -2840,6 +2846,8 @@ var lineBreakCodePoints = [][4]int{ {0x1123B, 0x1123C, prBA, gcPo}, // [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK {0x1123D, 0x1123D, prAL, gcPo}, // KHOJKI ABBREVIATION SIGN {0x1123E, 0x1123E, prCM, gcMn}, // KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prAL, gcLo}, // [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prCM, gcMn}, // KHOJKI VOWEL SIGN VOCALIC R {0x11280, 0x11286, prAL, gcLo}, // [7] MULTANI LETTER A..MULTANI LETTER GA {0x11288, 0x11288, prAL, gcLo}, // MULTANI LETTER GHA {0x1128A, 0x1128D, prAL, gcLo}, // [4] MULTANI LETTER CA..MULTANI LETTER JJA @@ -3013,6 +3021,7 @@ var lineBreakCodePoints = [][4]int{ {0x11AA1, 0x11AA2, prBA, gcPo}, // [2] SOYOMBO TERMINAL MARK-1..SOYOMBO TERMINAL MARK-2 {0x11AB0, 0x11ABF, prAL, gcLo}, // [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA {0x11AC0, 0x11AF8, prAL, gcLo}, // [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL + {0x11B00, 0x11B09, prBB, gcPo}, // [10] DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU {0x11C00, 0x11C08, prAL, gcLo}, // [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L {0x11C0A, 0x11C2E, prAL, gcLo}, // [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA {0x11C2F, 0x11C2F, prCM, gcMc}, // BHAIKSUKI VOWEL SIGN AA @@ -3059,6 +3068,20 @@ var lineBreakCodePoints = [][4]int{ {0x11EF3, 0x11EF4, prCM, gcMn}, // [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U {0x11EF5, 0x11EF6, prCM, gcMc}, // [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O {0x11EF7, 0x11EF8, prAL, gcPo}, // [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION + {0x11F00, 0x11F01, prCM, gcMn}, // [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prAL, gcLo}, // KAWI SIGN REPHA + {0x11F03, 0x11F03, prCM, gcMc}, // KAWI SIGN VISARGA + {0x11F04, 0x11F10, prAL, gcLo}, // [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prAL, gcLo}, // [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prCM, gcMc}, // [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prCM, gcMn}, // [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prCM, gcMc}, // [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prCM, gcMn}, // KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prCM, gcMc}, // KAWI SIGN KILLER + {0x11F42, 0x11F42, prCM, gcMn}, // KAWI CONJOINER + {0x11F43, 0x11F44, prBA, gcPo}, // [2] KAWI DANDA..KAWI DOUBLE DANDA + {0x11F45, 0x11F4F, prID, gcPo}, // [11] KAWI PUNCTUATION SECTION MARKER..KAWI PUNCTUATION CLOSING SPIRAL + {0x11F50, 0x11F59, prNU, gcNd}, // [10] KAWI DIGIT ZERO..KAWI DIGIT NINE {0x11FB0, 0x11FB0, prAL, gcLo}, // LISU LETTER YHA {0x11FC0, 0x11FD4, prAL, gcNo}, // [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH {0x11FD5, 0x11FDC, prAL, gcSo}, // [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI @@ -3084,10 +3107,18 @@ var lineBreakCodePoints = [][4]int{ {0x1328A, 0x13378, prAL, gcLo}, // [239] EGYPTIAN HIEROGLYPH O037..EGYPTIAN HIEROGLYPH V011 {0x13379, 0x13379, prOP, gcLo}, // EGYPTIAN HIEROGLYPH V011A {0x1337A, 0x1337B, prCL, gcLo}, // [2] EGYPTIAN HIEROGLYPH V011B..EGYPTIAN HIEROGLYPH V011C - {0x1337C, 0x1342E, prAL, gcLo}, // [179] EGYPTIAN HIEROGLYPH V012..EGYPTIAN HIEROGLYPH AA032 + {0x1337C, 0x1342F, prAL, gcLo}, // [180] EGYPTIAN HIEROGLYPH V012..EGYPTIAN HIEROGLYPH V011D {0x13430, 0x13436, prGL, gcCf}, // [7] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH OVERLAY MIDDLE {0x13437, 0x13437, prOP, gcCf}, // EGYPTIAN HIEROGLYPH BEGIN SEGMENT {0x13438, 0x13438, prCL, gcCf}, // EGYPTIAN HIEROGLYPH END SEGMENT + {0x13439, 0x1343B, prGL, gcCf}, // [3] EGYPTIAN HIEROGLYPH INSERT AT MIDDLE..EGYPTIAN HIEROGLYPH INSERT AT BOTTOM + {0x1343C, 0x1343C, prOP, gcCf}, // EGYPTIAN HIEROGLYPH BEGIN ENCLOSURE + {0x1343D, 0x1343D, prCL, gcCf}, // EGYPTIAN HIEROGLYPH END ENCLOSURE + {0x1343E, 0x1343E, prOP, gcCf}, // EGYPTIAN HIEROGLYPH BEGIN WALLED ENCLOSURE + {0x1343F, 0x1343F, prCL, gcCf}, // EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prCM, gcMn}, // EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prAL, gcLo}, // [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prCM, gcMn}, // [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED {0x14400, 0x145CD, prAL, gcLo}, // [462] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A409 {0x145CE, 0x145CE, prOP, gcLo}, // ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK {0x145CF, 0x145CF, prCL, gcLo}, // ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK @@ -3137,7 +3168,9 @@ var lineBreakCodePoints = [][4]int{ {0x1AFFD, 0x1AFFE, prAL, gcLm}, // [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 {0x1B000, 0x1B0FF, prID, gcLo}, // [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2 {0x1B100, 0x1B122, prID, gcLo}, // [35] HENTAIGANA LETTER RE-3..KATAKANA LETTER ARCHAIC WU + {0x1B132, 0x1B132, prCJ, gcLo}, // HIRAGANA LETTER SMALL KO {0x1B150, 0x1B152, prCJ, gcLo}, // [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO + {0x1B155, 0x1B155, prCJ, gcLo}, // KATAKANA LETTER SMALL KO {0x1B164, 0x1B167, prCJ, gcLo}, // [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N {0x1B170, 0x1B2FB, prID, gcLo}, // [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB {0x1BC00, 0x1BC6A, prAL, gcLo}, // [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M @@ -3168,6 +3201,7 @@ var lineBreakCodePoints = [][4]int{ {0x1D200, 0x1D241, prAL, gcSo}, // [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54 {0x1D242, 0x1D244, prCM, gcMn}, // [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME {0x1D245, 0x1D245, prAL, gcSo}, // GREEK MUSICAL LEIMMA + {0x1D2C0, 0x1D2D3, prAL, gcNo}, // [20] KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN {0x1D2E0, 0x1D2F3, prAL, gcNo}, // [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN {0x1D300, 0x1D356, prAL, gcSo}, // [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING {0x1D360, 0x1D378, prAL, gcNo}, // [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE @@ -3228,11 +3262,14 @@ var lineBreakCodePoints = [][4]int{ {0x1DF00, 0x1DF09, prAL, gcLl}, // [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK {0x1DF0A, 0x1DF0A, prAL, gcLo}, // LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK {0x1DF0B, 0x1DF1E, prAL, gcLl}, // [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prAL, gcLl}, // [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK {0x1E000, 0x1E006, prCM, gcMn}, // [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE {0x1E008, 0x1E018, prCM, gcMn}, // [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU {0x1E01B, 0x1E021, prCM, gcMn}, // [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI {0x1E023, 0x1E024, prCM, gcMn}, // [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS {0x1E026, 0x1E02A, prCM, gcMn}, // [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prAL, gcLm}, // [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prCM, gcMn}, // COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I {0x1E100, 0x1E12C, prAL, gcLo}, // [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W {0x1E130, 0x1E136, prCM, gcMn}, // [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D {0x1E137, 0x1E13D, prAL, gcLm}, // [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER @@ -3245,6 +3282,10 @@ var lineBreakCodePoints = [][4]int{ {0x1E2EC, 0x1E2EF, prCM, gcMn}, // [4] WANCHO TONE TUP..WANCHO TONE KOINI {0x1E2F0, 0x1E2F9, prNU, gcNd}, // [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE {0x1E2FF, 0x1E2FF, prPR, gcSc}, // WANCHO NGUN SIGN + {0x1E4D0, 0x1E4EA, prAL, gcLo}, // [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prAL, gcLm}, // NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prCM, gcMn}, // [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prNU, gcNd}, // [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE {0x1E7E0, 0x1E7E6, prAL, gcLo}, // [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO {0x1E7E8, 0x1E7EB, prAL, gcLo}, // [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE {0x1E7ED, 0x1E7EE, prAL, gcLo}, // [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE @@ -3412,16 +3453,18 @@ var lineBreakCodePoints = [][4]int{ {0x1F6C1, 0x1F6CB, prID, gcSo}, // [11] BATHTUB..COUCH AND LAMP {0x1F6CC, 0x1F6CC, prEB, gcSo}, // SLEEPING ACCOMMODATION {0x1F6CD, 0x1F6D7, prID, gcSo}, // [11] SHOPPING BAGS..ELEVATOR - {0x1F6D8, 0x1F6DC, prID, gcCn}, // [5] .. - {0x1F6DD, 0x1F6EC, prID, gcSo}, // [16] PLAYGROUND SLIDE..AIRPLANE ARRIVING + {0x1F6D8, 0x1F6DB, prID, gcCn}, // [4] .. + {0x1F6DC, 0x1F6EC, prID, gcSo}, // [17] WIRELESS..AIRPLANE ARRIVING {0x1F6ED, 0x1F6EF, prID, gcCn}, // [3] .. {0x1F6F0, 0x1F6FC, prID, gcSo}, // [13] SATELLITE..ROLLER SKATE {0x1F6FD, 0x1F6FF, prID, gcCn}, // [3] .. {0x1F700, 0x1F773, prAL, gcSo}, // [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE - {0x1F774, 0x1F77F, prID, gcCn}, // [12] .. + {0x1F774, 0x1F776, prID, gcSo}, // [3] LOT OF FORTUNE..LUNAR ECLIPSE + {0x1F777, 0x1F77A, prID, gcCn}, // [4] .. + {0x1F77B, 0x1F77F, prID, gcSo}, // [5] HAUMEA..ORCUS {0x1F780, 0x1F7D4, prAL, gcSo}, // [85] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..HEAVY TWELVE POINTED PINWHEEL STAR - {0x1F7D5, 0x1F7D8, prID, gcSo}, // [4] CIRCLED TRIANGLE..NEGATIVE CIRCLED SQUARE - {0x1F7D9, 0x1F7DF, prID, gcCn}, // [7] .. + {0x1F7D5, 0x1F7D9, prID, gcSo}, // [5] CIRCLED TRIANGLE..NINE POINTED WHITE STAR + {0x1F7DA, 0x1F7DF, prID, gcCn}, // [6] .. {0x1F7E0, 0x1F7EB, prID, gcSo}, // [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE {0x1F7EC, 0x1F7EF, prID, gcCn}, // [4] .. {0x1F7F0, 0x1F7F0, prID, gcSo}, // HEAVY EQUALS SIGN @@ -3467,33 +3510,29 @@ var lineBreakCodePoints = [][4]int{ {0x1FA54, 0x1FA5F, prID, gcCn}, // [12] .. {0x1FA60, 0x1FA6D, prID, gcSo}, // [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER {0x1FA6E, 0x1FA6F, prID, gcCn}, // [2] .. - {0x1FA70, 0x1FA74, prID, gcSo}, // [5] BALLET SHOES..THONG SANDAL - {0x1FA75, 0x1FA77, prID, gcCn}, // [3] .. - {0x1FA78, 0x1FA7C, prID, gcSo}, // [5] DROP OF BLOOD..CRUTCH + {0x1FA70, 0x1FA7C, prID, gcSo}, // [13] BALLET SHOES..CRUTCH {0x1FA7D, 0x1FA7F, prID, gcCn}, // [3] .. - {0x1FA80, 0x1FA86, prID, gcSo}, // [7] YO-YO..NESTING DOLLS - {0x1FA87, 0x1FA8F, prID, gcCn}, // [9] .. - {0x1FA90, 0x1FAAC, prID, gcSo}, // [29] RINGED PLANET..HAMSA - {0x1FAAD, 0x1FAAF, prID, gcCn}, // [3] .. - {0x1FAB0, 0x1FABA, prID, gcSo}, // [11] FLY..NEST WITH EGGS - {0x1FABB, 0x1FABF, prID, gcCn}, // [5] .. - {0x1FAC0, 0x1FAC2, prID, gcSo}, // [3] ANATOMICAL HEART..PEOPLE HUGGING + {0x1FA80, 0x1FA88, prID, gcSo}, // [9] YO-YO..FLUTE + {0x1FA89, 0x1FA8F, prID, gcCn}, // [7] .. + {0x1FA90, 0x1FABD, prID, gcSo}, // [46] RINGED PLANET..WING + {0x1FABE, 0x1FABE, prID, gcCn}, // + {0x1FABF, 0x1FAC2, prID, gcSo}, // [4] GOOSE..PEOPLE HUGGING {0x1FAC3, 0x1FAC5, prEB, gcSo}, // [3] PREGNANT MAN..PERSON WITH CROWN - {0x1FAC6, 0x1FACF, prID, gcCn}, // [10] .. - {0x1FAD0, 0x1FAD9, prID, gcSo}, // [10] BLUEBERRIES..JAR - {0x1FADA, 0x1FADF, prID, gcCn}, // [6] .. - {0x1FAE0, 0x1FAE7, prID, gcSo}, // [8] MELTING FACE..BUBBLES - {0x1FAE8, 0x1FAEF, prID, gcCn}, // [8] .. - {0x1FAF0, 0x1FAF6, prEB, gcSo}, // [7] HAND WITH INDEX FINGER AND THUMB CROSSED..HEART HANDS - {0x1FAF7, 0x1FAFF, prID, gcCn}, // [9] .. + {0x1FAC6, 0x1FACD, prID, gcCn}, // [8] .. + {0x1FACE, 0x1FADB, prID, gcSo}, // [14] MOOSE..PEA POD + {0x1FADC, 0x1FADF, prID, gcCn}, // [4] .. + {0x1FAE0, 0x1FAE8, prID, gcSo}, // [9] MELTING FACE..SHAKING FACE + {0x1FAE9, 0x1FAEF, prID, gcCn}, // [7] .. + {0x1FAF0, 0x1FAF8, prEB, gcSo}, // [9] HAND WITH INDEX FINGER AND THUMB CROSSED..RIGHTWARDS PUSHING HAND + {0x1FAF9, 0x1FAFF, prID, gcCn}, // [7] .. {0x1FB00, 0x1FB92, prAL, gcSo}, // [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK {0x1FB94, 0x1FBCA, prAL, gcSo}, // [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON {0x1FBF0, 0x1FBF9, prNU, gcNd}, // [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE {0x1FC00, 0x1FFFD, prID, gcCn}, // [1022] .. {0x20000, 0x2A6DF, prID, gcLo}, // [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF {0x2A6E0, 0x2A6FF, prID, gcCn}, // [32] .. - {0x2A700, 0x2B738, prID, gcLo}, // [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 - {0x2B739, 0x2B73F, prID, gcCn}, // [7] .. + {0x2A700, 0x2B739, prID, gcLo}, // [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739 + {0x2B73A, 0x2B73F, prID, gcCn}, // [6] .. {0x2B740, 0x2B81D, prID, gcLo}, // [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D {0x2B81E, 0x2B81F, prID, gcCn}, // [2] .. {0x2B820, 0x2CEA1, prID, gcLo}, // [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 @@ -3504,7 +3543,9 @@ var lineBreakCodePoints = [][4]int{ {0x2FA1E, 0x2FA1F, prID, gcCn}, // [2] .. {0x2FA20, 0x2FFFD, prID, gcCn}, // [1502] .. {0x30000, 0x3134A, prID, gcLo}, // [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A - {0x3134B, 0x3FFFD, prID, gcCn}, // [60595] .. + {0x3134B, 0x3134F, prID, gcCn}, // [5] .. + {0x31350, 0x323AF, prID, gcLo}, // [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF + {0x323B0, 0x3FFFD, prID, gcCn}, // [56398] .. {0xE0001, 0xE0001, prCM, gcCf}, // LANGUAGE TAG {0xE0020, 0xE007F, prCM, gcCf}, // [96] TAG SPACE..CANCEL TAG {0xE0100, 0xE01EF, prCM, gcMn}, // [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 diff --git a/vendor/github.com/rivo/uniseg/linerules.go b/vendor/github.com/rivo/uniseg/linerules.go index d2ad516..7708ae0 100644 --- a/vendor/github.com/rivo/uniseg/linerules.go +++ b/vendor/github.com/rivo/uniseg/linerules.go @@ -64,222 +64,381 @@ const ( LineMustBreak // You must break the line here. ) -// The line break parser's state transitions. It's anologous to grTransitions, -// see comments there for details. Unicode version 14.0.0. -var lbTransitions = map[[2]int][3]int{ +// lbTransitions implements the line break parser's state transitions. It's +// anologous to [grTransitions], see comments there for details. +// +// Unicode version 15.0.0. +func lbTransitions(state, prop int) (newState, lineBreak, rule int) { + switch uint64(state) | uint64(prop)<<32 { // LB4. - {lbAny, prBK}: {lbBK, LineCanBreak, 310}, - {lbBK, prAny}: {lbAny, LineMustBreak, 40}, + case lbBK | prAny<<32: + return lbAny, LineMustBreak, 40 // LB5. - {lbAny, prCR}: {lbCR, LineCanBreak, 310}, - {lbAny, prLF}: {lbLF, LineCanBreak, 310}, - {lbAny, prNL}: {lbNL, LineCanBreak, 310}, - {lbCR, prLF}: {lbLF, LineDontBreak, 50}, - {lbCR, prAny}: {lbAny, LineMustBreak, 50}, - {lbLF, prAny}: {lbAny, LineMustBreak, 50}, - {lbNL, prAny}: {lbAny, LineMustBreak, 50}, + case lbCR | prLF<<32: + return lbLF, LineDontBreak, 50 + case lbCR | prAny<<32: + return lbAny, LineMustBreak, 50 + case lbLF | prAny<<32: + return lbAny, LineMustBreak, 50 + case lbNL | prAny<<32: + return lbAny, LineMustBreak, 50 // LB6. - {lbAny, prBK}: {lbBK, LineDontBreak, 60}, - {lbAny, prCR}: {lbCR, LineDontBreak, 60}, - {lbAny, prLF}: {lbLF, LineDontBreak, 60}, - {lbAny, prNL}: {lbNL, LineDontBreak, 60}, + case lbAny | prBK<<32: + return lbBK, LineDontBreak, 60 + case lbAny | prCR<<32: + return lbCR, LineDontBreak, 60 + case lbAny | prLF<<32: + return lbLF, LineDontBreak, 60 + case lbAny | prNL<<32: + return lbNL, LineDontBreak, 60 // LB7. - {lbAny, prSP}: {lbSP, LineDontBreak, 70}, - {lbAny, prZW}: {lbZW, LineDontBreak, 70}, + case lbAny | prSP<<32: + return lbSP, LineDontBreak, 70 + case lbAny | prZW<<32: + return lbZW, LineDontBreak, 70 // LB8. - {lbZW, prSP}: {lbZW, LineDontBreak, 70}, - {lbZW, prAny}: {lbAny, LineCanBreak, 80}, + case lbZW | prSP<<32: + return lbZW, LineDontBreak, 70 + case lbZW | prAny<<32: + return lbAny, LineCanBreak, 80 // LB11. - {lbAny, prWJ}: {lbWJ, LineDontBreak, 110}, - {lbWJ, prAny}: {lbAny, LineDontBreak, 110}, + case lbAny | prWJ<<32: + return lbWJ, LineDontBreak, 110 + case lbWJ | prAny<<32: + return lbAny, LineDontBreak, 110 // LB12. - {lbAny, prGL}: {lbGL, LineCanBreak, 310}, - {lbGL, prAny}: {lbAny, LineDontBreak, 120}, + case lbAny | prGL<<32: + return lbGL, LineCanBreak, 310 + case lbGL | prAny<<32: + return lbAny, LineDontBreak, 120 // LB13 (simple transitions). - {lbAny, prCL}: {lbCL, LineCanBreak, 310}, - {lbAny, prCP}: {lbCP, LineCanBreak, 310}, - {lbAny, prEX}: {lbEX, LineDontBreak, 130}, - {lbAny, prIS}: {lbIS, LineCanBreak, 310}, - {lbAny, prSY}: {lbSY, LineCanBreak, 310}, + case lbAny | prCL<<32: + return lbCL, LineCanBreak, 310 + case lbAny | prCP<<32: + return lbCP, LineCanBreak, 310 + case lbAny | prEX<<32: + return lbEX, LineDontBreak, 130 + case lbAny | prIS<<32: + return lbIS, LineCanBreak, 310 + case lbAny | prSY<<32: + return lbSY, LineCanBreak, 310 // LB14. - {lbAny, prOP}: {lbOP, LineCanBreak, 310}, - {lbOP, prSP}: {lbOP, LineDontBreak, 70}, - {lbOP, prAny}: {lbAny, LineDontBreak, 140}, + case lbAny | prOP<<32: + return lbOP, LineCanBreak, 310 + case lbOP | prSP<<32: + return lbOP, LineDontBreak, 70 + case lbOP | prAny<<32: + return lbAny, LineDontBreak, 140 // LB15. - {lbQU, prSP}: {lbQUSP, LineDontBreak, 70}, - {lbQU, prOP}: {lbOP, LineDontBreak, 150}, - {lbQUSP, prOP}: {lbOP, LineDontBreak, 150}, + case lbQU | prSP<<32: + return lbQUSP, LineDontBreak, 70 + case lbQU | prOP<<32: + return lbOP, LineDontBreak, 150 + case lbQUSP | prOP<<32: + return lbOP, LineDontBreak, 150 // LB16. - {lbCL, prSP}: {lbCLCPSP, LineDontBreak, 70}, - {lbNUCL, prSP}: {lbCLCPSP, LineDontBreak, 70}, - {lbCP, prSP}: {lbCLCPSP, LineDontBreak, 70}, - {lbNUCP, prSP}: {lbCLCPSP, LineDontBreak, 70}, - {lbCL, prNS}: {lbNS, LineDontBreak, 160}, - {lbNUCL, prNS}: {lbNS, LineDontBreak, 160}, - {lbCP, prNS}: {lbNS, LineDontBreak, 160}, - {lbNUCP, prNS}: {lbNS, LineDontBreak, 160}, - {lbCLCPSP, prNS}: {lbNS, LineDontBreak, 160}, + case lbCL | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbNUCL | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbCP | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbNUCP | prSP<<32: + return lbCLCPSP, LineDontBreak, 70 + case lbCL | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbNUCL | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbCP | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbNUCP | prNS<<32: + return lbNS, LineDontBreak, 160 + case lbCLCPSP | prNS<<32: + return lbNS, LineDontBreak, 160 // LB17. - {lbAny, prB2}: {lbB2, LineCanBreak, 310}, - {lbB2, prSP}: {lbB2SP, LineDontBreak, 70}, - {lbB2, prB2}: {lbB2, LineDontBreak, 170}, - {lbB2SP, prB2}: {lbB2, LineDontBreak, 170}, + case lbAny | prB2<<32: + return lbB2, LineCanBreak, 310 + case lbB2 | prSP<<32: + return lbB2SP, LineDontBreak, 70 + case lbB2 | prB2<<32: + return lbB2, LineDontBreak, 170 + case lbB2SP | prB2<<32: + return lbB2, LineDontBreak, 170 // LB18. - {lbSP, prAny}: {lbAny, LineCanBreak, 180}, - {lbQUSP, prAny}: {lbAny, LineCanBreak, 180}, - {lbCLCPSP, prAny}: {lbAny, LineCanBreak, 180}, - {lbB2SP, prAny}: {lbAny, LineCanBreak, 180}, + case lbSP | prAny<<32: + return lbAny, LineCanBreak, 180 + case lbQUSP | prAny<<32: + return lbAny, LineCanBreak, 180 + case lbCLCPSP | prAny<<32: + return lbAny, LineCanBreak, 180 + case lbB2SP | prAny<<32: + return lbAny, LineCanBreak, 180 // LB19. - {lbAny, prQU}: {lbQU, LineDontBreak, 190}, - {lbQU, prAny}: {lbAny, LineDontBreak, 190}, + case lbAny | prQU<<32: + return lbQU, LineDontBreak, 190 + case lbQU | prAny<<32: + return lbAny, LineDontBreak, 190 // LB20. - {lbAny, prCB}: {lbCB, LineCanBreak, 200}, - {lbCB, prAny}: {lbAny, LineCanBreak, 200}, + case lbAny | prCB<<32: + return lbCB, LineCanBreak, 200 + case lbCB | prAny<<32: + return lbAny, LineCanBreak, 200 // LB21. - {lbAny, prBA}: {lbBA, LineDontBreak, 210}, - {lbAny, prHY}: {lbHY, LineDontBreak, 210}, - {lbAny, prNS}: {lbNS, LineDontBreak, 210}, - {lbAny, prBB}: {lbBB, LineCanBreak, 310}, - {lbBB, prAny}: {lbAny, LineDontBreak, 210}, + case lbAny | prBA<<32: + return lbBA, LineDontBreak, 210 + case lbAny | prHY<<32: + return lbHY, LineDontBreak, 210 + case lbAny | prNS<<32: + return lbNS, LineDontBreak, 210 + case lbAny | prBB<<32: + return lbBB, LineCanBreak, 310 + case lbBB | prAny<<32: + return lbAny, LineDontBreak, 210 // LB21a. - {lbAny, prHL}: {lbHL, LineCanBreak, 310}, - {lbHL, prHY}: {lbLB21a, LineDontBreak, 210}, - {lbHL, prBA}: {lbLB21a, LineDontBreak, 210}, - {lbLB21a, prAny}: {lbAny, LineDontBreak, 211}, + case lbAny | prHL<<32: + return lbHL, LineCanBreak, 310 + case lbHL | prHY<<32: + return lbLB21a, LineDontBreak, 210 + case lbHL | prBA<<32: + return lbLB21a, LineDontBreak, 210 + case lbLB21a | prAny<<32: + return lbAny, LineDontBreak, 211 // LB21b. - {lbSY, prHL}: {lbHL, LineDontBreak, 212}, - {lbNUSY, prHL}: {lbHL, LineDontBreak, 212}, + case lbSY | prHL<<32: + return lbHL, LineDontBreak, 212 + case lbNUSY | prHL<<32: + return lbHL, LineDontBreak, 212 // LB22. - {lbAny, prIN}: {lbAny, LineDontBreak, 220}, + case lbAny | prIN<<32: + return lbAny, LineDontBreak, 220 // LB23. - {lbAny, prAL}: {lbAL, LineCanBreak, 310}, - {lbAny, prNU}: {lbNU, LineCanBreak, 310}, - {lbAL, prNU}: {lbNU, LineDontBreak, 230}, - {lbHL, prNU}: {lbNU, LineDontBreak, 230}, - {lbNU, prAL}: {lbAL, LineDontBreak, 230}, - {lbNU, prHL}: {lbHL, LineDontBreak, 230}, - {lbNUNU, prAL}: {lbAL, LineDontBreak, 230}, - {lbNUNU, prHL}: {lbHL, LineDontBreak, 230}, + case lbAny | prAL<<32: + return lbAL, LineCanBreak, 310 + case lbAny | prNU<<32: + return lbNU, LineCanBreak, 310 + case lbAL | prNU<<32: + return lbNU, LineDontBreak, 230 + case lbHL | prNU<<32: + return lbNU, LineDontBreak, 230 + case lbNU | prAL<<32: + return lbAL, LineDontBreak, 230 + case lbNU | prHL<<32: + return lbHL, LineDontBreak, 230 + case lbNUNU | prAL<<32: + return lbAL, LineDontBreak, 230 + case lbNUNU | prHL<<32: + return lbHL, LineDontBreak, 230 // LB23a. - {lbAny, prPR}: {lbPR, LineCanBreak, 310}, - {lbAny, prID}: {lbIDEM, LineCanBreak, 310}, - {lbAny, prEB}: {lbEB, LineCanBreak, 310}, - {lbAny, prEM}: {lbIDEM, LineCanBreak, 310}, - {lbPR, prID}: {lbIDEM, LineDontBreak, 231}, - {lbPR, prEB}: {lbEB, LineDontBreak, 231}, - {lbPR, prEM}: {lbIDEM, LineDontBreak, 231}, - {lbIDEM, prPO}: {lbPO, LineDontBreak, 231}, - {lbEB, prPO}: {lbPO, LineDontBreak, 231}, + case lbAny | prPR<<32: + return lbPR, LineCanBreak, 310 + case lbAny | prID<<32: + return lbIDEM, LineCanBreak, 310 + case lbAny | prEB<<32: + return lbEB, LineCanBreak, 310 + case lbAny | prEM<<32: + return lbIDEM, LineCanBreak, 310 + case lbPR | prID<<32: + return lbIDEM, LineDontBreak, 231 + case lbPR | prEB<<32: + return lbEB, LineDontBreak, 231 + case lbPR | prEM<<32: + return lbIDEM, LineDontBreak, 231 + case lbIDEM | prPO<<32: + return lbPO, LineDontBreak, 231 + case lbEB | prPO<<32: + return lbPO, LineDontBreak, 231 // LB24. - {lbAny, prPO}: {lbPO, LineCanBreak, 310}, - {lbPR, prAL}: {lbAL, LineDontBreak, 240}, - {lbPR, prHL}: {lbHL, LineDontBreak, 240}, - {lbPO, prAL}: {lbAL, LineDontBreak, 240}, - {lbPO, prHL}: {lbHL, LineDontBreak, 240}, - {lbAL, prPR}: {lbPR, LineDontBreak, 240}, - {lbAL, prPO}: {lbPO, LineDontBreak, 240}, - {lbHL, prPR}: {lbPR, LineDontBreak, 240}, - {lbHL, prPO}: {lbPO, LineDontBreak, 240}, + case lbAny | prPO<<32: + return lbPO, LineCanBreak, 310 + case lbPR | prAL<<32: + return lbAL, LineDontBreak, 240 + case lbPR | prHL<<32: + return lbHL, LineDontBreak, 240 + case lbPO | prAL<<32: + return lbAL, LineDontBreak, 240 + case lbPO | prHL<<32: + return lbHL, LineDontBreak, 240 + case lbAL | prPR<<32: + return lbPR, LineDontBreak, 240 + case lbAL | prPO<<32: + return lbPO, LineDontBreak, 240 + case lbHL | prPR<<32: + return lbPR, LineDontBreak, 240 + case lbHL | prPO<<32: + return lbPO, LineDontBreak, 240 // LB25 (simple transitions). - {lbPR, prNU}: {lbNU, LineDontBreak, 250}, - {lbPO, prNU}: {lbNU, LineDontBreak, 250}, - {lbOP, prNU}: {lbNU, LineDontBreak, 250}, - {lbHY, prNU}: {lbNU, LineDontBreak, 250}, - {lbNU, prNU}: {lbNUNU, LineDontBreak, 250}, - {lbNU, prSY}: {lbNUSY, LineDontBreak, 250}, - {lbNU, prIS}: {lbNUIS, LineDontBreak, 250}, - {lbNUNU, prNU}: {lbNUNU, LineDontBreak, 250}, - {lbNUNU, prSY}: {lbNUSY, LineDontBreak, 250}, - {lbNUNU, prIS}: {lbNUIS, LineDontBreak, 250}, - {lbNUSY, prNU}: {lbNUNU, LineDontBreak, 250}, - {lbNUSY, prSY}: {lbNUSY, LineDontBreak, 250}, - {lbNUSY, prIS}: {lbNUIS, LineDontBreak, 250}, - {lbNUIS, prNU}: {lbNUNU, LineDontBreak, 250}, - {lbNUIS, prSY}: {lbNUSY, LineDontBreak, 250}, - {lbNUIS, prIS}: {lbNUIS, LineDontBreak, 250}, - {lbNU, prCL}: {lbNUCL, LineDontBreak, 250}, - {lbNU, prCP}: {lbNUCP, LineDontBreak, 250}, - {lbNUNU, prCL}: {lbNUCL, LineDontBreak, 250}, - {lbNUNU, prCP}: {lbNUCP, LineDontBreak, 250}, - {lbNUSY, prCL}: {lbNUCL, LineDontBreak, 250}, - {lbNUSY, prCP}: {lbNUCP, LineDontBreak, 250}, - {lbNUIS, prCL}: {lbNUCL, LineDontBreak, 250}, - {lbNUIS, prCP}: {lbNUCP, LineDontBreak, 250}, - {lbNU, prPO}: {lbPO, LineDontBreak, 250}, - {lbNUNU, prPO}: {lbPO, LineDontBreak, 250}, - {lbNUSY, prPO}: {lbPO, LineDontBreak, 250}, - {lbNUIS, prPO}: {lbPO, LineDontBreak, 250}, - {lbNUCL, prPO}: {lbPO, LineDontBreak, 250}, - {lbNUCP, prPO}: {lbPO, LineDontBreak, 250}, - {lbNU, prPR}: {lbPR, LineDontBreak, 250}, - {lbNUNU, prPR}: {lbPR, LineDontBreak, 250}, - {lbNUSY, prPR}: {lbPR, LineDontBreak, 250}, - {lbNUIS, prPR}: {lbPR, LineDontBreak, 250}, - {lbNUCL, prPR}: {lbPR, LineDontBreak, 250}, - {lbNUCP, prPR}: {lbPR, LineDontBreak, 250}, + case lbPR | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbPO | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbOP | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbHY | prNU<<32: + return lbNU, LineDontBreak, 250 + case lbNU | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNU | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNU | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNUNU | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNUNU | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNUNU | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNUSY | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNUSY | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNUSY | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNUIS | prNU<<32: + return lbNUNU, LineDontBreak, 250 + case lbNUIS | prSY<<32: + return lbNUSY, LineDontBreak, 250 + case lbNUIS | prIS<<32: + return lbNUIS, LineDontBreak, 250 + case lbNU | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNU | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNUNU | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNUNU | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNUSY | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNUSY | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNUIS | prCL<<32: + return lbNUCL, LineDontBreak, 250 + case lbNUIS | prCP<<32: + return lbNUCP, LineDontBreak, 250 + case lbNU | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUNU | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUSY | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUIS | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUCL | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNUCP | prPO<<32: + return lbPO, LineDontBreak, 250 + case lbNU | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUNU | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUSY | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUIS | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUCL | prPR<<32: + return lbPR, LineDontBreak, 250 + case lbNUCP | prPR<<32: + return lbPR, LineDontBreak, 250 // LB26. - {lbAny, prJL}: {lbJL, LineCanBreak, 310}, - {lbAny, prJV}: {lbJV, LineCanBreak, 310}, - {lbAny, prJT}: {lbJT, LineCanBreak, 310}, - {lbAny, prH2}: {lbH2, LineCanBreak, 310}, - {lbAny, prH3}: {lbH3, LineCanBreak, 310}, - {lbJL, prJL}: {lbJL, LineDontBreak, 260}, - {lbJL, prJV}: {lbJV, LineDontBreak, 260}, - {lbJL, prH2}: {lbH2, LineDontBreak, 260}, - {lbJL, prH3}: {lbH3, LineDontBreak, 260}, - {lbJV, prJV}: {lbJV, LineDontBreak, 260}, - {lbJV, prJT}: {lbJT, LineDontBreak, 260}, - {lbH2, prJV}: {lbJV, LineDontBreak, 260}, - {lbH2, prJT}: {lbJT, LineDontBreak, 260}, - {lbJT, prJT}: {lbJT, LineDontBreak, 260}, - {lbH3, prJT}: {lbJT, LineDontBreak, 260}, + case lbAny | prJL<<32: + return lbJL, LineCanBreak, 310 + case lbAny | prJV<<32: + return lbJV, LineCanBreak, 310 + case lbAny | prJT<<32: + return lbJT, LineCanBreak, 310 + case lbAny | prH2<<32: + return lbH2, LineCanBreak, 310 + case lbAny | prH3<<32: + return lbH3, LineCanBreak, 310 + case lbJL | prJL<<32: + return lbJL, LineDontBreak, 260 + case lbJL | prJV<<32: + return lbJV, LineDontBreak, 260 + case lbJL | prH2<<32: + return lbH2, LineDontBreak, 260 + case lbJL | prH3<<32: + return lbH3, LineDontBreak, 260 + case lbJV | prJV<<32: + return lbJV, LineDontBreak, 260 + case lbJV | prJT<<32: + return lbJT, LineDontBreak, 260 + case lbH2 | prJV<<32: + return lbJV, LineDontBreak, 260 + case lbH2 | prJT<<32: + return lbJT, LineDontBreak, 260 + case lbJT | prJT<<32: + return lbJT, LineDontBreak, 260 + case lbH3 | prJT<<32: + return lbJT, LineDontBreak, 260 // LB27. - {lbJL, prPO}: {lbPO, LineDontBreak, 270}, - {lbJV, prPO}: {lbPO, LineDontBreak, 270}, - {lbJT, prPO}: {lbPO, LineDontBreak, 270}, - {lbH2, prPO}: {lbPO, LineDontBreak, 270}, - {lbH3, prPO}: {lbPO, LineDontBreak, 270}, - {lbPR, prJL}: {lbJL, LineDontBreak, 270}, - {lbPR, prJV}: {lbJV, LineDontBreak, 270}, - {lbPR, prJT}: {lbJT, LineDontBreak, 270}, - {lbPR, prH2}: {lbH2, LineDontBreak, 270}, - {lbPR, prH3}: {lbH3, LineDontBreak, 270}, + case lbJL | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbJV | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbJT | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbH2 | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbH3 | prPO<<32: + return lbPO, LineDontBreak, 270 + case lbPR | prJL<<32: + return lbJL, LineDontBreak, 270 + case lbPR | prJV<<32: + return lbJV, LineDontBreak, 270 + case lbPR | prJT<<32: + return lbJT, LineDontBreak, 270 + case lbPR | prH2<<32: + return lbH2, LineDontBreak, 270 + case lbPR | prH3<<32: + return lbH3, LineDontBreak, 270 // LB28. - {lbAL, prAL}: {lbAL, LineDontBreak, 280}, - {lbAL, prHL}: {lbHL, LineDontBreak, 280}, - {lbHL, prAL}: {lbAL, LineDontBreak, 280}, - {lbHL, prHL}: {lbHL, LineDontBreak, 280}, + case lbAL | prAL<<32: + return lbAL, LineDontBreak, 280 + case lbAL | prHL<<32: + return lbHL, LineDontBreak, 280 + case lbHL | prAL<<32: + return lbAL, LineDontBreak, 280 + case lbHL | prHL<<32: + return lbHL, LineDontBreak, 280 // LB29. - {lbIS, prAL}: {lbAL, LineDontBreak, 290}, - {lbIS, prHL}: {lbHL, LineDontBreak, 290}, - {lbNUIS, prAL}: {lbAL, LineDontBreak, 290}, - {lbNUIS, prHL}: {lbHL, LineDontBreak, 290}, + case lbIS | prAL<<32: + return lbAL, LineDontBreak, 290 + case lbIS | prHL<<32: + return lbHL, LineDontBreak, 290 + case lbNUIS | prAL<<32: + return lbAL, LineDontBreak, 290 + case lbNUIS | prHL<<32: + return lbHL, LineDontBreak, 290 + + default: + return -1, -1, -1 + } } // transitionLineBreakState determines the new state of the line break parser @@ -290,7 +449,7 @@ var lbTransitions = map[[2]int][3]int{ // further lookups. func transitionLineBreakState(state int, r rune, b []byte, str string) (newState int, lineBreak int) { // Determine the property of the next character. - nextProperty, generalCategory := propertyWithGenCat(lineBreakCodePoints, r) + nextProperty, generalCategory := propertyLineBreak(r) // Prepare. var forceNoBreak, isCPeaFWH bool @@ -306,7 +465,7 @@ func transitionLineBreakState(state int, r rune, b []byte, str string) (newState defer func() { // Transition into LB30. if newState == lbCP || newState == lbNUCP { - ea := property(eastAsianWidth, r) + ea := propertyEastAsianWidth(r) if ea != prF && ea != prW && ea != prH { newState |= lbCPeaFWHBit } @@ -352,30 +511,27 @@ func transitionLineBreakState(state int, r rune, b []byte, str string) (newState // Find the applicable transition in the table. var rule int - transition, ok := lbTransitions[[2]int{state, nextProperty}] - if ok { - // We have a specific transition. We'll use it. - newState, lineBreak, rule = transition[0], transition[1], transition[2] - } else { + newState, lineBreak, rule = lbTransitions(state, nextProperty) + if newState < 0 { // No specific transition found. Try the less specific ones. - transAnyProp, okAnyProp := lbTransitions[[2]int{state, prAny}] - transAnyState, okAnyState := lbTransitions[[2]int{lbAny, nextProperty}] - if okAnyProp && okAnyState { + anyPropProp, anyPropLineBreak, anyPropRule := lbTransitions(state, prAny) + anyStateProp, anyStateLineBreak, anyStateRule := lbTransitions(lbAny, nextProperty) + if anyPropProp >= 0 && anyStateProp >= 0 { // Both apply. We'll use a mix (see comments for grTransitions). - newState, lineBreak, rule = transAnyState[0], transAnyState[1], transAnyState[2] - if transAnyProp[2] < transAnyState[2] { - lineBreak, rule = transAnyProp[1], transAnyProp[2] + newState, lineBreak, rule = anyStateProp, anyStateLineBreak, anyStateRule + if anyPropRule < anyStateRule { + lineBreak, rule = anyPropLineBreak, anyPropRule } - } else if okAnyProp { + } else if anyPropProp >= 0 { // We only have a specific state. - newState, lineBreak, rule = transAnyProp[0], transAnyProp[1], transAnyProp[2] + newState, lineBreak, rule = anyPropProp, anyPropLineBreak, anyPropRule // This branch will probably never be reached because okAnyState will // always be true given the current transition map. But we keep it here // for future modifications to the transition map where this may not be // true anymore. - } else if okAnyState { + } else if anyStateProp >= 0 { // We only have a specific property. - newState, lineBreak, rule = transAnyState[0], transAnyState[1], transAnyState[2] + newState, lineBreak, rule = anyStateProp, anyStateLineBreak, anyStateRule } else { // No known transition. LB31: ALL ÷ ALL. newState, lineBreak, rule = lbAny, LineCanBreak, 310 @@ -414,7 +570,7 @@ func transitionLineBreakState(state int, r rune, b []byte, str string) (newState r, _ = utf8.DecodeRuneInString(str) } if r != utf8.RuneError { - pr, _ := propertyWithGenCat(lineBreakCodePoints, r) + pr, _ := propertyLineBreak(r) if pr == prNU { return lbNU, LineDontBreak } @@ -424,7 +580,7 @@ func transitionLineBreakState(state int, r rune, b []byte, str string) (newState // LB30 (part one). if rule > 300 { if (state == lbAL || state == lbHL || state == lbNU || state == lbNUNU) && nextProperty == prOP { - ea := property(eastAsianWidth, r) + ea := propertyEastAsianWidth(r) if ea != prF && ea != prW && ea != prH { return lbOP, LineDontBreak } @@ -460,7 +616,7 @@ func transitionLineBreakState(state int, r rune, b []byte, str string) (newState return prAny, LineDontBreak } } - graphemeProperty := property(graphemeCodePoints, r) + graphemeProperty := propertyGraphemes(r) if graphemeProperty == prExtendedPictographic && generalCategory == gcCn { return lbExtPicCn, LineCanBreak } diff --git a/vendor/github.com/rivo/uniseg/properties.go b/vendor/github.com/rivo/uniseg/properties.go index bc3c7bc..6290e68 100644 --- a/vendor/github.com/rivo/uniseg/properties.go +++ b/vendor/github.com/rivo/uniseg/properties.go @@ -160,9 +160,49 @@ func property(dictionary [][3]int, r rune) int { return propertySearch(dictionary, r)[2] } -// propertyWithGenCat returns the Unicode property value and General Category -// (see constants above) of the given code point. -func propertyWithGenCat(dictionary [][4]int, r rune) (property, generalCategory int) { - entry := propertySearch(dictionary, r) +// propertyLineBreak returns the Unicode property value and General Category +// (see constants above) of the given code point, as listed in the line break +// code points table, while fast tracking ASCII digits and letters. +func propertyLineBreak(r rune) (property, generalCategory int) { + if r >= 'a' && r <= 'z' { + return prAL, gcLl + } + if r >= 'A' && r <= 'Z' { + return prAL, gcLu + } + if r >= '0' && r <= '9' { + return prNU, gcNd + } + entry := propertySearch(lineBreakCodePoints, r) return entry[2], entry[3] } + +// propertyGraphemes returns the Unicode grapheme cluster property value of the +// given code point while fast tracking ASCII characters. +func propertyGraphemes(r rune) int { + if r >= 0x20 && r <= 0x7e { + return prAny + } + if r == 0x0a { + return prLF + } + if r == 0x0d { + return prCR + } + if r >= 0 && r <= 0x1f || r == 0x7f { + return prControl + } + return property(graphemeCodePoints, r) +} + +// propertyEastAsianWidth returns the Unicode East Asian Width property value of +// the given code point while fast tracking ASCII characters. +func propertyEastAsianWidth(r rune) int { + if r >= 0x20 && r <= 0x7e { + return prNa + } + if r >= 0 && r <= 0x1f || r == 0x7f { + return prN + } + return property(eastAsianWidth, r) +} diff --git a/vendor/github.com/rivo/uniseg/sentenceproperties.go b/vendor/github.com/rivo/uniseg/sentenceproperties.go index ba0cf2d..67717ec 100644 --- a/vendor/github.com/rivo/uniseg/sentenceproperties.go +++ b/vendor/github.com/rivo/uniseg/sentenceproperties.go @@ -1,13 +1,13 @@ -package uniseg - // Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg + // sentenceBreakCodePoints are taken from -// https://www.unicode.org/Public/14.0.0/ucd/auxiliary/SentenceBreakProperty.txt +// https://www.unicode.org/Public/15.0.0/ucd/auxiliary/SentenceBreakProperty.txt // and -// https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt // ("Extended_Pictographic" only) -// on September 10, 2022. See https://www.unicode.org/license.html for the Unicode +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode // license agreement. var sentenceBreakCodePoints = [][3]int{ {0x0009, 0x0009, prSp}, // Cc @@ -843,6 +843,7 @@ var sentenceBreakCodePoints = [][3]int{ {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL {0x0CE6, 0x0CEF, prNumeric}, // Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE {0x0CF1, 0x0CF2, prOLetter}, // Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prExtend}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU {0x0D02, 0x0D03, prExtend}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA {0x0D04, 0x0D0C, prOLetter}, // Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L @@ -896,7 +897,7 @@ var sentenceBreakCodePoints = [][3]int{ {0x0EBD, 0x0EBD, prOLetter}, // Lo LAO SEMIVOWEL SIGN NYO {0x0EC0, 0x0EC4, prOLetter}, // Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI {0x0EC6, 0x0EC6, prOLetter}, // Lm LAO KO LA - {0x0EC8, 0x0ECD, prExtend}, // Mn [6] LAO TONE MAI EK..LAO NIGGAHITA + {0x0EC8, 0x0ECE, prExtend}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN {0x0ED0, 0x0ED9, prNumeric}, // Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE {0x0EDC, 0x0EDF, prOLetter}, // Lo [4] LAO HO NO..LAO LETTER KHMU NYO {0x0F00, 0x0F00, prOLetter}, // Lo TIBETAN SYLLABLE OM @@ -958,7 +959,7 @@ var sentenceBreakCodePoints = [][3]int{ {0x10C7, 0x10C7, prUpper}, // L& GEORGIAN CAPITAL LETTER YN {0x10CD, 0x10CD, prUpper}, // L& GEORGIAN CAPITAL LETTER AEN {0x10D0, 0x10FA, prOLetter}, // L& [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN - {0x10FC, 0x10FC, prOLetter}, // Lm MODIFIER LETTER GEORGIAN NAR + {0x10FC, 0x10FC, prLower}, // Lm MODIFIER LETTER GEORGIAN NAR {0x10FD, 0x10FF, prOLetter}, // L& [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN {0x1100, 0x1248, prOLetter}, // Lo [329] HANGUL CHOSEONG KIYEOK..ETHIOPIC SYLLABLE QWA {0x124A, 0x124D, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE @@ -2034,7 +2035,7 @@ var sentenceBreakCodePoints = [][3]int{ {0xA7D7, 0xA7D7, prLower}, // L& LATIN SMALL LETTER MIDDLE SCOTS S {0xA7D8, 0xA7D8, prUpper}, // L& LATIN CAPITAL LETTER SIGMOID S {0xA7D9, 0xA7D9, prLower}, // L& LATIN SMALL LETTER SIGMOID S - {0xA7F2, 0xA7F4, prOLetter}, // Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q + {0xA7F2, 0xA7F4, prLower}, // Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q {0xA7F5, 0xA7F5, prUpper}, // L& LATIN CAPITAL LETTER REVERSED HALF H {0xA7F6, 0xA7F6, prLower}, // L& LATIN SMALL LETTER REVERSED HALF H {0xA7F7, 0xA7F7, prOLetter}, // Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I @@ -2140,7 +2141,7 @@ var sentenceBreakCodePoints = [][3]int{ {0xAB30, 0xAB5A, prLower}, // L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG {0xAB5C, 0xAB5F, prLower}, // Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK {0xAB60, 0xAB68, prLower}, // L& [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE - {0xAB69, 0xAB69, prOLetter}, // Lm MODIFIER LETTER SMALL TURNED W + {0xAB69, 0xAB69, prLower}, // Lm MODIFIER LETTER SMALL TURNED W {0xAB70, 0xABBF, prLower}, // L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA {0xABC0, 0xABE2, prOLetter}, // Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM {0xABE3, 0xABE4, prExtend}, // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP @@ -2334,6 +2335,7 @@ var sentenceBreakCodePoints = [][3]int{ {0x10E80, 0x10EA9, prOLetter}, // Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET {0x10EAB, 0x10EAC, prExtend}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK {0x10EB0, 0x10EB1, prOLetter}, // Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prExtend}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA {0x10F00, 0x10F1C, prOLetter}, // Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL {0x10F27, 0x10F27, prOLetter}, // Lo OLD SOGDIAN LIGATURE AYIN-DALETH {0x10F30, 0x10F45, prOLetter}, // Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN @@ -2408,6 +2410,8 @@ var sentenceBreakCodePoints = [][3]int{ {0x11238, 0x11239, prSTerm}, // Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA {0x1123B, 0x1123C, prSTerm}, // Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prOLetter}, // Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prExtend}, // Mn KHOJKI VOWEL SIGN VOCALIC R {0x11280, 0x11286, prOLetter}, // Lo [7] MULTANI LETTER A..MULTANI LETTER GA {0x11288, 0x11288, prOLetter}, // Lo MULTANI LETTER GHA {0x1128A, 0x1128D, prOLetter}, // Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA @@ -2603,13 +2607,29 @@ var sentenceBreakCodePoints = [][3]int{ {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U {0x11EF5, 0x11EF6, prExtend}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O {0x11EF7, 0x11EF8, prSTerm}, // Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION + {0x11F00, 0x11F01, prExtend}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prOLetter}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prExtend}, // Mc KAWI SIGN VISARGA + {0x11F04, 0x11F10, prOLetter}, // Lo [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prOLetter}, // Lo [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prExtend}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prExtend}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prExtend}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prExtend}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prExtend}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prExtend}, // Mn KAWI CONJOINER + {0x11F43, 0x11F44, prSTerm}, // Po [2] KAWI DANDA..KAWI DOUBLE DANDA + {0x11F50, 0x11F59, prNumeric}, // Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE {0x11FB0, 0x11FB0, prOLetter}, // Lo LISU LETTER YHA {0x12000, 0x12399, prOLetter}, // Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U {0x12400, 0x1246E, prOLetter}, // Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM {0x12480, 0x12543, prOLetter}, // Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU {0x12F90, 0x12FF0, prOLetter}, // Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 - {0x13000, 0x1342E, prOLetter}, // Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 - {0x13430, 0x13438, prFormat}, // Cf [9] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT + {0x13000, 0x1342F, prOLetter}, // Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x1343F, prFormat}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prExtend}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prOLetter}, // Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prExtend}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED {0x14400, 0x14646, prOLetter}, // Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 {0x16800, 0x16A38, prOLetter}, // Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ {0x16A40, 0x16A5E, prOLetter}, // Lo [31] MRO LETTER TA..MRO LETTER TEK @@ -2648,7 +2668,9 @@ var sentenceBreakCodePoints = [][3]int{ {0x1AFF5, 0x1AFFB, prOLetter}, // Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5 {0x1AFFD, 0x1AFFE, prOLetter}, // Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 {0x1B000, 0x1B122, prOLetter}, // Lo [291] KATAKANA LETTER ARCHAIC E..KATAKANA LETTER ARCHAIC WU + {0x1B132, 0x1B132, prOLetter}, // Lo HIRAGANA LETTER SMALL KO {0x1B150, 0x1B152, prOLetter}, // Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO + {0x1B155, 0x1B155, prOLetter}, // Lo KATAKANA LETTER SMALL KO {0x1B164, 0x1B167, prOLetter}, // Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N {0x1B170, 0x1B2FB, prOLetter}, // Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB {0x1BC00, 0x1BC6A, prOLetter}, // Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M @@ -2738,11 +2760,14 @@ var sentenceBreakCodePoints = [][3]int{ {0x1DF00, 0x1DF09, prLower}, // L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK {0x1DF0A, 0x1DF0A, prOLetter}, // Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK {0x1DF0B, 0x1DF1E, prLower}, // L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prLower}, // L& [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK {0x1E000, 0x1E006, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE {0x1E008, 0x1E018, prExtend}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prLower}, // Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prExtend}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I {0x1E100, 0x1E12C, prOLetter}, // Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D {0x1E137, 0x1E13D, prOLetter}, // Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER @@ -2753,6 +2778,10 @@ var sentenceBreakCodePoints = [][3]int{ {0x1E2C0, 0x1E2EB, prOLetter}, // Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI {0x1E2F0, 0x1E2F9, prNumeric}, // Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE + {0x1E4D0, 0x1E4EA, prOLetter}, // Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prOLetter}, // Lm NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prExtend}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prNumeric}, // Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE {0x1E7E0, 0x1E7E6, prOLetter}, // Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO {0x1E7E8, 0x1E7EB, prOLetter}, // Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE {0x1E7ED, 0x1E7EE, prOLetter}, // Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE @@ -2803,12 +2832,13 @@ var sentenceBreakCodePoints = [][3]int{ {0x1F676, 0x1F678, prClose}, // So [3] SANS-SERIF HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT..SANS-SERIF HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT {0x1FBF0, 0x1FBF9, prNumeric}, // Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE {0x20000, 0x2A6DF, prOLetter}, // Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF - {0x2A700, 0x2B738, prOLetter}, // Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738 + {0x2A700, 0x2B739, prOLetter}, // Lo [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739 {0x2B740, 0x2B81D, prOLetter}, // Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D {0x2B820, 0x2CEA1, prOLetter}, // Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1 {0x2CEB0, 0x2EBE0, prOLetter}, // Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0 {0x2F800, 0x2FA1D, prOLetter}, // Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D {0x30000, 0x3134A, prOLetter}, // Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A + {0x31350, 0x323AF, prOLetter}, // Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF {0xE0001, 0xE0001, prFormat}, // Cf LANGUAGE TAG {0xE0020, 0xE007F, prExtend}, // Cf [96] TAG SPACE..CANCEL TAG {0xE0100, 0xE01EF, prExtend}, // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256 diff --git a/vendor/github.com/rivo/uniseg/sentencerules.go b/vendor/github.com/rivo/uniseg/sentencerules.go index 58c0479..0b29c7b 100644 --- a/vendor/github.com/rivo/uniseg/sentencerules.go +++ b/vendor/github.com/rivo/uniseg/sentencerules.go @@ -18,104 +18,178 @@ const ( sbSB8aSp ) -// The sentence break parser's breaking instructions. -const ( - sbDontBreak = iota - sbBreak -) - -// The sentence break parser's state transitions. It's anologous to -// grTransitions, see comments there for details. Unicode version 14.0.0. -var sbTransitions = map[[2]int][3]int{ +// sbTransitions implements the sentence break parser's state transitions. It's +// anologous to [grTransitions], see comments there for details. +// +// Unicode version 15.0.0. +func sbTransitions(state, prop int) (newState int, sentenceBreak bool, rule int) { + switch uint64(state) | uint64(prop)<<32 { // SB3. - {sbAny, prCR}: {sbCR, sbDontBreak, 9990}, - {sbCR, prLF}: {sbParaSep, sbDontBreak, 30}, + case sbAny | prCR<<32: + return sbCR, false, 9990 + case sbCR | prLF<<32: + return sbParaSep, false, 30 // SB4. - {sbAny, prSep}: {sbParaSep, sbDontBreak, 9990}, - {sbAny, prLF}: {sbParaSep, sbDontBreak, 9990}, - {sbParaSep, prAny}: {sbAny, sbBreak, 40}, - {sbCR, prAny}: {sbAny, sbBreak, 40}, + case sbAny | prSep<<32: + return sbParaSep, false, 9990 + case sbAny | prLF<<32: + return sbParaSep, false, 9990 + case sbParaSep | prAny<<32: + return sbAny, true, 40 + case sbCR | prAny<<32: + return sbAny, true, 40 // SB6. - {sbAny, prATerm}: {sbATerm, sbDontBreak, 9990}, - {sbATerm, prNumeric}: {sbAny, sbDontBreak, 60}, - {sbSB7, prNumeric}: {sbAny, sbDontBreak, 60}, // Because ATerm also appears in SB7. + case sbAny | prATerm<<32: + return sbATerm, false, 9990 + case sbATerm | prNumeric<<32: + return sbAny, false, 60 + case sbSB7 | prNumeric<<32: + return sbAny, false, 60 // Because ATerm also appears in SB7. // SB7. - {sbAny, prUpper}: {sbUpper, sbDontBreak, 9990}, - {sbAny, prLower}: {sbLower, sbDontBreak, 9990}, - {sbUpper, prATerm}: {sbSB7, sbDontBreak, 70}, - {sbLower, prATerm}: {sbSB7, sbDontBreak, 70}, - {sbSB7, prUpper}: {sbUpper, sbDontBreak, 70}, + case sbAny | prUpper<<32: + return sbUpper, false, 9990 + case sbAny | prLower<<32: + return sbLower, false, 9990 + case sbUpper | prATerm<<32: + return sbSB7, false, 70 + case sbLower | prATerm<<32: + return sbSB7, false, 70 + case sbSB7 | prUpper<<32: + return sbUpper, false, 70 // SB8a. - {sbAny, prSTerm}: {sbSTerm, sbDontBreak, 9990}, - {sbATerm, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbATerm, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbATerm, prSTerm}: {sbSTerm, sbDontBreak, 81}, - {sbSB7, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbSB7, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbSB7, prSTerm}: {sbSTerm, sbDontBreak, 81}, - {sbSB8Close, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbSB8Close, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbSB8Close, prSTerm}: {sbSTerm, sbDontBreak, 81}, - {sbSB8Sp, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbSB8Sp, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbSB8Sp, prSTerm}: {sbSTerm, sbDontBreak, 81}, - {sbSTerm, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbSTerm, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbSTerm, prSTerm}: {sbSTerm, sbDontBreak, 81}, - {sbSB8aClose, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbSB8aClose, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbSB8aClose, prSTerm}: {sbSTerm, sbDontBreak, 81}, - {sbSB8aSp, prSContinue}: {sbAny, sbDontBreak, 81}, - {sbSB8aSp, prATerm}: {sbATerm, sbDontBreak, 81}, - {sbSB8aSp, prSTerm}: {sbSTerm, sbDontBreak, 81}, + case sbAny | prSTerm<<32: + return sbSTerm, false, 9990 + case sbATerm | prSContinue<<32: + return sbAny, false, 81 + case sbATerm | prATerm<<32: + return sbATerm, false, 81 + case sbATerm | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB7 | prSContinue<<32: + return sbAny, false, 81 + case sbSB7 | prATerm<<32: + return sbATerm, false, 81 + case sbSB7 | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8Close | prSContinue<<32: + return sbAny, false, 81 + case sbSB8Close | prATerm<<32: + return sbATerm, false, 81 + case sbSB8Close | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8Sp | prSContinue<<32: + return sbAny, false, 81 + case sbSB8Sp | prATerm<<32: + return sbATerm, false, 81 + case sbSB8Sp | prSTerm<<32: + return sbSTerm, false, 81 + case sbSTerm | prSContinue<<32: + return sbAny, false, 81 + case sbSTerm | prATerm<<32: + return sbATerm, false, 81 + case sbSTerm | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8aClose | prSContinue<<32: + return sbAny, false, 81 + case sbSB8aClose | prATerm<<32: + return sbATerm, false, 81 + case sbSB8aClose | prSTerm<<32: + return sbSTerm, false, 81 + case sbSB8aSp | prSContinue<<32: + return sbAny, false, 81 + case sbSB8aSp | prATerm<<32: + return sbATerm, false, 81 + case sbSB8aSp | prSTerm<<32: + return sbSTerm, false, 81 // SB9. - {sbATerm, prClose}: {sbSB8Close, sbDontBreak, 90}, - {sbSB7, prClose}: {sbSB8Close, sbDontBreak, 90}, - {sbSB8Close, prClose}: {sbSB8Close, sbDontBreak, 90}, - {sbATerm, prSp}: {sbSB8Sp, sbDontBreak, 90}, - {sbSB7, prSp}: {sbSB8Sp, sbDontBreak, 90}, - {sbSB8Close, prSp}: {sbSB8Sp, sbDontBreak, 90}, - {sbSTerm, prClose}: {sbSB8aClose, sbDontBreak, 90}, - {sbSB8aClose, prClose}: {sbSB8aClose, sbDontBreak, 90}, - {sbSTerm, prSp}: {sbSB8aSp, sbDontBreak, 90}, - {sbSB8aClose, prSp}: {sbSB8aSp, sbDontBreak, 90}, - {sbATerm, prSep}: {sbParaSep, sbDontBreak, 90}, - {sbATerm, prCR}: {sbParaSep, sbDontBreak, 90}, - {sbATerm, prLF}: {sbParaSep, sbDontBreak, 90}, - {sbSB7, prSep}: {sbParaSep, sbDontBreak, 90}, - {sbSB7, prCR}: {sbParaSep, sbDontBreak, 90}, - {sbSB7, prLF}: {sbParaSep, sbDontBreak, 90}, - {sbSB8Close, prSep}: {sbParaSep, sbDontBreak, 90}, - {sbSB8Close, prCR}: {sbParaSep, sbDontBreak, 90}, - {sbSB8Close, prLF}: {sbParaSep, sbDontBreak, 90}, - {sbSTerm, prSep}: {sbParaSep, sbDontBreak, 90}, - {sbSTerm, prCR}: {sbParaSep, sbDontBreak, 90}, - {sbSTerm, prLF}: {sbParaSep, sbDontBreak, 90}, - {sbSB8aClose, prSep}: {sbParaSep, sbDontBreak, 90}, - {sbSB8aClose, prCR}: {sbParaSep, sbDontBreak, 90}, - {sbSB8aClose, prLF}: {sbParaSep, sbDontBreak, 90}, + case sbATerm | prClose<<32: + return sbSB8Close, false, 90 + case sbSB7 | prClose<<32: + return sbSB8Close, false, 90 + case sbSB8Close | prClose<<32: + return sbSB8Close, false, 90 + case sbATerm | prSp<<32: + return sbSB8Sp, false, 90 + case sbSB7 | prSp<<32: + return sbSB8Sp, false, 90 + case sbSB8Close | prSp<<32: + return sbSB8Sp, false, 90 + case sbSTerm | prClose<<32: + return sbSB8aClose, false, 90 + case sbSB8aClose | prClose<<32: + return sbSB8aClose, false, 90 + case sbSTerm | prSp<<32: + return sbSB8aSp, false, 90 + case sbSB8aClose | prSp<<32: + return sbSB8aSp, false, 90 + case sbATerm | prSep<<32: + return sbParaSep, false, 90 + case sbATerm | prCR<<32: + return sbParaSep, false, 90 + case sbATerm | prLF<<32: + return sbParaSep, false, 90 + case sbSB7 | prSep<<32: + return sbParaSep, false, 90 + case sbSB7 | prCR<<32: + return sbParaSep, false, 90 + case sbSB7 | prLF<<32: + return sbParaSep, false, 90 + case sbSB8Close | prSep<<32: + return sbParaSep, false, 90 + case sbSB8Close | prCR<<32: + return sbParaSep, false, 90 + case sbSB8Close | prLF<<32: + return sbParaSep, false, 90 + case sbSTerm | prSep<<32: + return sbParaSep, false, 90 + case sbSTerm | prCR<<32: + return sbParaSep, false, 90 + case sbSTerm | prLF<<32: + return sbParaSep, false, 90 + case sbSB8aClose | prSep<<32: + return sbParaSep, false, 90 + case sbSB8aClose | prCR<<32: + return sbParaSep, false, 90 + case sbSB8aClose | prLF<<32: + return sbParaSep, false, 90 // SB10. - {sbSB8Sp, prSp}: {sbSB8Sp, sbDontBreak, 100}, - {sbSB8aSp, prSp}: {sbSB8aSp, sbDontBreak, 100}, - {sbSB8Sp, prSep}: {sbParaSep, sbDontBreak, 100}, - {sbSB8Sp, prCR}: {sbParaSep, sbDontBreak, 100}, - {sbSB8Sp, prLF}: {sbParaSep, sbDontBreak, 100}, + case sbSB8Sp | prSp<<32: + return sbSB8Sp, false, 100 + case sbSB8aSp | prSp<<32: + return sbSB8aSp, false, 100 + case sbSB8Sp | prSep<<32: + return sbParaSep, false, 100 + case sbSB8Sp | prCR<<32: + return sbParaSep, false, 100 + case sbSB8Sp | prLF<<32: + return sbParaSep, false, 100 // SB11. - {sbATerm, prAny}: {sbAny, sbBreak, 110}, - {sbSB7, prAny}: {sbAny, sbBreak, 110}, - {sbSB8Close, prAny}: {sbAny, sbBreak, 110}, - {sbSB8Sp, prAny}: {sbAny, sbBreak, 110}, - {sbSTerm, prAny}: {sbAny, sbBreak, 110}, - {sbSB8aClose, prAny}: {sbAny, sbBreak, 110}, - {sbSB8aSp, prAny}: {sbAny, sbBreak, 110}, + case sbATerm | prAny<<32: + return sbAny, true, 110 + case sbSB7 | prAny<<32: + return sbAny, true, 110 + case sbSB8Close | prAny<<32: + return sbAny, true, 110 + case sbSB8Sp | prAny<<32: + return sbAny, true, 110 + case sbSTerm | prAny<<32: + return sbAny, true, 110 + case sbSB8aClose | prAny<<32: + return sbAny, true, 110 + case sbSB8aSp | prAny<<32: + return sbAny, true, 110 // We'll always break after ParaSep due to SB4. + + default: + return -1, false, -1 + } } // transitionSentenceBreakState determines the new state of the sentence break @@ -141,30 +215,27 @@ func transitionSentenceBreakState(state int, r rune, b []byte, str string) (newS // Find the applicable transition in the table. var rule int - transition, ok := sbTransitions[[2]int{state, nextProperty}] - if ok { - // We have a specific transition. We'll use it. - newState, sentenceBreak, rule = transition[0], transition[1] == sbBreak, transition[2] - } else { + newState, sentenceBreak, rule = sbTransitions(state, nextProperty) + if newState < 0 { // No specific transition found. Try the less specific ones. - transAnyProp, okAnyProp := sbTransitions[[2]int{state, prAny}] - transAnyState, okAnyState := sbTransitions[[2]int{sbAny, nextProperty}] - if okAnyProp && okAnyState { + anyPropState, anyPropProp, anyPropRule := sbTransitions(state, prAny) + anyStateState, anyStateProp, anyStateRule := sbTransitions(sbAny, nextProperty) + if anyPropState >= 0 && anyStateState >= 0 { // Both apply. We'll use a mix (see comments for grTransitions). - newState, sentenceBreak, rule = transAnyState[0], transAnyState[1] == sbBreak, transAnyState[2] - if transAnyProp[2] < transAnyState[2] { - sentenceBreak, rule = transAnyProp[1] == sbBreak, transAnyProp[2] + newState, sentenceBreak, rule = anyStateState, anyStateProp, anyStateRule + if anyPropRule < anyStateRule { + sentenceBreak, rule = anyPropProp, anyPropRule } - } else if okAnyProp { + } else if anyPropState >= 0 { // We only have a specific state. - newState, sentenceBreak, rule = transAnyProp[0], transAnyProp[1] == sbBreak, transAnyProp[2] + newState, sentenceBreak, rule = anyPropState, anyPropProp, anyPropRule // This branch will probably never be reached because okAnyState will // always be true given the current transition map. But we keep it here // for future modifications to the transition map where this may not be // true anymore. - } else if okAnyState { + } else if anyStateState >= 0 { // We only have a specific property. - newState, sentenceBreak, rule = transAnyState[0], transAnyState[1] == sbBreak, transAnyState[2] + newState, sentenceBreak, rule = anyStateState, anyStateProp, anyStateRule } else { // No known transition. SB999: Any × Any. newState, sentenceBreak, rule = sbAny, false, 9990 diff --git a/vendor/github.com/rivo/uniseg/step.go b/vendor/github.com/rivo/uniseg/step.go index 6eca4b5..2959b69 100644 --- a/vendor/github.com/rivo/uniseg/step.go +++ b/vendor/github.com/rivo/uniseg/step.go @@ -100,7 +100,7 @@ func Step(b []byte, state int) (cluster, rest []byte, boundaries int, newState i if len(b) <= length { // If we're already past the end, there is nothing else to parse. var prop int if state < 0 { - prop = property(graphemeCodePoints, r) + prop = propertyGraphemes(r) } else { prop = state >> shiftPropState } @@ -179,7 +179,7 @@ func StepString(str string, state int) (cluster, rest string, boundaries int, ne // Extract the first rune. r, length := utf8.DecodeRuneInString(str) if len(str) <= length { // If we're already past the end, there is nothing else to parse. - prop := property(graphemeCodePoints, r) + prop := propertyGraphemes(r) return str, "", LineMustBreak | (1 << shiftWord) | (1 << shiftSentence) | (runeWidth(r, prop) << ShiftWidth), grAny | (wbAny << shiftWordState) | (sbAny << shiftSentenceState) | (lbAny << shiftLineState) } diff --git a/vendor/github.com/rivo/uniseg/width.go b/vendor/github.com/rivo/uniseg/width.go index 12a57cc..975a9f1 100644 --- a/vendor/github.com/rivo/uniseg/width.go +++ b/vendor/github.com/rivo/uniseg/width.go @@ -1,5 +1,10 @@ package uniseg +// EastAsianAmbiguousWidth specifies the monospace width for East Asian +// characters classified as Ambiguous. The default is 1 but some rare fonts +// render them with a width of 2. +var EastAsianAmbiguousWidth = 1 + // runeWidth returns the monospace width for the given rune. The provided // grapheme property is a value mapped by the [graphemeCodePoints] table. // @@ -33,9 +38,11 @@ func runeWidth(r rune, graphemeProperty int) int { return 4 } - switch property(eastAsianWidth, r) { + switch propertyEastAsianWidth(r) { case prW, prF: return 2 + case prA: + return EastAsianAmbiguousWidth } return 1 diff --git a/vendor/github.com/rivo/uniseg/wordproperties.go b/vendor/github.com/rivo/uniseg/wordproperties.go index 805cc53..277ca10 100644 --- a/vendor/github.com/rivo/uniseg/wordproperties.go +++ b/vendor/github.com/rivo/uniseg/wordproperties.go @@ -1,13 +1,13 @@ -package uniseg - // Code generated via go generate from gen_properties.go. DO NOT EDIT. +package uniseg + // workBreakCodePoints are taken from -// https://www.unicode.org/Public/14.0.0/ucd/auxiliary/WordBreakProperty.txt +// https://www.unicode.org/Public/15.0.0/ucd/auxiliary/WordBreakProperty.txt // and -// https://unicode.org/Public/14.0.0/ucd/emoji/emoji-data.txt +// https://unicode.org/Public/15.0.0/ucd/emoji/emoji-data.txt // ("Extended_Pictographic" only) -// on September 10, 2022. See https://www.unicode.org/license.html for the Unicode +// on September 5, 2023. See https://www.unicode.org/license.html for the Unicode // license agreement. var workBreakCodePoints = [][3]int{ {0x000A, 0x000A, prLF}, // Cc @@ -318,6 +318,7 @@ var workBreakCodePoints = [][3]int{ {0x0CE2, 0x0CE3, prExtend}, // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL {0x0CE6, 0x0CEF, prNumeric}, // Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE {0x0CF1, 0x0CF2, prALetter}, // Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA + {0x0CF3, 0x0CF3, prExtend}, // Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT {0x0D00, 0x0D01, prExtend}, // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU {0x0D02, 0x0D03, prExtend}, // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA {0x0D04, 0x0D0C, prALetter}, // Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L @@ -357,7 +358,7 @@ var workBreakCodePoints = [][3]int{ {0x0E50, 0x0E59, prNumeric}, // Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE {0x0EB1, 0x0EB1, prExtend}, // Mn LAO VOWEL SIGN MAI KAN {0x0EB4, 0x0EBC, prExtend}, // Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO - {0x0EC8, 0x0ECD, prExtend}, // Mn [6] LAO TONE MAI EK..LAO NIGGAHITA + {0x0EC8, 0x0ECE, prExtend}, // Mn [7] LAO TONE MAI EK..LAO YAMAKKAN {0x0ED0, 0x0ED9, prNumeric}, // Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE {0x0F00, 0x0F00, prALetter}, // Lo TIBETAN SYLLABLE OM {0x0F18, 0x0F19, prExtend}, // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS @@ -1093,6 +1094,7 @@ var workBreakCodePoints = [][3]int{ {0x10E80, 0x10EA9, prALetter}, // Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET {0x10EAB, 0x10EAC, prExtend}, // Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK {0x10EB0, 0x10EB1, prALetter}, // Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE + {0x10EFD, 0x10EFF, prExtend}, // Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA {0x10F00, 0x10F1C, prALetter}, // Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL {0x10F27, 0x10F27, prALetter}, // Lo OLD SOGDIAN LIGATURE AYIN-DALETH {0x10F30, 0x10F45, prALetter}, // Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN @@ -1157,6 +1159,8 @@ var workBreakCodePoints = [][3]int{ {0x11235, 0x11235, prExtend}, // Mc KHOJKI SIGN VIRAMA {0x11236, 0x11237, prExtend}, // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA {0x1123E, 0x1123E, prExtend}, // Mn KHOJKI SIGN SUKUN + {0x1123F, 0x11240, prALetter}, // Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I + {0x11241, 0x11241, prExtend}, // Mn KHOJKI VOWEL SIGN VOCALIC R {0x11280, 0x11286, prALetter}, // Lo [7] MULTANI LETTER A..MULTANI LETTER GA {0x11288, 0x11288, prALetter}, // Lo MULTANI LETTER GHA {0x1128A, 0x1128D, prALetter}, // Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA @@ -1337,13 +1341,28 @@ var workBreakCodePoints = [][3]int{ {0x11EE0, 0x11EF2, prALetter}, // Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA {0x11EF3, 0x11EF4, prExtend}, // Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U {0x11EF5, 0x11EF6, prExtend}, // Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O + {0x11F00, 0x11F01, prExtend}, // Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA + {0x11F02, 0x11F02, prALetter}, // Lo KAWI SIGN REPHA + {0x11F03, 0x11F03, prExtend}, // Mc KAWI SIGN VISARGA + {0x11F04, 0x11F10, prALetter}, // Lo [13] KAWI LETTER A..KAWI LETTER O + {0x11F12, 0x11F33, prALetter}, // Lo [34] KAWI LETTER KA..KAWI LETTER JNYA + {0x11F34, 0x11F35, prExtend}, // Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA + {0x11F36, 0x11F3A, prExtend}, // Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R + {0x11F3E, 0x11F3F, prExtend}, // Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI + {0x11F40, 0x11F40, prExtend}, // Mn KAWI VOWEL SIGN EU + {0x11F41, 0x11F41, prExtend}, // Mc KAWI SIGN KILLER + {0x11F42, 0x11F42, prExtend}, // Mn KAWI CONJOINER + {0x11F50, 0x11F59, prNumeric}, // Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE {0x11FB0, 0x11FB0, prALetter}, // Lo LISU LETTER YHA {0x12000, 0x12399, prALetter}, // Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U {0x12400, 0x1246E, prALetter}, // Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM {0x12480, 0x12543, prALetter}, // Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU {0x12F90, 0x12FF0, prALetter}, // Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114 - {0x13000, 0x1342E, prALetter}, // Lo [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032 - {0x13430, 0x13438, prFormat}, // Cf [9] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END SEGMENT + {0x13000, 0x1342F, prALetter}, // Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D + {0x13430, 0x1343F, prFormat}, // Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE + {0x13440, 0x13440, prExtend}, // Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY + {0x13441, 0x13446, prALetter}, // Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN + {0x13447, 0x13455, prExtend}, // Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED {0x14400, 0x14646, prALetter}, // Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530 {0x16800, 0x16A38, prALetter}, // Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ {0x16A40, 0x16A5E, prALetter}, // Lo [31] MRO LETTER TA..MRO LETTER TEK @@ -1374,6 +1393,7 @@ var workBreakCodePoints = [][3]int{ {0x1AFFD, 0x1AFFE, prKatakana}, // Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8 {0x1B000, 0x1B000, prKatakana}, // Lo KATAKANA LETTER ARCHAIC E {0x1B120, 0x1B122, prKatakana}, // Lo [3] KATAKANA LETTER ARCHAIC YI..KATAKANA LETTER ARCHAIC WU + {0x1B155, 0x1B155, prKatakana}, // Lo KATAKANA LETTER SMALL KO {0x1B164, 0x1B167, prKatakana}, // Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N {0x1BC00, 0x1BC6A, prALetter}, // Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M {0x1BC70, 0x1BC7C, prALetter}, // Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK @@ -1431,11 +1451,14 @@ var workBreakCodePoints = [][3]int{ {0x1DF00, 0x1DF09, prALetter}, // L& [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK {0x1DF0A, 0x1DF0A, prALetter}, // Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK {0x1DF0B, 0x1DF1E, prALetter}, // L& [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL + {0x1DF25, 0x1DF2A, prALetter}, // L& [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK {0x1E000, 0x1E006, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE {0x1E008, 0x1E018, prExtend}, // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU {0x1E01B, 0x1E021, prExtend}, // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI {0x1E023, 0x1E024, prExtend}, // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS {0x1E026, 0x1E02A, prExtend}, // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA + {0x1E030, 0x1E06D, prALetter}, // Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE + {0x1E08F, 0x1E08F, prExtend}, // Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I {0x1E100, 0x1E12C, prALetter}, // Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W {0x1E130, 0x1E136, prExtend}, // Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D {0x1E137, 0x1E13D, prALetter}, // Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER @@ -1446,6 +1469,10 @@ var workBreakCodePoints = [][3]int{ {0x1E2C0, 0x1E2EB, prALetter}, // Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH {0x1E2EC, 0x1E2EF, prExtend}, // Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI {0x1E2F0, 0x1E2F9, prNumeric}, // Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE + {0x1E4D0, 0x1E4EA, prALetter}, // Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL + {0x1E4EB, 0x1E4EB, prALetter}, // Lm NAG MUNDARI SIGN OJOD + {0x1E4EC, 0x1E4EF, prExtend}, // Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH + {0x1E4F0, 0x1E4F9, prNumeric}, // Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE {0x1E7E0, 0x1E7E6, prALetter}, // Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO {0x1E7E8, 0x1E7EB, prALetter}, // Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE {0x1E7ED, 0x1E7EE, prALetter}, // Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE @@ -1740,7 +1767,8 @@ var workBreakCodePoints = [][3]int{ {0x1F6D3, 0x1F6D4, prExtendedPictographic}, // E0.0 [2] (🛓..🛔) STUPA..PAGODA {0x1F6D5, 0x1F6D5, prExtendedPictographic}, // E12.0 [1] (🛕) hindu temple {0x1F6D6, 0x1F6D7, prExtendedPictographic}, // E13.0 [2] (🛖..🛗) hut..elevator - {0x1F6D8, 0x1F6DC, prExtendedPictographic}, // E0.0 [5] (🛘..🛜) .. + {0x1F6D8, 0x1F6DB, prExtendedPictographic}, // E0.0 [4] (🛘..🛛) .. + {0x1F6DC, 0x1F6DC, prExtendedPictographic}, // E15.0 [1] (🛜) wireless {0x1F6DD, 0x1F6DF, prExtendedPictographic}, // E14.0 [3] (🛝..🛟) playground slide..ring buoy {0x1F6E0, 0x1F6E5, prExtendedPictographic}, // E0.7 [6] (🛠️..🛥️) hammer and wrench..motor boat {0x1F6E6, 0x1F6E8, prExtendedPictographic}, // E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE @@ -1757,7 +1785,7 @@ var workBreakCodePoints = [][3]int{ {0x1F6FA, 0x1F6FA, prExtendedPictographic}, // E12.0 [1] (🛺) auto rickshaw {0x1F6FB, 0x1F6FC, prExtendedPictographic}, // E13.0 [2] (🛻..🛼) pickup truck..roller skate {0x1F6FD, 0x1F6FF, prExtendedPictographic}, // E0.0 [3] (🛽..🛿) .. - {0x1F774, 0x1F77F, prExtendedPictographic}, // E0.0 [12] (🝴..🝿) .. + {0x1F774, 0x1F77F, prExtendedPictographic}, // E0.0 [12] (🝴..🝿) LOT OF FORTUNE..ORCUS {0x1F7D5, 0x1F7DF, prExtendedPictographic}, // E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE.. {0x1F7E0, 0x1F7EB, prExtendedPictographic}, // E12.0 [12] (🟠..🟫) orange circle..brown square {0x1F7EC, 0x1F7EF, prExtendedPictographic}, // E0.0 [4] (🟬..🟯) .. @@ -1816,30 +1844,37 @@ var workBreakCodePoints = [][3]int{ {0x1FA00, 0x1FA6F, prExtendedPictographic}, // E0.0 [112] (🨀..🩯) NEUTRAL CHESS KING.. {0x1FA70, 0x1FA73, prExtendedPictographic}, // E12.0 [4] (🩰..🩳) ballet shoes..shorts {0x1FA74, 0x1FA74, prExtendedPictographic}, // E13.0 [1] (🩴) thong sandal - {0x1FA75, 0x1FA77, prExtendedPictographic}, // E0.0 [3] (🩵..🩷) .. + {0x1FA75, 0x1FA77, prExtendedPictographic}, // E15.0 [3] (🩵..🩷) light blue heart..pink heart {0x1FA78, 0x1FA7A, prExtendedPictographic}, // E12.0 [3] (🩸..🩺) drop of blood..stethoscope {0x1FA7B, 0x1FA7C, prExtendedPictographic}, // E14.0 [2] (🩻..🩼) x-ray..crutch {0x1FA7D, 0x1FA7F, prExtendedPictographic}, // E0.0 [3] (🩽..🩿) .. {0x1FA80, 0x1FA82, prExtendedPictographic}, // E12.0 [3] (🪀..🪂) yo-yo..parachute {0x1FA83, 0x1FA86, prExtendedPictographic}, // E13.0 [4] (🪃..🪆) boomerang..nesting dolls - {0x1FA87, 0x1FA8F, prExtendedPictographic}, // E0.0 [9] (🪇..🪏) .. + {0x1FA87, 0x1FA88, prExtendedPictographic}, // E15.0 [2] (🪇..🪈) maracas..flute + {0x1FA89, 0x1FA8F, prExtendedPictographic}, // E0.0 [7] (🪉..🪏) .. {0x1FA90, 0x1FA95, prExtendedPictographic}, // E12.0 [6] (🪐..🪕) ringed planet..banjo {0x1FA96, 0x1FAA8, prExtendedPictographic}, // E13.0 [19] (🪖..🪨) military helmet..rock {0x1FAA9, 0x1FAAC, prExtendedPictographic}, // E14.0 [4] (🪩..🪬) mirror ball..hamsa - {0x1FAAD, 0x1FAAF, prExtendedPictographic}, // E0.0 [3] (🪭..🪯) .. + {0x1FAAD, 0x1FAAF, prExtendedPictographic}, // E15.0 [3] (🪭..🪯) folding hand fan..khanda {0x1FAB0, 0x1FAB6, prExtendedPictographic}, // E13.0 [7] (🪰..🪶) fly..feather {0x1FAB7, 0x1FABA, prExtendedPictographic}, // E14.0 [4] (🪷..🪺) lotus..nest with eggs - {0x1FABB, 0x1FABF, prExtendedPictographic}, // E0.0 [5] (🪻..🪿) .. + {0x1FABB, 0x1FABD, prExtendedPictographic}, // E15.0 [3] (🪻..🪽) hyacinth..wing + {0x1FABE, 0x1FABE, prExtendedPictographic}, // E0.0 [1] (🪾) + {0x1FABF, 0x1FABF, prExtendedPictographic}, // E15.0 [1] (🪿) goose {0x1FAC0, 0x1FAC2, prExtendedPictographic}, // E13.0 [3] (🫀..🫂) anatomical heart..people hugging {0x1FAC3, 0x1FAC5, prExtendedPictographic}, // E14.0 [3] (🫃..🫅) pregnant man..person with crown - {0x1FAC6, 0x1FACF, prExtendedPictographic}, // E0.0 [10] (🫆..🫏) .. + {0x1FAC6, 0x1FACD, prExtendedPictographic}, // E0.0 [8] (🫆..🫍) .. + {0x1FACE, 0x1FACF, prExtendedPictographic}, // E15.0 [2] (🫎..🫏) moose..donkey {0x1FAD0, 0x1FAD6, prExtendedPictographic}, // E13.0 [7] (🫐..🫖) blueberries..teapot {0x1FAD7, 0x1FAD9, prExtendedPictographic}, // E14.0 [3] (🫗..🫙) pouring liquid..jar - {0x1FADA, 0x1FADF, prExtendedPictographic}, // E0.0 [6] (🫚..🫟) .. + {0x1FADA, 0x1FADB, prExtendedPictographic}, // E15.0 [2] (🫚..🫛) ginger root..pea pod + {0x1FADC, 0x1FADF, prExtendedPictographic}, // E0.0 [4] (🫜..🫟) .. {0x1FAE0, 0x1FAE7, prExtendedPictographic}, // E14.0 [8] (🫠..🫧) melting face..bubbles - {0x1FAE8, 0x1FAEF, prExtendedPictographic}, // E0.0 [8] (🫨..🫯) .. + {0x1FAE8, 0x1FAE8, prExtendedPictographic}, // E15.0 [1] (🫨) shaking face + {0x1FAE9, 0x1FAEF, prExtendedPictographic}, // E0.0 [7] (🫩..🫯) .. {0x1FAF0, 0x1FAF6, prExtendedPictographic}, // E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands - {0x1FAF7, 0x1FAFF, prExtendedPictographic}, // E0.0 [9] (🫷..🫿) .. + {0x1FAF7, 0x1FAF8, prExtendedPictographic}, // E15.0 [2] (🫷..🫸) leftwards pushing hand..rightwards pushing hand + {0x1FAF9, 0x1FAFF, prExtendedPictographic}, // E0.0 [7] (🫹..🫿) .. {0x1FBF0, 0x1FBF9, prNumeric}, // Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE {0x1FC00, 0x1FFFD, prExtendedPictographic}, // E0.0[1022] (🰀..🿽) .. {0xE0001, 0xE0001, prFormat}, // Cf LANGUAGE TAG diff --git a/vendor/github.com/rivo/uniseg/wordrules.go b/vendor/github.com/rivo/uniseg/wordrules.go index 325407e..57a8c68 100644 --- a/vendor/github.com/rivo/uniseg/wordrules.go +++ b/vendor/github.com/rivo/uniseg/wordrules.go @@ -22,82 +22,121 @@ const ( wbZWJBit = 16 // This bit is set for any states followed by at least one zero-width joiner (see WB4 and WB3c). ) -// The word break parser's breaking instructions. -const ( - wbDontBreak = iota - wbBreak -) - -// The word break parser's state transitions. It's anologous to grTransitions, -// see comments there for details. Unicode version 14.0.0. -var wbTransitions = map[[2]int][3]int{ +// wbTransitions implements the word break parser's state transitions. It's +// anologous to [grTransitions], see comments there for details. +// +// Unicode version 15.0.0. +func wbTransitions(state, prop int) (newState int, wordBreak bool, rule int) { + switch uint64(state) | uint64(prop)<<32 { // WB3b. - {wbAny, prNewline}: {wbNewline, wbBreak, 32}, - {wbAny, prCR}: {wbCR, wbBreak, 32}, - {wbAny, prLF}: {wbLF, wbBreak, 32}, + case wbAny | prNewline<<32: + return wbNewline, true, 32 + case wbAny | prCR<<32: + return wbCR, true, 32 + case wbAny | prLF<<32: + return wbLF, true, 32 // WB3a. - {wbNewline, prAny}: {wbAny, wbBreak, 31}, - {wbCR, prAny}: {wbAny, wbBreak, 31}, - {wbLF, prAny}: {wbAny, wbBreak, 31}, + case wbNewline | prAny<<32: + return wbAny, true, 31 + case wbCR | prAny<<32: + return wbAny, true, 31 + case wbLF | prAny<<32: + return wbAny, true, 31 // WB3. - {wbCR, prLF}: {wbLF, wbDontBreak, 30}, + case wbCR | prLF<<32: + return wbLF, false, 30 // WB3d. - {wbAny, prWSegSpace}: {wbWSegSpace, wbBreak, 9990}, - {wbWSegSpace, prWSegSpace}: {wbWSegSpace, wbDontBreak, 34}, + case wbAny | prWSegSpace<<32: + return wbWSegSpace, true, 9990 + case wbWSegSpace | prWSegSpace<<32: + return wbWSegSpace, false, 34 // WB5. - {wbAny, prALetter}: {wbALetter, wbBreak, 9990}, - {wbAny, prHebrewLetter}: {wbHebrewLetter, wbBreak, 9990}, - {wbALetter, prALetter}: {wbALetter, wbDontBreak, 50}, - {wbALetter, prHebrewLetter}: {wbHebrewLetter, wbDontBreak, 50}, - {wbHebrewLetter, prALetter}: {wbALetter, wbDontBreak, 50}, - {wbHebrewLetter, prHebrewLetter}: {wbHebrewLetter, wbDontBreak, 50}, + case wbAny | prALetter<<32: + return wbALetter, true, 9990 + case wbAny | prHebrewLetter<<32: + return wbHebrewLetter, true, 9990 + case wbALetter | prALetter<<32: + return wbALetter, false, 50 + case wbALetter | prHebrewLetter<<32: + return wbHebrewLetter, false, 50 + case wbHebrewLetter | prALetter<<32: + return wbALetter, false, 50 + case wbHebrewLetter | prHebrewLetter<<32: + return wbHebrewLetter, false, 50 // WB7. Transitions to wbWB7 handled by transitionWordBreakState(). - {wbWB7, prALetter}: {wbALetter, wbDontBreak, 70}, - {wbWB7, prHebrewLetter}: {wbHebrewLetter, wbDontBreak, 70}, + case wbWB7 | prALetter<<32: + return wbALetter, false, 70 + case wbWB7 | prHebrewLetter<<32: + return wbHebrewLetter, false, 70 // WB7a. - {wbHebrewLetter, prSingleQuote}: {wbAny, wbDontBreak, 71}, + case wbHebrewLetter | prSingleQuote<<32: + return wbAny, false, 71 // WB7c. Transitions to wbWB7c handled by transitionWordBreakState(). - {wbWB7c, prHebrewLetter}: {wbHebrewLetter, wbDontBreak, 73}, + case wbWB7c | prHebrewLetter<<32: + return wbHebrewLetter, false, 73 // WB8. - {wbAny, prNumeric}: {wbNumeric, wbBreak, 9990}, - {wbNumeric, prNumeric}: {wbNumeric, wbDontBreak, 80}, + case wbAny | prNumeric<<32: + return wbNumeric, true, 9990 + case wbNumeric | prNumeric<<32: + return wbNumeric, false, 80 // WB9. - {wbALetter, prNumeric}: {wbNumeric, wbDontBreak, 90}, - {wbHebrewLetter, prNumeric}: {wbNumeric, wbDontBreak, 90}, + case wbALetter | prNumeric<<32: + return wbNumeric, false, 90 + case wbHebrewLetter | prNumeric<<32: + return wbNumeric, false, 90 // WB10. - {wbNumeric, prALetter}: {wbALetter, wbDontBreak, 100}, - {wbNumeric, prHebrewLetter}: {wbHebrewLetter, wbDontBreak, 100}, + case wbNumeric | prALetter<<32: + return wbALetter, false, 100 + case wbNumeric | prHebrewLetter<<32: + return wbHebrewLetter, false, 100 // WB11. Transitions to wbWB11 handled by transitionWordBreakState(). - {wbWB11, prNumeric}: {wbNumeric, wbDontBreak, 110}, + case wbWB11 | prNumeric<<32: + return wbNumeric, false, 110 // WB13. - {wbAny, prKatakana}: {wbKatakana, wbBreak, 9990}, - {wbKatakana, prKatakana}: {wbKatakana, wbDontBreak, 130}, + case wbAny | prKatakana<<32: + return wbKatakana, true, 9990 + case wbKatakana | prKatakana<<32: + return wbKatakana, false, 130 // WB13a. - {wbAny, prExtendNumLet}: {wbExtendNumLet, wbBreak, 9990}, - {wbALetter, prExtendNumLet}: {wbExtendNumLet, wbDontBreak, 131}, - {wbHebrewLetter, prExtendNumLet}: {wbExtendNumLet, wbDontBreak, 131}, - {wbNumeric, prExtendNumLet}: {wbExtendNumLet, wbDontBreak, 131}, - {wbKatakana, prExtendNumLet}: {wbExtendNumLet, wbDontBreak, 131}, - {wbExtendNumLet, prExtendNumLet}: {wbExtendNumLet, wbDontBreak, 131}, + case wbAny | prExtendNumLet<<32: + return wbExtendNumLet, true, 9990 + case wbALetter | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbHebrewLetter | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbNumeric | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbKatakana | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 + case wbExtendNumLet | prExtendNumLet<<32: + return wbExtendNumLet, false, 131 // WB13b. - {wbExtendNumLet, prALetter}: {wbALetter, wbDontBreak, 132}, - {wbExtendNumLet, prHebrewLetter}: {wbHebrewLetter, wbDontBreak, 132}, - {wbExtendNumLet, prNumeric}: {wbNumeric, wbDontBreak, 132}, - {wbExtendNumLet, prKatakana}: {prKatakana, wbDontBreak, 132}, + case wbExtendNumLet | prALetter<<32: + return wbALetter, false, 132 + case wbExtendNumLet | prHebrewLetter<<32: + return wbHebrewLetter, false, 132 + case wbExtendNumLet | prNumeric<<32: + return wbNumeric, false, 132 + case wbExtendNumLet | prKatakana<<32: + return wbKatakana, false, 132 + + default: + return -1, false, -1 + } } // transitionWordBreakState determines the new state of the word break parser @@ -141,30 +180,27 @@ func transitionWordBreakState(state int, r rune, b []byte, str string) (newState // Find the applicable transition in the table. var rule int - transition, ok := wbTransitions[[2]int{state, nextProperty}] - if ok { - // We have a specific transition. We'll use it. - newState, wordBreak, rule = transition[0], transition[1] == wbBreak, transition[2] - } else { + newState, wordBreak, rule = wbTransitions(state, nextProperty) + if newState < 0 { // No specific transition found. Try the less specific ones. - transAnyProp, okAnyProp := wbTransitions[[2]int{state, prAny}] - transAnyState, okAnyState := wbTransitions[[2]int{wbAny, nextProperty}] - if okAnyProp && okAnyState { + anyPropState, anyPropWordBreak, anyPropRule := wbTransitions(state, prAny) + anyStateState, anyStateWordBreak, anyStateRule := wbTransitions(wbAny, nextProperty) + if anyPropState >= 0 && anyStateState >= 0 { // Both apply. We'll use a mix (see comments for grTransitions). - newState, wordBreak, rule = transAnyState[0], transAnyState[1] == wbBreak, transAnyState[2] - if transAnyProp[2] < transAnyState[2] { - wordBreak, rule = transAnyProp[1] == wbBreak, transAnyProp[2] + newState, wordBreak, rule = anyStateState, anyStateWordBreak, anyStateRule + if anyPropRule < anyStateRule { + wordBreak, rule = anyPropWordBreak, anyPropRule } - } else if okAnyProp { + } else if anyPropState >= 0 { // We only have a specific state. - newState, wordBreak, rule = transAnyProp[0], transAnyProp[1] == wbBreak, transAnyProp[2] + newState, wordBreak, rule = anyPropState, anyPropWordBreak, anyPropRule // This branch will probably never be reached because okAnyState will // always be true given the current transition map. But we keep it here // for future modifications to the transition map where this may not be // true anymore. - } else if okAnyState { + } else if anyStateState >= 0 { // We only have a specific property. - newState, wordBreak, rule = transAnyState[0], transAnyState[1] == wbBreak, transAnyState[2] + newState, wordBreak, rule = anyStateState, anyStateWordBreak, anyStateRule } else { // No known transition. WB999: Any ÷ Any. newState, wordBreak, rule = wbAny, true, 9990 diff --git a/vendor/github.com/robotn/gohook/.gitignore b/vendor/github.com/robotn/gohook/.gitignore new file mode 100644 index 0000000..6d4051e --- /dev/null +++ b/vendor/github.com/robotn/gohook/.gitignore @@ -0,0 +1,30 @@ +# Object files +.DS_Store +.vscode +.idea + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +*.idea \ No newline at end of file diff --git a/vendor/github.com/robotn/gohook/LICENSE b/vendor/github.com/robotn/gohook/LICENSE new file mode 100644 index 0000000..cc87081 --- /dev/null +++ b/vendor/github.com/robotn/gohook/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 go-ego Project Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/robotn/gohook/README.md b/vendor/github.com/robotn/gohook/README.md new file mode 100644 index 0000000..350b281 --- /dev/null +++ b/vendor/github.com/robotn/gohook/README.md @@ -0,0 +1,66 @@ +# gohook + +[![Build Status](https://github.com/robotn/gohook/workflows/Go/badge.svg)](https://github.com/robotn/gohook/commits/master) +[![CircleCI Status](https://circleci.com/gh/robotn/gohook.svg?style=shield)](https://circleci.com/gh/robotn/gohook) +![Appveyor](https://ci.appveyor.com/api/projects/status/github/robotn/gohook?branch=master&svg=true) +[![Go Report Card](https://goreportcard.com/badge/github.com/robotn/gohook)](https://goreportcard.com/report/github.com/robotn/gohook) +[![GoDoc](https://godoc.org/github.com/robotn/gohook?status.svg)](https://godoc.org/github.com/robotn/gohook) + + +## Requirements (Linux): + +[Robotgo-requirements-event](https://github.com/go-vgo/robotgo#requirements) + +## Install: + +With Go module support (Go 1.11+), just import: + +```go +import "github.com/robotn/gohook" +``` + +## Examples: + +```Go +package main + +import ( + "fmt" + + hook "github.com/robotn/gohook" +) + +func main() { + add() + + low() +} + +func add() { + fmt.Println("--- Please press ctrl + shift + q to stop hook ---") + hook.Register(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) { + fmt.Println("ctrl-shift-q") + hook.End() + }) + + fmt.Println("--- Please press w---") + hook.Register(hook.KeyDown, []string{"w"}, func(e hook.Event) { + fmt.Println("w") + }) + + s := hook.Start() + <-hook.Process(s) +} + +func low() { + evChan := hook.Start() + defer hook.End() + + for ev := range evChan { + fmt.Println("hook: ", ev) + } +} + +``` + +Based on [libuiohook](https://github.com/kwhat/libuiohook). \ No newline at end of file diff --git a/vendor/github.com/robotn/gohook/appveyor.yml b/vendor/github.com/robotn/gohook/appveyor.yml new file mode 100644 index 0000000..78b79f6 --- /dev/null +++ b/vendor/github.com/robotn/gohook/appveyor.yml @@ -0,0 +1,80 @@ +# version format +version: "{build}" + +# Operating system (build VM template) +# os: Windows Server 2012 R2 +os: Visual Studio 2017 + +# Platform. +# platform: +# - x64 +# - x86 + +clone_folder: c:\gopath\src\github.com\robotn\gohook + +# Environment variables +environment: + global: + GOPATH: C:\gopath + CC: gcc.exe + matrix: + - GOARCH: amd64 + # GOVERSION: 1.9.3 + GETH_ARCH: amd64 + MSYS2_ARCH: x86_64 + MSYS2_BITS: 64 + MSYSTEM: MINGW64 + PATH: C:\msys64\mingw64\bin\;C:\Program Files (x86)\NSIS\;%PATH% + - GOARCH: 386 + # GOVERSION: 1.9.3 + GETH_ARCH: 386 + MSYS2_ARCH: i686 + MSYS2_BITS: 32 + MSYSTEM: MINGW32 + PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% + # - COMPILER: MINGW_W64 + # ARCHITECTURE: x64 + GOVERSION: 1.21.0 + # GOPATH: c:\gopath + +# scripts that run after cloning repository +# install: +# - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% +# - go version +# - go env +# - gcc --version +# - python --version + +install: + - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% + - git submodule update --init + - rmdir C:\go /s /q + - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-%GETH_ARCH%.zip + - 7z x go%GOVERSION%.windows-%GETH_ARCH%.zip -y -oC:\ > NUL + - go version + - go env + - gcc --version + +# To run your custom scripts instead of automatic MSBuild +build_script: + # We need to disable firewall - https://github.com/appveyor/ci/issues/1579#issuecomment-309830648 + - ps: Disable-NetFirewallRule -DisplayName 'File and Printer Sharing (SMB-Out)' + - cd c:\gopath\src\github.com\robotn\gohook + - git branch + - go get -t ./... + +# To run your custom scripts instead of automatic tests +test_script: + # Unit tests + - ps: Add-AppveyorTest "Unit Tests" -Outcome Running + - go test -v github.com/robotn/gohook... + - ps: Update-AppveyorTest "Unit Tests" -Outcome Passed + +# notifications: +# - provider: Email +# to: +# - .io +# on_build_failure: true +# on_build_status_changed: true +# to disable deployment +deploy: off diff --git a/vendor/github.com/robotn/gohook/circle.yml b/vendor/github.com/robotn/gohook/circle.yml new file mode 100644 index 0000000..2e965ff --- /dev/null +++ b/vendor/github.com/robotn/gohook/circle.yml @@ -0,0 +1,21 @@ +version: 2 + +jobs: + build: + docker: + # using custom image, see .circleci/images/primary/Dockerfile + - image: govgo/robotgoci:1.10.3 + working_directory: /gopath/src/github.com/robotn/gohook + steps: + - checkout + # specify any bash command here prefixed with `run: ` + - run: apt-get update + - run: apt-get -y install xvfb + # override: + # './...' is a relative pattern which means all subdirectories + # - run: go get -u golang.org/x/sys/unix + - run: go get -v -t -d ./... + - run: xvfb-run go test -v ./... + # codecov.io + # - run: go test -v -covermode=count -coverprofile=coverage.out + # - run: bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/robotn/gohook/event.go b/vendor/github.com/robotn/gohook/event.go new file mode 100644 index 0000000..3c8f01c --- /dev/null +++ b/vendor/github.com/robotn/gohook/event.go @@ -0,0 +1,150 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package hook + +import "strconv" + +/* + ___________ ____ _______ .__ __. .___________. +| ____\ \ / / | ____|| \ | | | | +| |__ \ \/ / | |__ | \| | `---| |----` +| __| \ / | __| | . ` | | | +| |____ \ / | |____ | |\ | | | +|_______| \__/ |_______||__| \__| |__| +*/ + +// AddEvent add event listener, +// +// parameters for the string type, +// the keyboard corresponding key parameters, +// +// mouse arguments: mleft, center, mright, wheelDown, wheelUp, +// wheelLeft, wheelRight. +// +// Use "hook.AddEvents()" or "gohook" add asynchronous event listener +func AddEvent(key string) bool { + var ( + // cs *C.char + mArr = []string{"mleft", "center", "mright", "wheelDown", + "wheelUp", "wheelLeft", "wheelRight"} + mouseBool bool + ) + + for i := 0; i < len(mArr); i++ { + if key == mArr[i] { + mouseBool = true + } + } + + if len(key) > 1 && !mouseBool { + key = strconv.Itoa(int(Keycode[key])) + } + + geve := addEvent(key) + // defer C.free(unsafe.Pointer(cs)) + return geve == 0 +} + +// AddEvents add global event hook +// +// hook.AddEvents("q") +// hook.AddEvents("q", "ctrl") +// hook.AddEvents("q", "ctrl", "shift") +func AddEvents(key string, arr ...string) bool { + s := Start() + // defer End() + + ct := false + k := 0 + for { + e := <-s + + l := len(arr) + if l > 0 { + for i := 0; i < l; i++ { + ukey := Keycode[arr[i]] + + if e.Kind == KeyHold && e.Keycode == ukey { + k++ + } + + if k == l { + ct = true + } + + if e.Kind == KeyUp && e.Keycode == ukey { + if k > 0 { + k-- + } + // time.Sleep(10 * time.Microsecond) + ct = false + } + } + } else { + ct = true + } + + if ct && e.Kind == KeyUp && e.Keycode == Keycode[key] { + End() + // k = 0 + break + } + } + + return true +} + +// AddMouse add mouse event hook +// +// mouse arguments: left, center, right, wheelDown, wheelUp, +// wheelLeft, wheelRight. +// +// hook.AddMouse("left") +// hook.AddMouse("left", 100, 100) +func AddMouse(btn string, x ...int16) bool { + s := Start() + ukey := MouseMap[btn] + + ct := false + for { + e := <-s + + if len(x) > 1 { + if e.Kind == MouseMove && e.X == x[0] && e.Y == x[1] { + ct = true + } + } else { + ct = true + } + + if ct && e.Kind == MouseDown && e.Button == ukey { + End() + break + } + } + + return true +} + +// AddMousePos add listen mouse event pos hook +func AddMousePos(x, y int16) bool { + s := Start() + + for { + e := <-s + if e.Kind == MouseMove && e.X == x && e.Y == y { + End() + break + } + } + + return true +} diff --git a/vendor/github.com/robotn/gohook/extern.go b/vendor/github.com/robotn/gohook/extern.go new file mode 100644 index 0000000..0e12a83 --- /dev/null +++ b/vendor/github.com/robotn/gohook/extern.go @@ -0,0 +1,40 @@ +package hook + +/* + +// #include "event/hook_async.h" +*/ +import "C" + +import ( + "log" + "time" + + "encoding/json" +) + +//export go_send +func go_send(s *C.char) { + str := []byte(C.GoString(s)) + out := Event{} + + err := json.Unmarshal(str, &out) + if err != nil { + log.Fatal("json.Unmarshal error is: ", err) + } + + if out.Keychar != CharUndefined { + lck.Lock() + raw2key[out.Rawcode] = string([]rune{out.Keychar}) + lck.Unlock() + } + + // todo bury this deep into the C lib so that the time is correct + out.When = time.Now() // at least it's consistent + if err != nil { + log.Fatal("json.Unmarshal error is: ", err) + } + + // todo: maybe make non-bloking + ev <- out +} diff --git a/vendor/github.com/robotn/gohook/hook.go b/vendor/github.com/robotn/gohook/hook.go new file mode 100644 index 0000000..123c208 --- /dev/null +++ b/vendor/github.com/robotn/gohook/hook.go @@ -0,0 +1,277 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package hook + +/* +#cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations +#cgo darwin LDFLAGS: -framework Cocoa + +#cgo linux CFLAGS:-I/usr/src +#cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst +#cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11 +//#cgo windows LDFLAGS: -lgdi32 -luser32 + +#include "event/goEvent.h" +*/ +import "C" + +import ( + "fmt" + "sync" + "time" + "unsafe" +) + +const ( + // Version get the gohook version + Version = "v0.40.0.123, Sierra Nevada!" + + // HookEnabled honk enable status + HookEnabled = 1 // iota + HookDisabled = 2 + + KeyDown = 3 + KeyHold = 4 + KeyUp = 5 + + MouseUp = 6 + MouseHold = 7 + MouseDown = 8 + MouseMove = 9 + MouseDrag = 10 + MouseWheel = 11 + + FakeEvent = 12 + + // Keychar could be v + CharUndefined = 0xFFFF + WheelUp = -1 + WheelDown = 1 +) + +// Event Holds a system event +// +// If it's a Keyboard event the relevant fields are: +// Mask, Keycode, Rawcode, and Keychar, +// Keychar is probably what you want. +// +// If it's a Mouse event the relevant fields are: +// Button, Clicks, X, Y, Amount, Rotation and Direction +type Event struct { + Kind uint8 `json:"id"` + When time.Time + Mask uint16 `json:"mask"` + Reserved uint16 `json:"reserved"` + + Keycode uint16 `json:"keycode"` + Rawcode uint16 `json:"rawcode"` + Keychar rune `json:"keychar"` + + Button uint16 `json:"button"` + Clicks uint16 `json:"clicks"` + + X int16 `json:"x"` + Y int16 `json:"y"` + + Amount uint16 `json:"amount"` + Rotation int32 `json:"rotation"` + Direction uint8 `json:"direction"` +} + +var ( + ev = make(chan Event, 1024) + asyncon = false + + lck sync.RWMutex + + pressed = make(map[uint16]bool, 256) + used = []int{} + + keys = map[int][]uint16{} + cbs = map[int]func(Event){} + events = map[uint8][]int{} +) + +func allPressed(pressed map[uint16]bool, keys ...uint16) bool { + for _, i := range keys { + // fmt.Println(i) + if !pressed[i] { + return false + } + } + + return true +} + +// Register register gohook event +func Register(when uint8, cmds []string, cb func(Event)) { + key := len(used) + used = append(used, key) + tmp := []uint16{} + + for _, v := range cmds { + tmp = append(tmp, Keycode[v]) + } + + keys[key] = tmp + cbs[key] = cb + events[when] = append(events[when], key) + // return +} + +// Process return go hook process +func Process(evChan <-chan Event) (out chan bool) { + out = make(chan bool) + go func() { + for ev := range evChan { + if ev.Kind == KeyDown || ev.Kind == KeyHold { + pressed[ev.Keycode] = true + } else if ev.Kind == KeyUp { + pressed[ev.Keycode] = false + } + + for _, v := range events[ev.Kind] { + if !asyncon { + break + } + + if allPressed(pressed, keys[v]...) { + cbs[v](ev) + } + } + } + + // fmt.Println("exiting after end (process)") + out <- true + }() + + return +} + +// String return formatted hook kind string +func (e Event) String() string { + switch e.Kind { + case HookEnabled: + return fmt.Sprintf("%v - Event: {Kind: HookEnabled}", e.When) + case HookDisabled: + return fmt.Sprintf("%v - Event: {Kind: HookDisabled}", e.When) + case KeyUp: + return fmt.Sprintf("%v - Event: {Kind: KeyUp, Rawcode: %v, Keychar: %v}", + e.When, e.Rawcode, e.Keychar) + case KeyHold: + return fmt.Sprintf( + "%v - Event: {Kind: KeyHold, Rawcode: %v, Keychar: %v}", + e.When, e.Rawcode, e.Keychar) + case KeyDown: + return fmt.Sprintf( + "%v - Event: {Kind: KeyDown, Rawcode: %v, Keychar: %v}", + e.When, e.Rawcode, e.Keychar) + case MouseUp: + return fmt.Sprintf( + "%v - Event: {Kind: MouseUp, Button: %v, X: %v, Y: %v, Clicks: %v}", + e.When, e.Button, e.X, e.Y, e.Clicks) + case MouseHold: + return fmt.Sprintf( + "%v - Event: {Kind: MouseHold, Button: %v, X: %v, Y: %v, Clicks: %v}", + e.When, e.Button, e.X, e.Y, e.Clicks) + case MouseDown: + return fmt.Sprintf( + "%v - Event: {Kind: MouseDown, Button: %v, X: %v, Y: %v, Clicks: %v}", + e.When, e.Button, e.X, e.Y, e.Clicks) + case MouseMove: + return fmt.Sprintf( + "%v - Event: {Kind: MouseMove, Button: %v, X: %v, Y: %v, Clicks: %v}", + e.When, e.Button, e.X, e.Y, e.Clicks) + case MouseDrag: + return fmt.Sprintf( + "%v - Event: {Kind: MouseDrag, Button: %v, X: %v, Y: %v, Clicks: %v}", + e.When, e.Button, e.X, e.Y, e.Clicks) + case MouseWheel: + return fmt.Sprintf( + "%v - Event: {Kind: MouseWheel, Amount: %v, Rotation: %v, Direction: %v}", + e.When, e.Amount, e.Rotation, e.Direction) + case FakeEvent: + return fmt.Sprintf("%v - Event: {Kind: FakeEvent}", e.When) + } + + return "Unknown event, contact the mantainers." +} + +// RawcodetoKeychar rawcode to keychar +func RawcodetoKeychar(r uint16) string { + lck.RLock() + defer lck.RUnlock() + + return raw2key[r] +} + +// KeychartoRawcode key char to rawcode +func KeychartoRawcode(kc string) uint16 { + return keytoraw[kc] +} + +// Start adds global event hook to OS +// returns event channel +func Start() chan Event { + ev = make(chan Event, 1024) + go C.start_ev() + + asyncon = true + go func() { + for { + if !asyncon { + return + } + + C.pollEv() + time.Sleep(time.Millisecond * 50) + //todo: find smallest time that does not destroy the cpu utilization + } + }() + + return ev +} + +// End removes global event hook +func End() { + asyncon = false + C.endPoll() + C.stop_event() + time.Sleep(time.Millisecond * 10) + + for len(ev) != 0 { + <-ev + } + close(ev) + + pressed = make(map[uint16]bool, 256) + used = []int{} + + keys = map[int][]uint16{} + cbs = map[int]func(Event){} + events = map[uint8][]int{} +} + +// AddEvent add the block event listener +func addEvent(key string) int { + cs := C.CString(key) + defer C.free(unsafe.Pointer(cs)) + + eve := C.add_event(cs) + geve := int(eve) + + return geve +} + +// StopEvent stop the block event listener +func StopEvent() { + C.stop_event() +} diff --git a/vendor/github.com/robotn/gohook/keycode.go b/vendor/github.com/robotn/gohook/keycode.go new file mode 100644 index 0000000..4224ad0 --- /dev/null +++ b/vendor/github.com/robotn/gohook/keycode.go @@ -0,0 +1,22 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package hook + +import "github.com/vcaesar/keycode" + +// MouseMap defines the robotgo hook mouse's code map +var MouseMap = keycode.MouseMap + +// Keycode defines the robotgo hook key's code map +var Keycode = keycode.Keycode + +// Special defines the special key map +var Special = keycode.Special diff --git a/vendor/github.com/robotn/gohook/tables.go b/vendor/github.com/robotn/gohook/tables.go new file mode 100644 index 0000000..0778dcd --- /dev/null +++ b/vendor/github.com/robotn/gohook/tables.go @@ -0,0 +1,354 @@ +package hook + +var ( + raw2key = map[uint16]string{ // https://github.com/wesbos/keycodes + 0: "error", + 3: "break", + 8: "backspace", + 9: "tab", + 12: "clear", + 13: "enter", + 16: "shift", + 17: "ctrl", + 18: "alt", + 19: "pause/break", + 20: "caps lock", + 21: "hangul", + 25: "hanja", + 27: "escape", + 28: "conversion", + 29: "non-conversion", + 32: "spacebar", + 33: "page up", + 34: "page down", + 35: "end", + 36: "home", + 37: "left arrow", + 38: "up arrow", + 39: "right arrow", + 40: "down arrow", + 41: "select", + 42: "print", + 43: "execute", + 44: "Print Screen", + 45: "insert", + 46: "delete", + 47: "help", + 48: "0", + 49: "1", + 50: "2", + 51: "3", + 52: "4", + 53: "5", + 54: "6", + 55: "7", + 56: "8", + 57: "9", + 58: ":", + 59: ";", + 60: "<", + 61: "=", + 63: "ß", + 64: "@", + 65: "a", + 66: "b", + 67: "c", + 68: "d", + 69: "e", + 70: "f", + 71: "g", + 72: "h", + 73: "i", + 74: "j", + 75: "k", + 76: "l", + 77: "m", + 78: "n", + 79: "o", + 80: "p", + 81: "q", + 82: "r", + 83: "s", + 84: "t", + 85: "u", + 86: "v", + 87: "w", + 88: "x", + 89: "y", + 90: "z", + 91: "l-super", + 92: "r-super", + 93: "apps", + 95: "sleep", + 96: "numpad 0", + 97: "numpad 1", + 98: "numpad 2", + 99: "numpad 3", + 100: "numpad 4", + 101: "numpad 5", + 102: "numpad 6", + 103: "numpad 7", + 104: "numpad 8", + 105: "numpad 9", + 106: "multiply", + 107: "add", + 108: "numpad period", + 109: "subtract", + 110: "decimal point", + 111: "divide", + 112: "f1", + 113: "f2", + 114: "f3", + 115: "f4", + 116: "f5", + 117: "f6", + 118: "f7", + 119: "f8", + 120: "f9", + 121: "f10", + 122: "f11", + 123: "f12", + 124: "f13", + 125: "f14", + 126: "f15", + 127: "f16", + 128: "f17", + 129: "f18", + 130: "f19", + 131: "f20", + 132: "f21", + 133: "f22", + 134: "f23", + 135: "f24", + 144: "num lock", + 145: "scroll lock", + 160: "^", + 161: "!", + 162: "؛", + 163: "#", + 164: "$", + 165: "ù", + 166: "page backward", + 167: "page forward", + 168: "refresh", + 169: "closing paren (AZERTY)", + 170: "*", + 171: "~ + * key", + 172: "home key", + 173: "minus (firefox), mute/unmute", + 174: "decrease volume level", + 175: "increase volume level", + 176: "next", + 177: "previous", + 178: "stop", + 179: "play/pause", + 180: "e-mail", + 181: "mute/unmute (firefox)", + 182: "decrease volume level (firefox)", + 183: "increase volume level (firefox)", + 186: "semi-colon / ñ", + 187: "equal sign", + 188: "comma", + 189: "dash", + 190: "period", + 191: "forward slash / ç", + 192: "grave accent / ñ / æ / ö", + 193: "?, / or °", + 194: "numpad period (chrome)", + 219: "open bracket", + 220: "back slash", + 221: "close bracket / å", + 222: "single quote / ø / ä", + 223: "`", + 224: "left or right ⌘ key (firefox)", + 225: "altgr", + 226: "< /git >, left back slash", + 230: "GNOME Compose Key", + 231: "ç", + 233: "XF86Forward", + 234: "XF86Back", + 235: "non-conversion", + 240: "alphanumeric", + 242: "hiragana/katakana", + 243: "half-width/full-width", + 244: "kanji", + 251: "unlock trackpad (Chrome/Edge)", + 255: "toggle touchpad", + 65517: "hyper", + } + + keytoraw = map[string]uint16{ + "error": 0, + "break": 3, + "backspace": 8, + "tab": 9, + "clear": 12, + "enter": 13, + "shift": 16, + "ctrl": 17, + "alt": 18, + "pause/break": 19, + "caps lock": 20, + "hangul": 21, + "hanja": 25, + "escape": 27, + "conversion": 28, + "non-conversion": 29, + "spacebar": 32, + "page up": 33, + "page down": 34, + "end": 35, + "home": 36, + "left arrow": 37, + "up arrow": 38, + "right arrow": 39, + "down arrow": 40, + "select": 41, + "print": 42, + "execute": 43, + "Print Screen": 44, + "insert": 45, + "delete": 46, + "help": 47, + "0": 48, + "1": 49, + "2": 50, + "3": 51, + "4": 52, + "5": 53, + "6": 54, + "7": 55, + "8": 56, + "9": 57, + ":": 58, + ";": 59, + "<": 60, + "=": 61, + "ß": 63, + "@": 64, + "a": 65, + "b": 66, + "c": 67, + "d": 68, + "e": 69, + "f": 70, + "g": 71, + "h": 72, + "i": 73, + "j": 74, + "k": 75, + "l": 76, + "m": 77, + "n": 78, + "o": 79, + "p": 80, + "q": 81, + "r": 82, + "s": 83, + "t": 84, + "u": 85, + "v": 86, + "w": 87, + "x": 88, + "y": 89, + "z": 90, + "l-super": 91, + "r-super": 92, + "apps": 93, + "sleep": 95, + "numpad 0": 96, + "numpad 1": 97, + "numpad 2": 98, + "numpad 3": 99, + "numpad 4": 100, + "numpad 5": 101, + "numpad 6": 102, + "numpad 7": 103, + "numpad 8": 104, + "numpad 9": 105, + "multiply": 106, + "add": 107, + "numpad period": 108, + "subtract": 109, + "decimal point": 110, + "divide": 111, + "f1": 112, + "f2": 113, + "f3": 114, + "f4": 115, + "f5": 116, + "f6": 117, + "f7": 118, + "f8": 119, + "f9": 120, + "f10": 121, + "f11": 122, + "f12": 123, + "f13": 124, + "f14": 125, + "f15": 126, + "f16": 127, + "f17": 128, + "f18": 129, + "f19": 130, + "f20": 131, + "f21": 132, + "f22": 133, + "f23": 134, + "f24": 135, + "num lock": 144, + "scroll lock": 145, + "^": 160, + "!": 161, + "؛": 162, + "#": 163, + "$": 164, + "ù": 165, + "page backward": 166, + "page forward": 167, + "refresh": 168, + "closing paren (AZERTY)": 169, + "*": 170, + "~ + * key": 171, + "home key": 172, + "minus (firefox), mute/unmute": 173, + "decrease volume level": 174, + "increase volume level": 175, + "next": 176, + "previous": 177, + "stop": 178, + "play/pause": 179, + "e-mail": 180, + "mute/unmute (firefox)": 181, + "decrease volume level (firefox)": 182, + "increase volume level (firefox)": 183, + "semi-colon / ñ": 186, + "equal sign": 187, + "comma": 188, + "dash": 189, + "period": 190, + "forward slash / ç": 191, + "grave accent / ñ / æ / ö": 192, + "?, / or °": 193, + "numpad period (chrome)": 194, + "open bracket": 219, + "back slash": 220, + "close bracket / å": 221, + "single quote / ø / ä": 222, + "`": 223, + "left or right ⌘ key (firefox)": 224, + "altgr": 225, + "< /git >, left back slash": 226, + "GNOME Compose Key": 230, + "ç": 231, + "XF86Forward": 233, + "XF86Back": 234, + "alphanumeric": 240, + "hiragana/katakana": 242, + "half-width/full-width": 243, + "kanji": 244, + "unlock trackpad (Chrome/Edge)": 251, + "toggle touchpad": 255, + "hyper": 65517, + } +) diff --git a/vendor/github.com/vcaesar/keycode/.gitignore b/vendor/github.com/vcaesar/keycode/.gitignore new file mode 100644 index 0000000..2c819ed --- /dev/null +++ b/vendor/github.com/vcaesar/keycode/.gitignore @@ -0,0 +1,20 @@ +# Object files +.DS_Store +.vscode +.idea + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/containerd/console/LICENSE b/vendor/github.com/vcaesar/keycode/LICENSE similarity index 93% rename from vendor/github.com/containerd/console/LICENSE rename to vendor/github.com/vcaesar/keycode/LICENSE index 584149b..261eeb9 100644 --- a/vendor/github.com/containerd/console/LICENSE +++ b/vendor/github.com/vcaesar/keycode/LICENSE @@ -1,7 +1,6 @@ - Apache License Version 2.0, January 2004 - https://www.apache.org/licenses/ + http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -176,13 +175,24 @@ END OF TERMS AND CONDITIONS - Copyright The containerd Authors + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - https://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/vendor/github.com/vcaesar/keycode/README.md b/vendor/github.com/vcaesar/keycode/README.md new file mode 100644 index 0000000..37edc73 --- /dev/null +++ b/vendor/github.com/vcaesar/keycode/README.md @@ -0,0 +1 @@ +# keycode \ No newline at end of file diff --git a/vendor/github.com/vcaesar/keycode/circle.yml b/vendor/github.com/vcaesar/keycode/circle.yml new file mode 100644 index 0000000..0b84f64 --- /dev/null +++ b/vendor/github.com/vcaesar/keycode/circle.yml @@ -0,0 +1,15 @@ +version: 2 + +jobs: + build: + docker: + - image: golang:1.17.3 + working_directory: /gopath/src/github.com/vcaesar/keycode + steps: + - checkout + # specify any bash command here prefixed with `run: ` + - run: go get -v -t -d ./... + - run: go test -v ./... + # codecov.io + - run: go test -v -covermode=count -coverprofile=coverage.out + - run: bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/vcaesar/keycode/keycode.go b/vendor/github.com/vcaesar/keycode/keycode.go new file mode 100644 index 0000000..7193f8d --- /dev/null +++ b/vendor/github.com/vcaesar/keycode/keycode.go @@ -0,0 +1,168 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package keycode + +// UMap type map[string]uint16 +type UMap map[string]uint16 + +// MouseMap robotgo hook mouse's code map +var MouseMap = UMap{ + "left": 1, + "right": 2, + "center": 3, + "wheelDown": 4, + "wheelUp": 5, + "wheelLeft": 6, + "wheelRight": 7, +} + +// Keycode robotgo hook key's code map +var Keycode = UMap{ + "`": 41, + "1": 2, + "2": 3, + "3": 4, + "4": 5, + "5": 6, + "6": 7, + "7": 8, + "8": 9, + "9": 10, + "0": 11, + "-": 12, + "=": 13, + // + "_": 12, + "+": 13, + // + "q": 16, + "w": 17, + "e": 18, + "r": 19, + "t": 20, + "y": 21, + "u": 22, + "i": 23, + "o": 24, + "p": 25, + "[": 26, + "]": 27, + "\\": 43, + // + "{": 26, + "}": 27, + "|": 43, + // + "a": 30, + "s": 31, + "d": 32, + "f": 33, + "g": 34, + "h": 35, + "j": 36, + "k": 37, + "l": 38, + ";": 39, + "'": 40, + // + ":": 39, + `"`: 40, + // + "z": 44, + "x": 45, + "c": 46, + "v": 47, + "b": 48, + "n": 49, + "m": 50, + ",": 51, + ".": 52, + "/": 53, + // + "<": 51, + ">": 52, + "?": 53, + // + "f1": 59, + "f2": 60, + "f3": 61, + "f4": 62, + "f5": 63, + "f6": 64, + "f7": 65, + "f8": 66, + "f9": 67, + "f10": 68, + "f11": 69, + "f12": 70, + // numeric keypad + "num1": 79, + "num2": 80, + "num3": 81, + "num4": 75, + "num5": 76, + "num6": 77, + "num7": 71, + "num8": 72, + "num9": 73, + "num0": 82, + "num_minus": 74, + "num_plus": 78, + "num_asterisk": 55, + "num_slash": 3637, + "num_enter": 3612, + // more + "esc": 1, + "delete": 14, + "tab": 15, + "enter": 28, + "ctrl": 29, + "control": 29, + "shift": 42, + "rshift": 54, + "space": 57, + // + "alt": 56, + "ralt": 3640, + "cmd": 3675, + "command": 3675, + "rcmd": 3676, + // + "up": 57416, + "down": 57424, + "left": 57419, + "right": 57421, +} + +// Special is the special key map +var Special = map[string]string{ + "~": "`", + "!": "1", + "@": "2", + "#": "3", + "$": "4", + "%": "5", + "^": "6", + "&": "7", + "*": "8", + "(": "9", + ")": "0", + "_": "-", + "+": "=", + "{": "[", + "}": "]", + "|": "\\", + ":": ";", + `"`: "'", + "<": ",", + ">": ".", + "?": "/", +} diff --git a/vendor/golang.org/x/exp/shiny/LICENSE b/vendor/golang.org/x/exp/shiny/LICENSE deleted file mode 100644 index 6a66aea..0000000 --- a/vendor/golang.org/x/exp/shiny/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/buffer.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/buffer.go deleted file mode 100644 index 94b4b9a..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/buffer.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gldriver - -import "image" - -type bufferImpl struct { - // buf should always be equal to (i.e. the same ptr, len, cap as) rgba.Pix. - // It is a separate, redundant field in order to detect modifications to - // the rgba field that are invalid as per the screen.Buffer documentation. - buf []byte - rgba image.RGBA - size image.Point -} - -func (b *bufferImpl) Release() {} -func (b *bufferImpl) Size() image.Point { return b.size } -func (b *bufferImpl) Bounds() image.Rectangle { return image.Rectangle{Max: b.size} } -func (b *bufferImpl) RGBA() *image.RGBA { return &b.rgba } - -func (b *bufferImpl) preUpload() { - // Check that the program hasn't tried to modify the rgba field via the - // pointer returned by the bufferImpl.RGBA method. This check doesn't catch - // 100% of all cases; it simply tries to detect some invalid uses of a - // screen.Buffer such as: - // *buffer.RGBA() = anotherImageRGBA - if len(b.buf) != 0 && len(b.rgba.Pix) != 0 && &b.buf[0] != &b.rgba.Pix[0] { - panic("gldriver: invalid Buffer.RGBA modification") - } -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.go deleted file mode 100644 index db5ba63..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.go +++ /dev/null @@ -1,671 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && !ios -// +build darwin,!ios - -package gldriver - -/* -#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION -#cgo LDFLAGS: -framework Cocoa -framework OpenGL -#include -#import // for HIToolbox/Events.h -#import -#include -#include -#include - -void startDriver(); -void stopDriver(); -void makeCurrentContext(uintptr_t ctx); -void flushContext(uintptr_t ctx); -uintptr_t doNewWindow(int width, int height, char* title); -void doShowWindow(uintptr_t id); -void doCloseWindow(uintptr_t id); -uint64_t threadID(); -*/ -import "C" - -import ( - "errors" - "fmt" - "log" - "runtime" - "unsafe" - - "golang.org/x/exp/shiny/driver/internal/lifecycler" - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/event/key" - "golang.org/x/mobile/event/mouse" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/geom" - "golang.org/x/mobile/gl" -) - -const useLifecycler = true - -// TODO: change this to true, after manual testing on OS X. -const handleSizeEventsAtChannelReceive = false - -var initThreadID C.uint64_t - -func init() { - // Lock the goroutine responsible for initialization to an OS thread. - // This means the goroutine running main (and calling startDriver below) - // is locked to the OS thread that started the program. This is - // necessary for the correct delivery of Cocoa events to the process. - // - // A discussion on this topic: - // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ - runtime.LockOSThread() - initThreadID = C.threadID() -} - -func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { - width, height := optsSize(opts) - - title := C.CString(opts.GetTitle()) - defer C.free(unsafe.Pointer(title)) - - return uintptr(C.doNewWindow(C.int(width), C.int(height), title)), nil -} - -func initWindow(w *windowImpl) { - w.glctx, w.worker = gl.NewContext() -} - -func showWindow(w *windowImpl) { - C.doShowWindow(C.uintptr_t(w.id)) -} - -//export preparedOpenGL -func preparedOpenGL(id, ctx, vba uintptr) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - w.ctx = ctx - go drawLoop(w, vba) -} - -func closeWindow(id uintptr) { - C.doCloseWindow(C.uintptr_t(id)) -} - -var mainCallback func(screen.Screen) - -func main(f func(screen.Screen)) error { - if tid := C.threadID(); tid != initThreadID { - log.Fatalf("gldriver.Main called on thread %d, but gldriver.init ran on %d", tid, initThreadID) - } - - mainCallback = f - C.startDriver() - return nil -} - -//export driverStarted -func driverStarted() { - go func() { - mainCallback(theScreen) - C.stopDriver() - }() -} - -//export drawgl -func drawgl(id uintptr) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return // closing window - } - - // TODO: is this necessary? - w.lifecycler.SetVisible(true) - w.lifecycler.SendEvent(w, w.glctx) - - w.Send(paint.Event{External: true}) - <-w.drawDone -} - -// drawLoop is the primary drawing loop. -// -// After Cocoa has created an NSWindow and called prepareOpenGL, -// it starts drawLoop on a locked goroutine to handle OpenGL calls. -// -// The screen is drawn every time a paint.Event is received, which can be -// triggered either by the user or by Cocoa via drawgl (for example, when -// the window is resized). -func drawLoop(w *windowImpl, vba uintptr) { - runtime.LockOSThread() - C.makeCurrentContext(C.uintptr_t(w.ctx.(uintptr))) - - // Starting in OS X 10.11 (El Capitan), the vertex array is - // occasionally getting unbound when the context changes threads. - // - // Avoid this by binding it again. - C.glBindVertexArray(C.GLuint(vba)) - if errno := C.glGetError(); errno != 0 { - panic(fmt.Sprintf("gldriver: glBindVertexArray failed: %d", errno)) - } - - workAvailable := w.worker.WorkAvailable() - - // TODO(crawshaw): exit this goroutine on Release. - for { - select { - case <-workAvailable: - w.worker.DoWork() - case <-w.publish: - loop: - for { - select { - case <-workAvailable: - w.worker.DoWork() - default: - break loop - } - } - C.flushContext(C.uintptr_t(w.ctx.(uintptr))) - w.publishDone <- screen.PublishResult{} - } - } -} - -//export setGeom -func setGeom(id uintptr, ppp float32, widthPx, heightPx int) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return // closing window - } - - sz := size.Event{ - WidthPx: widthPx, - HeightPx: heightPx, - WidthPt: geom.Pt(float32(widthPx) / ppp), - HeightPt: geom.Pt(float32(heightPx) / ppp), - PixelsPerPt: ppp, - } - - if !handleSizeEventsAtChannelReceive { - w.szMu.Lock() - w.sz = sz - w.szMu.Unlock() - } - - w.Send(sz) -} - -//export windowClosing -func windowClosing(id uintptr) { - sendLifecycle(id, (*lifecycler.State).SetDead, true) -} - -func sendWindowEvent(id uintptr, e interface{}) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return // closing window - } - w.Send(e) -} - -var mods = [...]struct { - flags uint32 - code uint16 - mod key.Modifiers -}{ - // Left and right variants of modifier keys have their own masks, - // but they are not documented. These were determined empirically. - {1<<17 | 0x102, C.kVK_Shift, key.ModShift}, - {1<<17 | 0x104, C.kVK_RightShift, key.ModShift}, - {1<<18 | 0x101, C.kVK_Control, key.ModControl}, - {33<<13 | 0x100, C.kVK_RightControl, key.ModControl}, - {1<<19 | 0x120, C.kVK_Option, key.ModAlt}, - {1<<19 | 0x140, C.kVK_RightOption, key.ModAlt}, - {1<<20 | 0x108, C.kVK_Command, key.ModMeta}, - {1<<20 | 0x110, 0x36 /* kVK_RightCommand */, key.ModMeta}, -} - -func cocoaMods(flags uint32) (m key.Modifiers) { - for _, mod := range mods { - if flags&mod.flags == mod.flags { - m |= mod.mod - } - } - return m -} - -func cocoaMouseDir(ty int32) mouse.Direction { - switch ty { - case C.NSLeftMouseDown, C.NSRightMouseDown, C.NSOtherMouseDown: - return mouse.DirPress - case C.NSLeftMouseUp, C.NSRightMouseUp, C.NSOtherMouseUp: - return mouse.DirRelease - default: // dragged - return mouse.DirNone - } -} - -func cocoaMouseButton(button int32) mouse.Button { - switch button { - case 0: - return mouse.ButtonLeft - case 1: - return mouse.ButtonRight - case 2: - return mouse.ButtonMiddle - default: - return mouse.ButtonNone - } -} - -//export mouseEvent -func mouseEvent(id uintptr, x, y, dx, dy float32, ty, button int32, flags uint32) { - cmButton := mouse.ButtonNone - switch ty { - default: - cmButton = cocoaMouseButton(button) - case C.NSMouseMoved, C.NSLeftMouseDragged, C.NSRightMouseDragged, C.NSOtherMouseDragged: - // No-op. - case C.NSScrollWheel: - // Note that the direction of scrolling is inverted by default - // on OS X by the "natural scrolling" setting. At the Cocoa - // level this inversion is applied to trackpads and mice behind - // the scenes, and the value of dy goes in the direction the OS - // wants scrolling to go. - // - // This means the same trackpad/mouse motion on OS X and Linux - // can produce wheel events in opposite directions, but the - // direction matches what other programs on the OS do. - // - // If we wanted to expose the physical device motion in the - // event we could use [NSEvent isDirectionInvertedFromDevice] - // to know if "natural scrolling" is enabled. - // - // TODO: On a trackpad, a scroll can be a drawn-out affair with a - // distinct beginning and end. Should the intermediate events be - // DirNone? - // - // TODO: handle horizontal scrolling - button := mouse.ButtonWheelUp - if dy < 0 { - dy = -dy - button = mouse.ButtonWheelDown - } - e := mouse.Event{ - X: x, - Y: y, - Button: button, - Direction: mouse.DirStep, - Modifiers: cocoaMods(flags), - } - for delta := int(dy); delta != 0; delta-- { - sendWindowEvent(id, e) - } - return - } - sendWindowEvent(id, mouse.Event{ - X: x, - Y: y, - Button: cmButton, - Direction: cocoaMouseDir(ty), - Modifiers: cocoaMods(flags), - }) -} - -//export keyEvent -func keyEvent(id uintptr, runeVal rune, dir uint8, code uint16, flags uint32) { - sendWindowEvent(id, key.Event{ - Rune: cocoaRune(runeVal), - Direction: key.Direction(dir), - Code: cocoaKeyCode(code), - Modifiers: cocoaMods(flags), - }) -} - -//export flagEvent -func flagEvent(id uintptr, flags uint32) { - for _, mod := range mods { - if flags&mod.flags == mod.flags && lastFlags&mod.flags != mod.flags { - keyEvent(id, -1, C.NSKeyDown, mod.code, flags) - } - if lastFlags&mod.flags == mod.flags && flags&mod.flags != mod.flags { - keyEvent(id, -1, C.NSKeyUp, mod.code, flags) - } - } - lastFlags = flags -} - -var lastFlags uint32 - -func sendLifecycle(id uintptr, setter func(*lifecycler.State, bool), val bool) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - setter(&w.lifecycler, val) - w.lifecycler.SendEvent(w, w.glctx) -} - -func sendLifecycleAll(dead bool) { - windows := []*windowImpl{} - - theScreen.mu.Lock() - for _, w := range theScreen.windows { - windows = append(windows, w) - } - theScreen.mu.Unlock() - - for _, w := range windows { - w.lifecycler.SetFocused(false) - w.lifecycler.SetVisible(false) - if dead { - w.lifecycler.SetDead(true) - } - w.lifecycler.SendEvent(w, w.glctx) - } -} - -//export lifecycleDeadAll -func lifecycleDeadAll() { sendLifecycleAll(true) } - -//export lifecycleHideAll -func lifecycleHideAll() { sendLifecycleAll(false) } - -//export lifecycleVisible -func lifecycleVisible(id uintptr, val bool) { - sendLifecycle(id, (*lifecycler.State).SetVisible, val) -} - -//export lifecycleFocused -func lifecycleFocused(id uintptr, val bool) { - sendLifecycle(id, (*lifecycler.State).SetFocused, val) -} - -// cocoaRune marks the Carbon/Cocoa private-range unicode rune representing -// a non-unicode key event to -1, used for Rune in the key package. -// -// http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT -func cocoaRune(r rune) rune { - if '\uE000' <= r && r <= '\uF8FF' { - return -1 - } - return r -} - -// cocoaKeyCode converts a Carbon/Cocoa virtual key code number -// into the standard keycodes used by the key package. -// -// To get a sense of the key map, see the diagram on -// -// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes -func cocoaKeyCode(vkcode uint16) key.Code { - switch vkcode { - case C.kVK_ANSI_A: - return key.CodeA - case C.kVK_ANSI_B: - return key.CodeB - case C.kVK_ANSI_C: - return key.CodeC - case C.kVK_ANSI_D: - return key.CodeD - case C.kVK_ANSI_E: - return key.CodeE - case C.kVK_ANSI_F: - return key.CodeF - case C.kVK_ANSI_G: - return key.CodeG - case C.kVK_ANSI_H: - return key.CodeH - case C.kVK_ANSI_I: - return key.CodeI - case C.kVK_ANSI_J: - return key.CodeJ - case C.kVK_ANSI_K: - return key.CodeK - case C.kVK_ANSI_L: - return key.CodeL - case C.kVK_ANSI_M: - return key.CodeM - case C.kVK_ANSI_N: - return key.CodeN - case C.kVK_ANSI_O: - return key.CodeO - case C.kVK_ANSI_P: - return key.CodeP - case C.kVK_ANSI_Q: - return key.CodeQ - case C.kVK_ANSI_R: - return key.CodeR - case C.kVK_ANSI_S: - return key.CodeS - case C.kVK_ANSI_T: - return key.CodeT - case C.kVK_ANSI_U: - return key.CodeU - case C.kVK_ANSI_V: - return key.CodeV - case C.kVK_ANSI_W: - return key.CodeW - case C.kVK_ANSI_X: - return key.CodeX - case C.kVK_ANSI_Y: - return key.CodeY - case C.kVK_ANSI_Z: - return key.CodeZ - case C.kVK_ANSI_1: - return key.Code1 - case C.kVK_ANSI_2: - return key.Code2 - case C.kVK_ANSI_3: - return key.Code3 - case C.kVK_ANSI_4: - return key.Code4 - case C.kVK_ANSI_5: - return key.Code5 - case C.kVK_ANSI_6: - return key.Code6 - case C.kVK_ANSI_7: - return key.Code7 - case C.kVK_ANSI_8: - return key.Code8 - case C.kVK_ANSI_9: - return key.Code9 - case C.kVK_ANSI_0: - return key.Code0 - // TODO: move the rest of these codes to constants in key.go - // if we are happy with them. - case C.kVK_Return: - return key.CodeReturnEnter - case C.kVK_Escape: - return key.CodeEscape - case C.kVK_Delete: - return key.CodeDeleteBackspace - case C.kVK_Tab: - return key.CodeTab - case C.kVK_Space: - return key.CodeSpacebar - case C.kVK_ANSI_Minus: - return key.CodeHyphenMinus - case C.kVK_ANSI_Equal: - return key.CodeEqualSign - case C.kVK_ANSI_LeftBracket: - return key.CodeLeftSquareBracket - case C.kVK_ANSI_RightBracket: - return key.CodeRightSquareBracket - case C.kVK_ANSI_Backslash: - return key.CodeBackslash - // 50: Keyboard Non-US "#" and ~ - case C.kVK_ANSI_Semicolon: - return key.CodeSemicolon - case C.kVK_ANSI_Quote: - return key.CodeApostrophe - case C.kVK_ANSI_Grave: - return key.CodeGraveAccent - case C.kVK_ANSI_Comma: - return key.CodeComma - case C.kVK_ANSI_Period: - return key.CodeFullStop - case C.kVK_ANSI_Slash: - return key.CodeSlash - case C.kVK_CapsLock: - return key.CodeCapsLock - case C.kVK_F1: - return key.CodeF1 - case C.kVK_F2: - return key.CodeF2 - case C.kVK_F3: - return key.CodeF3 - case C.kVK_F4: - return key.CodeF4 - case C.kVK_F5: - return key.CodeF5 - case C.kVK_F6: - return key.CodeF6 - case C.kVK_F7: - return key.CodeF7 - case C.kVK_F8: - return key.CodeF8 - case C.kVK_F9: - return key.CodeF9 - case C.kVK_F10: - return key.CodeF10 - case C.kVK_F11: - return key.CodeF11 - case C.kVK_F12: - return key.CodeF12 - // 70: PrintScreen - // 71: Scroll Lock - // 72: Pause - // 73: Insert - case C.kVK_Home: - return key.CodeHome - case C.kVK_PageUp: - return key.CodePageUp - case C.kVK_ForwardDelete: - return key.CodeDeleteForward - case C.kVK_End: - return key.CodeEnd - case C.kVK_PageDown: - return key.CodePageDown - case C.kVK_RightArrow: - return key.CodeRightArrow - case C.kVK_LeftArrow: - return key.CodeLeftArrow - case C.kVK_DownArrow: - return key.CodeDownArrow - case C.kVK_UpArrow: - return key.CodeUpArrow - case C.kVK_ANSI_KeypadClear: - return key.CodeKeypadNumLock - case C.kVK_ANSI_KeypadDivide: - return key.CodeKeypadSlash - case C.kVK_ANSI_KeypadMultiply: - return key.CodeKeypadAsterisk - case C.kVK_ANSI_KeypadMinus: - return key.CodeKeypadHyphenMinus - case C.kVK_ANSI_KeypadPlus: - return key.CodeKeypadPlusSign - case C.kVK_ANSI_KeypadEnter: - return key.CodeKeypadEnter - case C.kVK_ANSI_Keypad1: - return key.CodeKeypad1 - case C.kVK_ANSI_Keypad2: - return key.CodeKeypad2 - case C.kVK_ANSI_Keypad3: - return key.CodeKeypad3 - case C.kVK_ANSI_Keypad4: - return key.CodeKeypad4 - case C.kVK_ANSI_Keypad5: - return key.CodeKeypad5 - case C.kVK_ANSI_Keypad6: - return key.CodeKeypad6 - case C.kVK_ANSI_Keypad7: - return key.CodeKeypad7 - case C.kVK_ANSI_Keypad8: - return key.CodeKeypad8 - case C.kVK_ANSI_Keypad9: - return key.CodeKeypad9 - case C.kVK_ANSI_Keypad0: - return key.CodeKeypad0 - case C.kVK_ANSI_KeypadDecimal: - return key.CodeKeypadFullStop - case C.kVK_ANSI_KeypadEquals: - return key.CodeKeypadEqualSign - case C.kVK_F13: - return key.CodeF13 - case C.kVK_F14: - return key.CodeF14 - case C.kVK_F15: - return key.CodeF15 - case C.kVK_F16: - return key.CodeF16 - case C.kVK_F17: - return key.CodeF17 - case C.kVK_F18: - return key.CodeF18 - case C.kVK_F19: - return key.CodeF19 - case C.kVK_F20: - return key.CodeF20 - // 116: Keyboard Execute - case C.kVK_Help: - return key.CodeHelp - // 118: Keyboard Menu - // 119: Keyboard Select - // 120: Keyboard Stop - // 121: Keyboard Again - // 122: Keyboard Undo - // 123: Keyboard Cut - // 124: Keyboard Copy - // 125: Keyboard Paste - // 126: Keyboard Find - case C.kVK_Mute: - return key.CodeMute - case C.kVK_VolumeUp: - return key.CodeVolumeUp - case C.kVK_VolumeDown: - return key.CodeVolumeDown - // 130: Keyboard Locking Caps Lock - // 131: Keyboard Locking Num Lock - // 132: Keyboard Locking Scroll Lock - // 133: Keyboard Comma - // 134: Keyboard Equal Sign - // ...: Bunch of stuff - case C.kVK_Control: - return key.CodeLeftControl - case C.kVK_Shift: - return key.CodeLeftShift - case C.kVK_Option: - return key.CodeLeftAlt - case C.kVK_Command: - return key.CodeLeftGUI - case C.kVK_RightControl: - return key.CodeRightControl - case C.kVK_RightShift: - return key.CodeRightShift - case C.kVK_RightOption: - return key.CodeRightAlt - // TODO key.CodeRightGUI - default: - return key.CodeUnknown - } -} - -func surfaceCreate() error { - return errors.New("gldriver: surface creation not implemented on darwin") -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.m b/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.m deleted file mode 100644 index 2c8fd83..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.m +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin -// +build !ios - -#include "_cgo_export.h" -#include -#include - -#import -#import -#import - -// The variables did not exist on older OS X releases, -// we use the old variables deprecated on macOS to define them. -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200 -enum -{ - NSEventTypeScrollWheel = NSScrollWheel, - NSEventTypeKeyDown = NSKeyDown -}; -enum -{ - NSWindowStyleMaskTitled = NSTitledWindowMask, - NSWindowStyleMaskResizable = NSResizableWindowMask, - NSWindowStyleMaskMiniaturizable = NSMiniaturizableWindowMask, - NSWindowStyleMaskClosable = NSClosableWindowMask -}; -#endif - -void makeCurrentContext(uintptr_t context) { - NSOpenGLContext* ctx = (NSOpenGLContext*)context; - [ctx makeCurrentContext]; -} - -void flushContext(uintptr_t context) { - NSOpenGLContext* ctx = (NSOpenGLContext*)context; - [ctx flushBuffer]; -} - -uint64 threadID() { - uint64 id; - if (pthread_threadid_np(pthread_self(), &id)) { - abort(); - } - return id; -} - -@interface ScreenGLView : NSOpenGLView -{ -} -@end - -@implementation ScreenGLView -- (void)prepareOpenGL { - [super prepareOpenGL]; - - [self setWantsBestResolutionOpenGLSurface:YES]; - GLint swapInt = 1; - NSOpenGLContext *ctx = [self openGLContext]; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [ctx setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; -#pragma clang diagnostic pop - - // Using attribute arrays in OpenGL 3.3 requires the use of a VBA. - // But VBAs don't exist in ES 2. So we bind a default one. - GLuint vba; - glGenVertexArrays(1, &vba); - glBindVertexArray(vba); - - preparedOpenGL((GoUintptr)self, (GoUintptr)ctx, (GoUintptr)vba); -} - -- (void)callSetGeom { - // Calculate screen PPI. - // - // Note that the backingScaleFactor converts from logical - // pixels to actual pixels, but both of these units vary - // independently from real world size. E.g. - // - // 13" Retina Macbook Pro, 2560x1600, 227ppi, backingScaleFactor=2, scale=3.15 - // 15" Retina Macbook Pro, 2880x1800, 220ppi, backingScaleFactor=2, scale=3.06 - // 27" iMac, 2560x1440, 109ppi, backingScaleFactor=1, scale=1.51 - // 27" Retina iMac, 5120x2880, 218ppi, backingScaleFactor=2, scale=3.03 - NSScreen *screen = self.window.screen; - double screenPixW = [screen frame].size.width * [screen backingScaleFactor]; - - CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue]; - CGSize screenSizeMM = CGDisplayScreenSize(display); // in millimeters - float ppi = 25.4 * screenPixW / screenSizeMM.width; - float pixelsPerPt = ppi/72.0; - - // The width and height reported to the geom package are the - // bounds of the OpenGL view. Several steps are necessary. - // First, [self bounds] gives us the number of logical pixels - // in the view. Multiplying this by the backingScaleFactor - // gives us the number of actual pixels. - NSRect r = [self bounds]; - int w = r.size.width * [screen backingScaleFactor]; - int h = r.size.height * [screen backingScaleFactor]; - - setGeom((GoUintptr)self, pixelsPerPt, w, h); -} - -- (void)reshape { - [super reshape]; - [self callSetGeom]; -} - -- (void)drawRect:(NSRect)theRect { - // Called during resize. Do an extra draw if we are visible. - // This gets rid of flicker when resizing. - drawgl((GoUintptr)self); -} - -- (void)mouseEventNS:(NSEvent *)theEvent { - NSPoint p = [theEvent locationInWindow]; - double h = self.frame.size.height; - - // Both h and p are measured in Cocoa pixels, which are a fraction of - // physical pixels, so we multiply by backingScaleFactor. - double scale = [self.window.screen backingScaleFactor]; - - double x = p.x * scale; - double y = (h - p.y) * scale - 1; // flip origin from bottom-left to top-left. - - double dx, dy; - if (theEvent.type == NSEventTypeScrollWheel) { - dx = theEvent.scrollingDeltaX; - dy = theEvent.scrollingDeltaY; - } - - mouseEvent((GoUintptr)self, x, y, dx, dy, theEvent.type, theEvent.buttonNumber, theEvent.modifierFlags); -} - -- (void)mouseMoved:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)mouseDown:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)mouseUp:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)mouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)rightMouseDown:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)rightMouseUp:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)rightMouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)otherMouseDown:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)otherMouseUp:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)otherMouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } -- (void)scrollWheel:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } - -// raw modifier key presses -- (void)flagsChanged:(NSEvent *)theEvent { - flagEvent((GoUintptr)self, theEvent.modifierFlags); -} - -// overrides special handling of escape and tab -- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { - [self key:theEvent]; - return YES; -} - -- (void)keyDown:(NSEvent *)theEvent { [self key:theEvent]; } -- (void)keyUp:(NSEvent *)theEvent { [self key:theEvent]; } - -- (void)key:(NSEvent *)theEvent { - NSRange range = [theEvent.characters rangeOfComposedCharacterSequenceAtIndex:0]; - - uint8_t buf[4] = {0, 0, 0, 0}; - if (![theEvent.characters getBytes:buf - maxLength:4 - usedLength:nil - encoding:NSUTF32LittleEndianStringEncoding - options:NSStringEncodingConversionAllowLossy - range:range - remainingRange:nil]) { - NSLog(@"failed to read key event %@", theEvent); - return; - } - - uint32_t rune = (uint32_t)buf[0]<<0 | (uint32_t)buf[1]<<8 | (uint32_t)buf[2]<<16 | (uint32_t)buf[3]<<24; - - uint8_t direction; - if ([theEvent isARepeat]) { - direction = 0; - } else if (theEvent.type == NSEventTypeKeyDown) { - direction = 1; - } else { - direction = 2; - } - keyEvent((GoUintptr)self, (int32_t)rune, direction, theEvent.keyCode, theEvent.modifierFlags); -} - -- (void)windowDidChangeScreenProfile:(NSNotification *)notification { - [self callSetGeom]; -} - -// TODO: catch windowDidMiniaturize? - -- (void)windowDidExpose:(NSNotification *)notification { - lifecycleVisible((GoUintptr)self, true); -} - -- (void)windowDidBecomeKey:(NSNotification *)notification { - lifecycleFocused((GoUintptr)self, true); -} - -- (void)windowDidResignKey:(NSNotification *)notification { - lifecycleFocused((GoUintptr)self, false); - if ([NSApp isHidden]) { - lifecycleVisible((GoUintptr)self, false); - } -} - -- (void)windowWillClose:(NSNotification *)notification { - // TODO: is this right? Closing a window via the top-left red button - // seems to return early without ever calling windowClosing. - if (self.window.nextResponder == NULL) { - return; // already called close - } - - windowClosing((GoUintptr)self); - [self.window.nextResponder release]; - self.window.nextResponder = NULL; -} -@end - -@interface AppDelegate : NSObject -{ -} -@end - -@implementation AppDelegate -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - driverStarted(); - [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)]; -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - lifecycleDeadAll(); -} - -- (void)applicationWillHide:(NSNotification *)aNotification { - lifecycleHideAll(); -} -@end - -uintptr_t doNewWindow(int width, int height, char* title) { - NSScreen *screen = [NSScreen mainScreen]; - double w = (double)width / [screen backingScaleFactor]; - double h = (double)height / [screen backingScaleFactor]; - __block ScreenGLView* view = NULL; - - dispatch_sync(dispatch_get_main_queue(), ^{ - id menuBar = [NSMenu new]; - id menuItem = [NSMenuItem new]; - [menuBar addItem:menuItem]; - [NSApp setMainMenu:menuBar]; - - id menu = [NSMenu new]; - NSString* name = [[NSString alloc] initWithUTF8String:title]; - - id hideMenuItem = [[NSMenuItem alloc] initWithTitle:@"Hide" - action:@selector(hide:) keyEquivalent:@"h"]; - [menu addItem:hideMenuItem]; - - id quitMenuItem = [[NSMenuItem alloc] initWithTitle:@"Quit" - action:@selector(terminate:) keyEquivalent:@"q"]; - [menu addItem:quitMenuItem]; - [menuItem setSubmenu:menu]; - - NSRect rect = NSMakeRect(0, 0, w, h); - - NSWindow* window = [[NSWindow alloc] initWithContentRect:rect - styleMask:NSWindowStyleMaskTitled - backing:NSBackingStoreBuffered - defer:NO]; - window.styleMask |= NSWindowStyleMaskResizable; - window.styleMask |= NSWindowStyleMaskMiniaturizable; - window.styleMask |= NSWindowStyleMaskClosable; - window.title = name; - window.displaysWhenScreenProfileChanges = YES; - [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; - [window setAcceptsMouseMovedEvents:YES]; - - NSOpenGLPixelFormatAttribute attr[] = { - NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 16, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAllowOfflineRenderers, - 0 - }; - id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; - view = [[ScreenGLView alloc] initWithFrame:rect pixelFormat:pixFormat]; - [window setContentView:view]; - [window setDelegate:view]; - [window makeFirstResponder:view]; - }); - - return (uintptr_t)view; -} - -void doShowWindow(uintptr_t viewID) { - ScreenGLView* view = (ScreenGLView*)viewID; - dispatch_async(dispatch_get_main_queue(), ^{ - [view.window makeKeyAndOrderFront:view.window]; - }); -} - -void doCloseWindow(uintptr_t viewID) { - ScreenGLView* view = (ScreenGLView*)viewID; - dispatch_sync(dispatch_get_main_queue(), ^{ - [view.window performClose:view]; - }); -} - -void startDriver() { - [NSAutoreleasePool new]; - [NSApplication sharedApplication]; - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - AppDelegate* delegate = [[AppDelegate alloc] init]; - [NSApp setDelegate:delegate]; - [NSApp run]; -} - -void stopDriver() { - dispatch_async(dispatch_get_main_queue(), ^{ - [NSApp terminate:nil]; - }); -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/context.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/context.go deleted file mode 100644 index 274d799..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/context.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !android -// +build !android - -package gldriver - -import ( - "runtime" - - "golang.org/x/mobile/gl" -) - -// NewContext creates an OpenGL ES context with a dedicated processing thread. -func NewContext() (gl.Context, error) { - glctx, worker := gl.NewContext() - - errCh := make(chan error) - workAvailable := worker.WorkAvailable() - go func() { - runtime.LockOSThread() - err := surfaceCreate() - errCh <- err - if err != nil { - return - } - - for range workAvailable { - worker.DoWork() - } - }() - if err := <-errCh; err != nil { - return nil, err - } - return glctx, nil -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/egl.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/egl.go deleted file mode 100644 index 6f5d3d7..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/egl.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gldriver - -// These constants match the values found in the EGL 1.4 headers, -// egl.h, eglext.h, and eglplatform.h. -const ( - _EGL_DONT_CARE = -1 - - _EGL_NO_SURFACE = 0 - _EGL_NO_CONTEXT = 0 - _EGL_NO_DISPLAY = 0 - - _EGL_OPENGL_ES2_BIT = 0x04 // EGL_RENDERABLE_TYPE mask - _EGL_WINDOW_BIT = 0x04 // EGL_SURFACE_TYPE mask - - _EGL_OPENGL_ES_API = 0x30A0 - _EGL_RENDERABLE_TYPE = 0x3040 - _EGL_SURFACE_TYPE = 0x3033 - _EGL_BUFFER_SIZE = 0x3020 - _EGL_ALPHA_SIZE = 0x3021 - _EGL_BLUE_SIZE = 0x3022 - _EGL_GREEN_SIZE = 0x3023 - _EGL_RED_SIZE = 0x3024 - _EGL_DEPTH_SIZE = 0x3025 - _EGL_STENCIL_SIZE = 0x3026 - _EGL_SAMPLE_BUFFERS = 0x3032 - _EGL_CONFIG_CAVEAT = 0x3027 - _EGL_NONE = 0x3038 - - _EGL_CONTEXT_CLIENT_VERSION = 0x3098 -) - -// ANGLE specific options found in eglext.h -const ( - _EGL_PLATFORM_ANGLE_ANGLE = 0x3202 - _EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203 - _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204 - _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205 - _EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206 - - _EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207 - _EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208 - _EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209 - _EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A - _EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE = 0x320B - - _EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D - _EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E -) - -const ( - _EGL_SUCCESS = 0x3000 - _EGL_NOT_INITIALIZED = 0x3001 - _EGL_BAD_ACCESS = 0x3002 - _EGL_BAD_ALLOC = 0x3003 - _EGL_BAD_ATTRIBUTE = 0x3004 - _EGL_BAD_CONFIG = 0x3005 - _EGL_BAD_CONTEXT = 0x3006 - _EGL_BAD_CURRENT_SURFACE = 0x3007 - _EGL_BAD_DISPLAY = 0x3008 - _EGL_BAD_MATCH = 0x3009 - _EGL_BAD_NATIVE_PIXMAP = 0x300A - _EGL_BAD_NATIVE_WINDOW = 0x300B - _EGL_BAD_PARAMETER = 0x300C - _EGL_BAD_SURFACE = 0x300D - _EGL_CONTEXT_LOST = 0x300E -) - -func eglErrString(errno uintptr) string { - switch errno { - case _EGL_SUCCESS: - return "EGL_SUCCESS" - case _EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED" - case _EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS" - case _EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC" - case _EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE" - case _EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG" - case _EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT" - case _EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE" - case _EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY" - case _EGL_BAD_MATCH: - return "EGL_BAD_MATCH" - case _EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP" - case _EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW" - case _EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER" - case _EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE" - case _EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST" - } - return "EGL: unknown error" -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go deleted file mode 100644 index 37eb467..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package gldriver provides an OpenGL driver for accessing a screen. -package gldriver // import "golang.org/x/exp/shiny/driver/gldriver" - -import ( - "encoding/binary" - "fmt" - "math" - - "golang.org/x/exp/shiny/driver/internal/errscreen" - "golang.org/x/exp/shiny/screen" - "golang.org/x/image/math/f64" - "golang.org/x/mobile/gl" -) - -// Main is called by the program's main function to run the graphical -// application. -// -// It calls f on the Screen, possibly in a separate goroutine, as some OS- -// specific libraries require being on 'the main thread'. It returns when f -// returns. -func Main(f func(screen.Screen)) { - if err := main(f); err != nil { - f(errscreen.Stub(err)) - } -} - -func mul(a, b f64.Aff3) f64.Aff3 { - return f64.Aff3{ - a[0]*b[0] + a[1]*b[3], - a[0]*b[1] + a[1]*b[4], - a[0]*b[2] + a[1]*b[5] + a[2], - - a[3]*b[0] + a[4]*b[3], - a[3]*b[1] + a[4]*b[4], - a[3]*b[2] + a[4]*b[5] + a[5], - } -} - -// writeAff3 must only be called while holding windowImpl.glctxMu. -func writeAff3(glctx gl.Context, u gl.Uniform, a f64.Aff3) { - var m [9]float32 - m[0*3+0] = float32(a[0*3+0]) - m[0*3+1] = float32(a[1*3+0]) - m[0*3+2] = 0 - m[1*3+0] = float32(a[0*3+1]) - m[1*3+1] = float32(a[1*3+1]) - m[1*3+2] = 0 - m[2*3+0] = float32(a[0*3+2]) - m[2*3+1] = float32(a[1*3+2]) - m[2*3+2] = 1 - glctx.UniformMatrix3fv(u, m[:]) -} - -// f32Bytes returns the byte representation of float32 values in the given byte -// order. byteOrder must be either binary.BigEndian or binary.LittleEndian. -func f32Bytes(byteOrder binary.ByteOrder, values ...float32) []byte { - le := false - switch byteOrder { - case binary.BigEndian: - case binary.LittleEndian: - le = true - default: - panic(fmt.Sprintf("invalid byte order %v", byteOrder)) - } - - b := make([]byte, 4*len(values)) - for i, v := range values { - u := math.Float32bits(v) - if le { - b[4*i+0] = byte(u >> 0) - b[4*i+1] = byte(u >> 8) - b[4*i+2] = byte(u >> 16) - b[4*i+3] = byte(u >> 24) - } else { - b[4*i+0] = byte(u >> 24) - b[4*i+1] = byte(u >> 16) - b[4*i+2] = byte(u >> 8) - b[4*i+3] = byte(u >> 0) - } - } - return b -} - -// compileProgram must only be called while holding windowImpl.glctxMu. -func compileProgram(glctx gl.Context, vSrc, fSrc string) (gl.Program, error) { - program := glctx.CreateProgram() - if program.Value == 0 { - return gl.Program{}, fmt.Errorf("gldriver: no programs available") - } - - vertexShader, err := compileShader(glctx, gl.VERTEX_SHADER, vSrc) - if err != nil { - return gl.Program{}, err - } - fragmentShader, err := compileShader(glctx, gl.FRAGMENT_SHADER, fSrc) - if err != nil { - glctx.DeleteShader(vertexShader) - return gl.Program{}, err - } - - glctx.AttachShader(program, vertexShader) - glctx.AttachShader(program, fragmentShader) - glctx.LinkProgram(program) - - // Flag shaders for deletion when program is unlinked. - glctx.DeleteShader(vertexShader) - glctx.DeleteShader(fragmentShader) - - if glctx.GetProgrami(program, gl.LINK_STATUS) == 0 { - defer glctx.DeleteProgram(program) - return gl.Program{}, fmt.Errorf("gldriver: program compile: %s", glctx.GetProgramInfoLog(program)) - } - return program, nil -} - -// compileShader must only be called while holding windowImpl.glctxMu. -func compileShader(glctx gl.Context, shaderType gl.Enum, src string) (gl.Shader, error) { - shader := glctx.CreateShader(shaderType) - if shader.Value == 0 { - return gl.Shader{}, fmt.Errorf("gldriver: could not create shader (type %v)", shaderType) - } - glctx.ShaderSource(shader, src) - glctx.CompileShader(shader) - if glctx.GetShaderi(shader, gl.COMPILE_STATUS) == 0 { - defer glctx.DeleteShader(shader) - return gl.Shader{}, fmt.Errorf("gldriver: shader compile: %s", glctx.GetShaderInfoLog(shader)) - } - return shader, nil -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/other.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/other.go deleted file mode 100644 index 0a04425..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/other.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (!darwin || ios || !cgo) && (!linux || android || !cgo) && (!openbsd || !cgo) && !windows -// +build !darwin ios !cgo -// +build !linux android !cgo -// +build !openbsd !cgo -// +build !windows - -package gldriver - -import ( - "fmt" - "runtime" - - "golang.org/x/exp/shiny/screen" -) - -const useLifecycler = true -const handleSizeEventsAtChannelReceive = true - -var errUnsupported = fmt.Errorf("gldriver: unsupported GOOS/GOARCH %s/%s or cgo not enabled", runtime.GOOS, runtime.GOARCH) - -func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { return 0, errUnsupported } - -func initWindow(id *windowImpl) {} -func showWindow(id *windowImpl) {} -func closeWindow(id uintptr) {} -func drawLoop(w *windowImpl) {} - -func surfaceCreate() error { return errUnsupported } -func main(f func(screen.Screen)) error { return errUnsupported } diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/screen.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/screen.go deleted file mode 100644 index f6f18f1..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/screen.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gldriver - -import ( - "fmt" - "image" - "sync" - - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/gl" -) - -var theScreen = &screenImpl{ - windows: make(map[uintptr]*windowImpl), -} - -type screenImpl struct { - texture struct { - program gl.Program - pos gl.Attrib - mvp gl.Uniform - uvp gl.Uniform - inUV gl.Attrib - sample gl.Uniform - quad gl.Buffer - } - fill struct { - program gl.Program - pos gl.Attrib - mvp gl.Uniform - color gl.Uniform - quad gl.Buffer - } - - mu sync.Mutex - windows map[uintptr]*windowImpl -} - -func (s *screenImpl) NewBuffer(size image.Point) (retBuf screen.Buffer, retErr error) { - m := image.NewRGBA(image.Rectangle{Max: size}) - return &bufferImpl{ - buf: m.Pix, - rgba: *m, - size: size, - }, nil -} - -func (s *screenImpl) NewTexture(size image.Point) (screen.Texture, error) { - // TODO: can we compile these programs eagerly instead of lazily? - - // Find a GL context for this texture. - // TODO: this might be correct. Some GL objects can be shared - // across contexts. But this needs a review of the spec to make - // sure it's correct, and some testing would be nice. - var w *windowImpl - - s.mu.Lock() - for _, window := range s.windows { - w = window - break - } - s.mu.Unlock() - - if w == nil { - return nil, fmt.Errorf("gldriver: no window available") - } - - w.glctxMu.Lock() - defer w.glctxMu.Unlock() - glctx := w.glctx - if glctx == nil { - return nil, fmt.Errorf("gldriver: no GL context available") - } - - if !glctx.IsProgram(s.texture.program) { - p, err := compileProgram(glctx, textureVertexSrc, textureFragmentSrc) - if err != nil { - return nil, err - } - s.texture.program = p - s.texture.pos = glctx.GetAttribLocation(p, "pos") - s.texture.mvp = glctx.GetUniformLocation(p, "mvp") - s.texture.uvp = glctx.GetUniformLocation(p, "uvp") - s.texture.inUV = glctx.GetAttribLocation(p, "inUV") - s.texture.sample = glctx.GetUniformLocation(p, "sample") - s.texture.quad = glctx.CreateBuffer() - - glctx.BindBuffer(gl.ARRAY_BUFFER, s.texture.quad) - glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW) - } - - t := &textureImpl{ - w: w, - id: glctx.CreateTexture(), - size: size, - } - - glctx.BindTexture(gl.TEXTURE_2D, t.id) - glctx.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.X, size.Y, gl.RGBA, gl.UNSIGNED_BYTE, nil) - glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - - return t, nil -} - -func optsSize(opts *screen.NewWindowOptions) (width, height int) { - width, height = 1024, 768 - if opts != nil { - if opts.Width > 0 { - width = opts.Width - } - if opts.Height > 0 { - height = opts.Height - } - } - return width, height -} - -func (s *screenImpl) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) { - id, err := newWindow(opts) - if err != nil { - return nil, err - } - w := &windowImpl{ - s: s, - id: id, - publish: make(chan struct{}), - publishDone: make(chan screen.PublishResult), - drawDone: make(chan struct{}), - } - initWindow(w) - - s.mu.Lock() - s.windows[id] = w - s.mu.Unlock() - - if useLifecycler { - w.lifecycler.SendEvent(w, nil) - } - - showWindow(w) - - return w, nil -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/texture.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/texture.go deleted file mode 100644 index a691ed8..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/texture.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gldriver - -import ( - "encoding/binary" - "image" - "image/color" - "image/draw" - - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/gl" -) - -type textureImpl struct { - w *windowImpl - id gl.Texture - fb gl.Framebuffer - size image.Point -} - -func (t *textureImpl) Size() image.Point { return t.size } -func (t *textureImpl) Bounds() image.Rectangle { return image.Rectangle{Max: t.size} } - -func (t *textureImpl) Release() { - t.w.glctxMu.Lock() - defer t.w.glctxMu.Unlock() - - if t.fb.Value != 0 { - t.w.glctx.DeleteFramebuffer(t.fb) - t.fb = gl.Framebuffer{} - } - t.w.glctx.DeleteTexture(t.id) - t.id = gl.Texture{} -} - -func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { - buf := src.(*bufferImpl) - buf.preUpload() - - // src2dst is added to convert from the src coordinate space to the dst - // coordinate space. It is subtracted to convert the other way. - src2dst := dp.Sub(sr.Min) - - // Clip to the source. - sr = sr.Intersect(buf.Bounds()) - - // Clip to the destination. - dr := sr.Add(src2dst) - dr = dr.Intersect(t.Bounds()) - if dr.Empty() { - return - } - - // Bring dr.Min in dst-space back to src-space to get the pixel buffer offset. - pix := buf.rgba.Pix[buf.rgba.PixOffset(dr.Min.X-src2dst.X, dr.Min.Y-src2dst.Y):] - - t.w.glctxMu.Lock() - defer t.w.glctxMu.Unlock() - - t.w.glctx.BindTexture(gl.TEXTURE_2D, t.id) - - width := dr.Dx() - if width*4 == buf.rgba.Stride { - t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, dr.Min.Y, width, dr.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, pix) - return - } - // TODO: can we use GL_UNPACK_ROW_LENGTH with glPixelStorei for stride in - // ES 3.0, instead of uploading the pixels row-by-row? - for y, p := dr.Min.Y, 0; y < dr.Max.Y; y++ { - t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, y, width, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix[p:]) - p += buf.rgba.Stride - } -} - -func (t *textureImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { - minX := float64(dr.Min.X) - minY := float64(dr.Min.Y) - maxX := float64(dr.Max.X) - maxY := float64(dr.Max.Y) - mvp := calcMVP( - t.size.X, t.size.Y, - minX, minY, - maxX, minY, - minX, maxY, - ) - - glctx := t.w.glctx - - t.w.glctxMu.Lock() - defer t.w.glctxMu.Unlock() - - create := t.fb.Value == 0 - if create { - t.fb = glctx.CreateFramebuffer() - } - glctx.BindFramebuffer(gl.FRAMEBUFFER, t.fb) - if create { - glctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, t.id, 0) - } - - glctx.Viewport(0, 0, t.size.X, t.size.Y) - doFill(t.w.s, t.w.glctx, mvp, src, op) - - // We can't restore the GL state (i.e. bind the back buffer, also known as - // gl.Framebuffer{Value: 0}) right away, since we don't necessarily know - // the right viewport size yet. It is valid to call textureImpl.Fill before - // we've gotten our first size.Event. We bind it lazily instead. - t.w.backBufferBound = false -} - -var quadCoords = f32Bytes(binary.LittleEndian, - 0, 0, // top left - 1, 0, // top right - 0, 1, // bottom left - 1, 1, // bottom right -) - -const textureVertexSrc = `#version 100 -uniform mat3 mvp; -uniform mat3 uvp; -attribute vec3 pos; -attribute vec2 inUV; -varying vec2 uv; -void main() { - vec3 p = pos; - p.z = 1.0; - gl_Position = vec4(mvp * p, 1); - uv = (uvp * vec3(inUV, 1)).xy; -} -` - -const textureFragmentSrc = `#version 100 -precision mediump float; -varying vec2 uv; -uniform sampler2D sample; -void main() { - gl_FragColor = texture2D(sample, uv); -} -` - -const fillVertexSrc = `#version 100 -uniform mat3 mvp; -attribute vec3 pos; -void main() { - vec3 p = pos; - p.z = 1.0; - gl_Position = vec4(mvp * p, 1); -} -` - -const fillFragmentSrc = `#version 100 -precision mediump float; -uniform vec4 color; -void main() { - gl_FragColor = color; -} -` diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/win32.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/win32.go deleted file mode 100644 index 8ece242..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/win32.go +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -package gldriver - -import ( - "errors" - "fmt" - "runtime" - "syscall" - "unsafe" - - "golang.org/x/exp/shiny/driver/internal/win32" - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/event/key" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/mouse" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/gl" -) - -// TODO: change this to true, after manual testing on Win32. -const useLifecycler = false - -// TODO: change this to true, after manual testing on Win32. -const handleSizeEventsAtChannelReceive = false - -func main(f func(screen.Screen)) error { - return win32.Main(func() { f(theScreen) }) -} - -var ( - eglGetPlatformDisplayEXT = gl.LibEGL.NewProc("eglGetPlatformDisplayEXT") - eglInitialize = gl.LibEGL.NewProc("eglInitialize") - eglChooseConfig = gl.LibEGL.NewProc("eglChooseConfig") - eglGetError = gl.LibEGL.NewProc("eglGetError") - eglBindAPI = gl.LibEGL.NewProc("eglBindAPI") - eglCreateWindowSurface = gl.LibEGL.NewProc("eglCreateWindowSurface") - eglCreateContext = gl.LibEGL.NewProc("eglCreateContext") - eglMakeCurrent = gl.LibEGL.NewProc("eglMakeCurrent") - eglSwapInterval = gl.LibEGL.NewProc("eglSwapInterval") - eglDestroySurface = gl.LibEGL.NewProc("eglDestroySurface") - eglSwapBuffers = gl.LibEGL.NewProc("eglSwapBuffers") -) - -type eglConfig uintptr // void* - -type eglInt int32 - -var rgb888 = [...]eglInt{ - _EGL_RENDERABLE_TYPE, _EGL_OPENGL_ES2_BIT, - _EGL_SURFACE_TYPE, _EGL_WINDOW_BIT, - _EGL_BLUE_SIZE, 8, - _EGL_GREEN_SIZE, 8, - _EGL_RED_SIZE, 8, - _EGL_DEPTH_SIZE, 16, - _EGL_STENCIL_SIZE, 8, - _EGL_NONE, -} - -type ctxWin32 struct { - ctx uintptr - display uintptr // EGLDisplay - surface uintptr // EGLSurface -} - -func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { - w, err := win32.NewWindow(opts) - if err != nil { - return 0, err - } - return uintptr(w), nil -} - -func initWindow(w *windowImpl) { - w.glctx, w.worker = gl.NewContext() -} - -func showWindow(w *windowImpl) { - // Show makes an initial call to sizeEvent (via win32.SizeEvent), where - // we setup the EGL surface and GL context. - win32.Show(syscall.Handle(w.id)) -} - -func closeWindow(id uintptr) {} // TODO - -func drawLoop(w *windowImpl) { - runtime.LockOSThread() - - display := w.ctx.(ctxWin32).display - surface := w.ctx.(ctxWin32).surface - ctx := w.ctx.(ctxWin32).ctx - - if ret, _, _ := eglMakeCurrent.Call(display, surface, surface, ctx); ret == 0 { - panic(fmt.Sprintf("eglMakeCurrent failed: %v", eglErr())) - } - - // TODO(crawshaw): exit this goroutine on Release. - workAvailable := w.worker.WorkAvailable() - for { - select { - case <-workAvailable: - w.worker.DoWork() - case <-w.publish: - loop: - for { - select { - case <-workAvailable: - w.worker.DoWork() - default: - break loop - } - } - if ret, _, _ := eglSwapBuffers.Call(display, surface); ret == 0 { - panic(fmt.Sprintf("eglSwapBuffers failed: %v", eglErr())) - } - w.publishDone <- screen.PublishResult{} - } - } -} - -func init() { - win32.SizeEvent = sizeEvent - win32.PaintEvent = paintEvent - win32.MouseEvent = mouseEvent - win32.KeyEvent = keyEvent - win32.LifecycleEvent = lifecycleEvent -} - -func lifecycleEvent(hwnd syscall.Handle, to lifecycle.Stage) { - theScreen.mu.Lock() - w := theScreen.windows[uintptr(hwnd)] - theScreen.mu.Unlock() - - if w.lifecycleStage == to { - return - } - w.Send(lifecycle.Event{ - From: w.lifecycleStage, - To: to, - DrawContext: w.glctx, - }) - w.lifecycleStage = to -} - -func mouseEvent(hwnd syscall.Handle, e mouse.Event) { - theScreen.mu.Lock() - w := theScreen.windows[uintptr(hwnd)] - theScreen.mu.Unlock() - - w.Send(e) -} - -func keyEvent(hwnd syscall.Handle, e key.Event) { - theScreen.mu.Lock() - w := theScreen.windows[uintptr(hwnd)] - theScreen.mu.Unlock() - - w.Send(e) -} - -func paintEvent(hwnd syscall.Handle, e paint.Event) { - theScreen.mu.Lock() - w := theScreen.windows[uintptr(hwnd)] - theScreen.mu.Unlock() - - if w.ctx == nil { - // Sometimes a paint event comes in before initial - // window size is set. Ignore it. - return - } - - // TODO: the paint.Event should have External: true. - w.Send(paint.Event{}) -} - -func sizeEvent(hwnd syscall.Handle, e size.Event) { - theScreen.mu.Lock() - w := theScreen.windows[uintptr(hwnd)] - theScreen.mu.Unlock() - - if w.ctx == nil { - // This is the initial size event on window creation. - // Create an EGL surface and spin up a GL context. - if err := createEGLSurface(hwnd, w); err != nil { - panic(err) - } - go drawLoop(w) - } - - if !handleSizeEventsAtChannelReceive { - w.szMu.Lock() - w.sz = e - w.szMu.Unlock() - } - - w.Send(e) - - if handleSizeEventsAtChannelReceive { - return - } - - // Screen is dirty, generate a paint event. - // - // The sizeEvent function is called on the goroutine responsible for - // calling the GL worker.DoWork. When compiling with -tags gldebug, - // these GL calls are blocking (so we can read the error message), so - // to make progress they need to happen on another goroutine. - go func() { - // TODO: this call to Viewport is not right, but is very hard to - // do correctly with our async events channel model. We want - // the call to Viewport to be made the instant before the - // paint.Event is received. - w.glctxMu.Lock() - w.glctx.Viewport(0, 0, e.WidthPx, e.HeightPx) - w.glctx.ClearColor(0, 0, 0, 1) - w.glctx.Clear(gl.COLOR_BUFFER_BIT) - w.glctxMu.Unlock() - - w.Send(paint.Event{}) - }() -} - -func eglErr() error { - if ret, _, _ := eglGetError.Call(); ret != _EGL_SUCCESS { - return errors.New(eglErrString(ret)) - } - return nil -} - -func createEGLSurface(hwnd syscall.Handle, w *windowImpl) error { - var displayAttribPlatforms = [][]eglInt{ - // Default - []eglInt{ - _EGL_PLATFORM_ANGLE_TYPE_ANGLE, - _EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, - _EGL_NONE, - }, - // Direct3D 11 - []eglInt{ - _EGL_PLATFORM_ANGLE_TYPE_ANGLE, - _EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, - _EGL_NONE, - }, - // Direct3D 9 - []eglInt{ - _EGL_PLATFORM_ANGLE_TYPE_ANGLE, - _EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, - _EGL_NONE, - }, - // Direct3D 11 with WARP - // https://msdn.microsoft.com/en-us/library/windows/desktop/gg615082.aspx - []eglInt{ - _EGL_PLATFORM_ANGLE_TYPE_ANGLE, - _EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - _EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, - _EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, - _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, - _EGL_NONE, - }, - } - - dc, err := win32.GetDC(hwnd) - if err != nil { - return fmt.Errorf("win32.GetDC failed: %v", err) - } - - var display uintptr = _EGL_NO_DISPLAY - for i, displayAttrib := range displayAttribPlatforms { - lastTry := i == len(displayAttribPlatforms)-1 - - display, _, _ = eglGetPlatformDisplayEXT.Call( - _EGL_PLATFORM_ANGLE_ANGLE, - uintptr(dc), - uintptr(unsafe.Pointer(&displayAttrib[0])), - ) - - if display == _EGL_NO_DISPLAY { - if !lastTry { - continue - } - return fmt.Errorf("eglGetPlatformDisplayEXT failed: %v", eglErr()) - } - - if ret, _, _ := eglInitialize.Call(display, 0, 0); ret == 0 { - if !lastTry { - continue - } - return fmt.Errorf("eglInitialize failed: %v", eglErr()) - } - } - - eglBindAPI.Call(_EGL_OPENGL_ES_API) - if err := eglErr(); err != nil { - return err - } - - var numConfigs eglInt - var config eglConfig - ret, _, _ := eglChooseConfig.Call( - display, - uintptr(unsafe.Pointer(&rgb888[0])), - uintptr(unsafe.Pointer(&config)), - 1, - uintptr(unsafe.Pointer(&numConfigs)), - ) - if ret == 0 { - return fmt.Errorf("eglChooseConfig failed: %v", eglErr()) - } - if numConfigs <= 0 { - return errors.New("eglChooseConfig found no valid config") - } - - surface, _, _ := eglCreateWindowSurface.Call(display, uintptr(config), uintptr(hwnd), 0, 0) - if surface == _EGL_NO_SURFACE { - return fmt.Errorf("eglCreateWindowSurface failed: %v", eglErr()) - } - - contextAttribs := [...]eglInt{ - _EGL_CONTEXT_CLIENT_VERSION, 2, - _EGL_NONE, - } - context, _, _ := eglCreateContext.Call( - display, - uintptr(config), - _EGL_NO_CONTEXT, - uintptr(unsafe.Pointer(&contextAttribs[0])), - ) - if context == _EGL_NO_CONTEXT { - return fmt.Errorf("eglCreateContext failed: %v", eglErr()) - } - - eglSwapInterval.Call(display, 1) - - w.ctx = ctxWin32{ - ctx: context, - display: display, - surface: surface, - } - - return nil -} - -func surfaceCreate() error { - return errors.New("gldriver: surface creation not implemented on windows") -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/window.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/window.go deleted file mode 100644 index 82baf2c..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/window.go +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gldriver - -import ( - "image" - "image/color" - "image/draw" - "sync" - - "golang.org/x/exp/shiny/driver/internal/drawer" - "golang.org/x/exp/shiny/driver/internal/event" - "golang.org/x/exp/shiny/driver/internal/lifecycler" - "golang.org/x/exp/shiny/screen" - "golang.org/x/image/math/f64" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/gl" -) - -type windowImpl struct { - s *screenImpl - - // id is an OS-specific data structure for the window. - // - Cocoa: ScreenGLView* - // - X11: Window - // - Windows: win32.HWND - id uintptr - - // ctx is a C data structure for the GL context. - // - Cocoa: uintptr holding a NSOpenGLContext*. - // - X11: uintptr holding an EGLSurface. - // - Windows: ctxWin32 - ctx interface{} - - lifecycler lifecycler.State - // TODO: Delete the field below (and the useLifecycler constant), and use - // the field above for cocoa and win32. - lifecycleStage lifecycle.Stage // current stage - - event.Deque - publish chan struct{} - publishDone chan screen.PublishResult - drawDone chan struct{} - - // glctxMu is a mutex that enforces the atomicity of methods like - // Texture.Upload or Window.Draw that are conceptually one operation - // but are implemented by multiple OpenGL calls. OpenGL is a stateful - // API, so interleaving OpenGL calls from separate higher-level - // operations causes inconsistencies. - glctxMu sync.Mutex - glctx gl.Context - worker gl.Worker - // backBufferBound is whether the default Framebuffer, with ID 0, also - // known as the back buffer or the window's Framebuffer, is bound and its - // viewport is known to equal the window size. It can become false when we - // bind to a texture's Framebuffer or when the window size changes. - backBufferBound bool - - // szMu protects only sz. If you need to hold both glctxMu and szMu, the - // lock ordering is to lock glctxMu first (and unlock it last). - szMu sync.Mutex - sz size.Event -} - -// NextEvent implements the screen.EventDeque interface. -func (w *windowImpl) NextEvent() interface{} { - e := w.Deque.NextEvent() - if handleSizeEventsAtChannelReceive { - if sz, ok := e.(size.Event); ok { - w.glctxMu.Lock() - w.backBufferBound = false - w.szMu.Lock() - w.sz = sz - w.szMu.Unlock() - w.glctxMu.Unlock() - } - } - return e -} - -func (w *windowImpl) Release() { - // There are two ways a window can be closed: the Operating System or - // Desktop Environment can initiate (e.g. in response to a user clicking a - // red button), or the Go app can programatically close the window (by - // calling Window.Release). - // - // When the OS closes a window: - // - Cocoa: Obj-C's windowWillClose calls Go's windowClosing. - // - X11: the X11 server sends a WM_DELETE_WINDOW message. - // - Windows: TODO: implement and document this. - // - // This should send a lifecycle event (To: StageDead) to the Go app's event - // loop, which should respond by calling Window.Release (this method). - // Window.Release is where system resources are actually cleaned up. - // - // When Window.Release is called, the closeWindow call below: - // - Cocoa: calls Obj-C's performClose, which emulates the red button - // being clicked. (TODO: document how this actually cleans up - // resources??) - // - X11: calls C's XDestroyWindow. - // - Windows: TODO: implement and document this. - // - // On Cocoa, if these two approaches race, experiments suggest that the - // race is won by performClose (which is called serially on the main - // thread). Even if that isn't true, the windowWillClose handler is - // idempotent. - - theScreen.mu.Lock() - delete(theScreen.windows, w.id) - theScreen.mu.Unlock() - - closeWindow(w.id) -} - -func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { - originalSRMin := sr.Min - sr = sr.Intersect(src.Bounds()) - if sr.Empty() { - return - } - dp = dp.Add(sr.Min.Sub(originalSRMin)) - // TODO: keep a texture around for this purpose? - t, err := w.s.NewTexture(sr.Size()) - if err != nil { - panic(err) - } - t.Upload(image.Point{}, src, sr) - w.Draw(f64.Aff3{ - 1, 0, float64(dp.X), - 0, 1, float64(dp.Y), - }, t, t.Bounds(), draw.Src, nil) - t.Release() -} - -func useOp(glctx gl.Context, op draw.Op) { - if op == draw.Over { - glctx.Enable(gl.BLEND) - glctx.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) - } else { - glctx.Disable(gl.BLEND) - } -} - -func (w *windowImpl) bindBackBuffer() { - w.szMu.Lock() - sz := w.sz - w.szMu.Unlock() - - w.backBufferBound = true - w.glctx.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{Value: 0}) - w.glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx) -} - -func (w *windowImpl) fill(mvp f64.Aff3, src color.Color, op draw.Op) { - w.glctxMu.Lock() - defer w.glctxMu.Unlock() - - if !w.backBufferBound { - w.bindBackBuffer() - } - - doFill(w.s, w.glctx, mvp, src, op) -} - -func doFill(s *screenImpl, glctx gl.Context, mvp f64.Aff3, src color.Color, op draw.Op) { - useOp(glctx, op) - if !glctx.IsProgram(s.fill.program) { - p, err := compileProgram(glctx, fillVertexSrc, fillFragmentSrc) - if err != nil { - // TODO: initialize this somewhere else we can better handle the error. - panic(err.Error()) - } - s.fill.program = p - s.fill.pos = glctx.GetAttribLocation(p, "pos") - s.fill.mvp = glctx.GetUniformLocation(p, "mvp") - s.fill.color = glctx.GetUniformLocation(p, "color") - s.fill.quad = glctx.CreateBuffer() - - glctx.BindBuffer(gl.ARRAY_BUFFER, s.fill.quad) - glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW) - } - glctx.UseProgram(s.fill.program) - - writeAff3(glctx, s.fill.mvp, mvp) - - r, g, b, a := src.RGBA() - glctx.Uniform4f( - s.fill.color, - float32(r)/65535, - float32(g)/65535, - float32(b)/65535, - float32(a)/65535, - ) - - glctx.BindBuffer(gl.ARRAY_BUFFER, s.fill.quad) - glctx.EnableVertexAttribArray(s.fill.pos) - glctx.VertexAttribPointer(s.fill.pos, 2, gl.FLOAT, false, 0, 0) - - glctx.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - - glctx.DisableVertexAttribArray(s.fill.pos) -} - -func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { - minX := float64(dr.Min.X) - minY := float64(dr.Min.Y) - maxX := float64(dr.Max.X) - maxY := float64(dr.Max.Y) - w.fill(w.mvp( - minX, minY, - maxX, minY, - minX, maxY, - ), src, op) -} - -func (w *windowImpl) DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { - minX := float64(sr.Min.X) - minY := float64(sr.Min.Y) - maxX := float64(sr.Max.X) - maxY := float64(sr.Max.Y) - w.fill(w.mvp( - src2dst[0]*minX+src2dst[1]*minY+src2dst[2], - src2dst[3]*minX+src2dst[4]*minY+src2dst[5], - src2dst[0]*maxX+src2dst[1]*minY+src2dst[2], - src2dst[3]*maxX+src2dst[4]*minY+src2dst[5], - src2dst[0]*minX+src2dst[1]*maxY+src2dst[2], - src2dst[3]*minX+src2dst[4]*maxY+src2dst[5], - ), src, op) -} - -func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { - t := src.(*textureImpl) - sr = sr.Intersect(t.Bounds()) - if sr.Empty() { - return - } - - w.glctxMu.Lock() - defer w.glctxMu.Unlock() - - if !w.backBufferBound { - w.bindBackBuffer() - } - - useOp(w.glctx, op) - w.glctx.UseProgram(w.s.texture.program) - - // Start with src-space left, top, right and bottom. - srcL := float64(sr.Min.X) - srcT := float64(sr.Min.Y) - srcR := float64(sr.Max.X) - srcB := float64(sr.Max.Y) - // Transform to dst-space via the src2dst matrix, then to a MVP matrix. - writeAff3(w.glctx, w.s.texture.mvp, w.mvp( - src2dst[0]*srcL+src2dst[1]*srcT+src2dst[2], - src2dst[3]*srcL+src2dst[4]*srcT+src2dst[5], - src2dst[0]*srcR+src2dst[1]*srcT+src2dst[2], - src2dst[3]*srcR+src2dst[4]*srcT+src2dst[5], - src2dst[0]*srcL+src2dst[1]*srcB+src2dst[2], - src2dst[3]*srcL+src2dst[4]*srcB+src2dst[5], - )) - - // OpenGL's fragment shaders' UV coordinates run from (0,0)-(1,1), - // unlike vertex shaders' XY coordinates running from (-1,+1)-(+1,-1). - // - // We are drawing a rectangle PQRS, defined by two of its - // corners, onto the entire texture. The two quads may actually - // be equal, but in the general case, PQRS can be smaller. - // - // (0,0) +---------------+ (1,0) - // | P +-----+ Q | - // | | | | - // | S +-----+ R | - // (0,1) +---------------+ (1,1) - // - // The PQRS quad is always axis-aligned. First of all, convert - // from pixel space to texture space. - tw := float64(t.size.X) - th := float64(t.size.Y) - px := float64(sr.Min.X-0) / tw - py := float64(sr.Min.Y-0) / th - qx := float64(sr.Max.X-0) / tw - sy := float64(sr.Max.Y-0) / th - // Due to axis alignment, qy = py and sx = px. - // - // The simultaneous equations are: - // 0 + 0 + a02 = px - // 0 + 0 + a12 = py - // a00 + 0 + a02 = qx - // a10 + 0 + a12 = qy = py - // 0 + a01 + a02 = sx = px - // 0 + a11 + a12 = sy - writeAff3(w.glctx, w.s.texture.uvp, f64.Aff3{ - qx - px, 0, px, - 0, sy - py, py, - }) - - w.glctx.ActiveTexture(gl.TEXTURE0) - w.glctx.BindTexture(gl.TEXTURE_2D, t.id) - w.glctx.Uniform1i(w.s.texture.sample, 0) - - w.glctx.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quad) - w.glctx.EnableVertexAttribArray(w.s.texture.pos) - w.glctx.VertexAttribPointer(w.s.texture.pos, 2, gl.FLOAT, false, 0, 0) - - w.glctx.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quad) - w.glctx.EnableVertexAttribArray(w.s.texture.inUV) - w.glctx.VertexAttribPointer(w.s.texture.inUV, 2, gl.FLOAT, false, 0, 0) - - w.glctx.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) - - w.glctx.DisableVertexAttribArray(w.s.texture.pos) - w.glctx.DisableVertexAttribArray(w.s.texture.inUV) -} - -func (w *windowImpl) Copy(dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { - drawer.Copy(w, dp, src, sr, op, opts) -} - -func (w *windowImpl) Scale(dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { - drawer.Scale(w, dr, src, sr, op, opts) -} - -func (w *windowImpl) mvp(tlx, tly, trx, try, blx, bly float64) f64.Aff3 { - w.szMu.Lock() - sz := w.sz - w.szMu.Unlock() - - return calcMVP(sz.WidthPx, sz.HeightPx, tlx, tly, trx, try, blx, bly) -} - -// calcMVP returns the Model View Projection matrix that maps the quadCoords -// unit square, (0, 0) to (1, 1), to a quad QV, such that QV in vertex shader -// space corresponds to the quad QP in pixel space, where QP is defined by -// three of its four corners - the arguments to this function. The three -// corners are nominally the top-left, top-right and bottom-left, but there is -// no constraint that e.g. tlx < trx. -// -// In pixel space, the window ranges from (0, 0) to (widthPx, heightPx). The -// Y-axis points downwards. -// -// In vertex shader space, the window ranges from (-1, +1) to (+1, -1), which -// is a 2-unit by 2-unit square. The Y-axis points upwards. -func calcMVP(widthPx, heightPx int, tlx, tly, trx, try, blx, bly float64) f64.Aff3 { - // Convert from pixel coords to vertex shader coords. - invHalfWidth := +2 / float64(widthPx) - invHalfHeight := -2 / float64(heightPx) - tlx = tlx*invHalfWidth - 1 - tly = tly*invHalfHeight + 1 - trx = trx*invHalfWidth - 1 - try = try*invHalfHeight + 1 - blx = blx*invHalfWidth - 1 - bly = bly*invHalfHeight + 1 - - // The resultant affine matrix: - // - maps (0, 0) to (tlx, tly). - // - maps (1, 0) to (trx, try). - // - maps (0, 1) to (blx, bly). - return f64.Aff3{ - trx - tlx, blx - tlx, tlx, - try - tly, bly - tly, tly, - } -} - -func (w *windowImpl) Publish() screen.PublishResult { - // gl.Flush is a lightweight (on modern GL drivers) blocking call - // that ensures all GL functions pending in the gl package have - // been passed onto the GL driver before the app package attempts - // to swap the screen buffer. - // - // This enforces that the final receive (for this paint cycle) on - // gl.WorkAvailable happens before the send on publish. - w.glctxMu.Lock() - w.glctx.Flush() - w.glctxMu.Unlock() - - w.publish <- struct{}{} - res := <-w.publishDone - - select { - case w.drawDone <- struct{}{}: - default: - } - - return res -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.c b/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.c deleted file mode 100644 index e7fb289..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.c +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build linux,!android openbsd - -#include "_cgo_export.h" -#include -#include // for Atom, Colormap, Display, Window -#include // for XVisualInfo -#include -#include -#include - -Atom net_wm_name; -Atom utf8_string; -Atom wm_delete_window; -Atom wm_protocols; -Atom wm_take_focus; - -EGLConfig e_config; -EGLContext e_ctx; -EGLDisplay e_dpy; -Colormap x_colormap; -Display *x_dpy; -XVisualInfo *x_visual_info; -Window x_root; - -// TODO: share code with eglErrString -char * -eglGetErrorStr() { - switch (eglGetError()) { - case EGL_SUCCESS: - return "EGL_SUCCESS"; - case EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED"; - case EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS"; - case EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE"; - case EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG"; - case EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT"; - case EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY"; - case EGL_BAD_MATCH: - return "EGL_BAD_MATCH"; - case EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW"; - case EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER"; - case EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE"; - case EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST"; - } - return "unknown EGL error"; -} - -void -startDriver() { - x_dpy = XOpenDisplay(NULL); - if (!x_dpy) { - fprintf(stderr, "XOpenDisplay failed\n"); - exit(1); - } - e_dpy = eglGetDisplay(x_dpy); - if (!e_dpy) { - fprintf(stderr, "eglGetDisplay failed: %s\n", eglGetErrorStr()); - exit(1); - } - EGLint e_major, e_minor; - if (!eglInitialize(e_dpy, &e_major, &e_minor)) { - fprintf(stderr, "eglInitialize failed: %s\n", eglGetErrorStr()); - exit(1); - } - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "eglBindAPI failed: %s\n", eglGetErrorStr()); - exit(1); - } - - static const EGLint attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_NONE - }; - EGLint num_configs; - if (!eglChooseConfig(e_dpy, attribs, &e_config, 1, &num_configs)) { - fprintf(stderr, "eglChooseConfig failed: %s\n", eglGetErrorStr()); - exit(1); - } - EGLint vid; - if (!eglGetConfigAttrib(e_dpy, e_config, EGL_NATIVE_VISUAL_ID, &vid)) { - fprintf(stderr, "eglGetConfigAttrib failed: %s\n", eglGetErrorStr()); - exit(1); - } - - XVisualInfo visTemplate; - visTemplate.visualid = vid; - int num_visuals; - x_visual_info = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); - if (!x_visual_info) { - fprintf(stderr, "XGetVisualInfo failed\n"); - exit(1); - } - - x_root = RootWindow(x_dpy, DefaultScreen(x_dpy)); - x_colormap = XCreateColormap(x_dpy, x_root, x_visual_info->visual, AllocNone); - if (!x_colormap) { - fprintf(stderr, "XCreateColormap failed\n"); - exit(1); - } - - static const EGLint ctx_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - e_ctx = eglCreateContext(e_dpy, e_config, EGL_NO_CONTEXT, ctx_attribs); - if (!e_ctx) { - fprintf(stderr, "eglCreateContext failed: %s\n", eglGetErrorStr()); - exit(1); - } - - net_wm_name = XInternAtom(x_dpy, "_NET_WM_NAME", False); - utf8_string = XInternAtom(x_dpy, "UTF8_STRING", False); - wm_delete_window = XInternAtom(x_dpy, "WM_DELETE_WINDOW", False); - wm_protocols = XInternAtom(x_dpy, "WM_PROTOCOLS", False); - wm_take_focus = XInternAtom(x_dpy, "WM_TAKE_FOCUS", False); - - const int key_lo = 8; - const int key_hi = 255; - int keysyms_per_keycode; - KeySym *keysyms = XGetKeyboardMapping(x_dpy, key_lo, key_hi-key_lo+1, &keysyms_per_keycode); - if (keysyms_per_keycode < 2) { - fprintf(stderr, "XGetKeyboardMapping returned too few keysyms per keycode: %d\n", keysyms_per_keycode); - exit(1); - } - int k; - for (k = key_lo; k <= key_hi; k++) { - onKeysym(k, - keysyms[(k-key_lo)*keysyms_per_keycode + 0], - keysyms[(k-key_lo)*keysyms_per_keycode + 1]); - } - //TODO: use GetModifierMapping to figure out which modifier is the numlock modifier. -} - -void -processEvents() { - while (XPending(x_dpy)) { - XEvent ev; - XNextEvent(x_dpy, &ev); - switch (ev.type) { - case KeyPress: - case KeyRelease: - onKey(ev.xkey.window, ev.xkey.state, ev.xkey.keycode, ev.type == KeyPress ? 1 : 2); - break; - case ButtonPress: - case ButtonRelease: - onMouse(ev.xbutton.window, ev.xbutton.x, ev.xbutton.y, ev.xbutton.state, ev.xbutton.button, - ev.type == ButtonPress ? 1 : 2); - break; - case MotionNotify: - onMouse(ev.xmotion.window, ev.xmotion.x, ev.xmotion.y, ev.xmotion.state, 0, 0); - break; - case FocusIn: - case FocusOut: - onFocus(ev.xmotion.window, ev.type == FocusIn); - break; - case Expose: - // A non-zero Count means that there are more expose events coming. For - // example, a non-rectangular exposure (e.g. from a partially overlapped - // window) will result in multiple expose events whose dirty rectangles - // combine to define the dirty region. Go's paint events do not provide - // dirty regions, so we only pass on the final X11 expose event. - if (ev.xexpose.count == 0) { - onExpose(ev.xexpose.window); - } - break; - case ConfigureNotify: - onConfigure(ev.xconfigure.window, ev.xconfigure.x, ev.xconfigure.y, - ev.xconfigure.width, ev.xconfigure.height, - DisplayWidth(x_dpy, DefaultScreen(x_dpy)), - DisplayWidthMM(x_dpy, DefaultScreen(x_dpy))); - break; - case ClientMessage: - if ((ev.xclient.message_type != wm_protocols) || (ev.xclient.format != 32)) { - break; - } - Atom a = ev.xclient.data.l[0]; - if (a == wm_delete_window) { - onDeleteWindow(ev.xclient.window); - } else if (a == wm_take_focus) { - XSetInputFocus(x_dpy, ev.xclient.window, RevertToParent, ev.xclient.data.l[1]); - } - break; - } - } -} - -void -makeCurrent(uintptr_t surface) { - EGLSurface surf = (EGLSurface)(surface); - if (!eglMakeCurrent(e_dpy, surf, surf, e_ctx)) { - fprintf(stderr, "eglMakeCurrent failed: %s\n", eglGetErrorStr()); - exit(1); - } -} - -void -swapBuffers(uintptr_t surface) { - EGLSurface surf = (EGLSurface)(surface); - if (!eglSwapBuffers(e_dpy, surf)) { - fprintf(stderr, "eglSwapBuffers failed: %s\n", eglGetErrorStr()); - exit(1); - } -} - -void -doCloseWindow(uintptr_t id) { - Window win = (Window)(id); - XDestroyWindow(x_dpy, win); -} - -uintptr_t -doNewWindow(int width, int height, char* title, int title_len) { - XSetWindowAttributes attr; - attr.colormap = x_colormap; - attr.event_mask = - KeyPressMask | - KeyReleaseMask | - ButtonPressMask | - ButtonReleaseMask | - PointerMotionMask | - ExposureMask | - StructureNotifyMask | - FocusChangeMask; - - Window win = XCreateWindow( - x_dpy, x_root, 0, 0, width, height, 0, x_visual_info->depth, InputOutput, - x_visual_info->visual, CWColormap | CWEventMask, &attr); - - XSizeHints sizehints; - sizehints.width = width; - sizehints.height = height; - sizehints.flags = USSize; - XSetNormalHints(x_dpy, win, &sizehints); - - Atom atoms[2]; - atoms[0] = wm_delete_window; - atoms[1] = wm_take_focus; - XSetWMProtocols(x_dpy, win, atoms, 2); - - XSetStandardProperties(x_dpy, win, "", "App", None, (char **)NULL, 0, &sizehints); - XChangeProperty(x_dpy, win, net_wm_name, utf8_string, 8, PropModeReplace, title, title_len); - - return win; -} - -uintptr_t -doShowWindow(uintptr_t id) { - Window win = (Window)(id); - XMapWindow(x_dpy, win); - EGLSurface surf = eglCreateWindowSurface(e_dpy, e_config, win, NULL); - if (!surf) { - fprintf(stderr, "eglCreateWindowSurface failed: %s\n", eglGetErrorStr()); - exit(1); - } - return (uintptr_t)(surf); -} - -uintptr_t -surfaceCreate() { - static const EGLint ctx_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - EGLContext ctx = eglCreateContext(e_dpy, e_config, EGL_NO_CONTEXT, ctx_attribs); - if (!ctx) { - fprintf(stderr, "surface eglCreateContext failed: %s\n", eglGetErrorStr()); - return 0; - } - - static const EGLint cfg_attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_NONE - }; - EGLConfig cfg; - EGLint num_configs; - if (!eglChooseConfig(e_dpy, cfg_attribs, &cfg, 1, &num_configs)) { - fprintf(stderr, "gldriver: surface eglChooseConfig failed: %s\n", eglGetErrorStr()); - return 0; - } - - // TODO: use the size of the monitor as a bound for texture size. - static const EGLint attribs[] = { - EGL_WIDTH, 4096, - EGL_HEIGHT, 3072, - EGL_NONE - }; - EGLSurface surface = eglCreatePbufferSurface(e_dpy, cfg, attribs); - if (!surface) { - fprintf(stderr, "gldriver: surface eglCreatePbufferSurface failed: %s\n", eglGetErrorStr()); - return 0; - } - - if (!eglMakeCurrent(e_dpy, surface, surface, ctx)) { - fprintf(stderr, "gldriver: surface eglMakeCurrent failed: %s\n", eglGetErrorStr()); - return 0; - } - - return (uintptr_t)surface; -} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.go deleted file mode 100644 index 4847e85..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.go +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (linux && !android) || openbsd -// +build linux,!android openbsd - -package gldriver - -/* -#cgo linux LDFLAGS: -lEGL -lGLESv2 -lX11 -#cgo openbsd LDFLAGS: -L/usr/X11R6/lib/ -lEGL -lGLESv2 -lX11 - -#cgo openbsd CFLAGS: -I/usr/X11R6/include/ - -#include -#include -#include - -char *eglGetErrorStr(); -void startDriver(); -void processEvents(); -void makeCurrent(uintptr_t ctx); -void swapBuffers(uintptr_t ctx); -void doCloseWindow(uintptr_t id); -uintptr_t doNewWindow(int width, int height, char* title, int title_len); -uintptr_t doShowWindow(uintptr_t id); -uintptr_t surfaceCreate(); -*/ -import "C" -import ( - "errors" - "runtime" - "time" - "unsafe" - - "golang.org/x/exp/shiny/driver/internal/x11key" - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/event/key" - "golang.org/x/mobile/event/mouse" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/geom" - "golang.org/x/mobile/gl" -) - -const useLifecycler = true - -const handleSizeEventsAtChannelReceive = true - -var theKeysyms x11key.KeysymTable - -func init() { - // It might not be necessary, but it probably doesn't hurt to try to make - // 'the main thread' be 'the X11 / OpenGL thread'. - runtime.LockOSThread() -} - -func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { - width, height := optsSize(opts) - - title := opts.GetTitle() - ctitle := C.CString(title) - defer C.free(unsafe.Pointer(ctitle)) - - retc := make(chan uintptr) - uic <- uiClosure{ - f: func() uintptr { - return uintptr(C.doNewWindow(C.int(width), C.int(height), ctitle, C.int(len(title)))) - }, - retc: retc, - } - return <-retc, nil -} - -func initWindow(w *windowImpl) { - w.glctx, w.worker = glctx, worker -} - -func showWindow(w *windowImpl) { - retc := make(chan uintptr) - uic <- uiClosure{ - f: func() uintptr { - return uintptr(C.doShowWindow(C.uintptr_t(w.id))) - }, - retc: retc, - } - w.ctx = <-retc - go drawLoop(w) -} - -func closeWindow(id uintptr) { - uic <- uiClosure{ - f: func() uintptr { - C.doCloseWindow(C.uintptr_t(id)) - return 0 - }, - } -} - -func drawLoop(w *windowImpl) { - glcontextc <- w.ctx.(uintptr) - go func() { - for range w.publish { - publishc <- w - } - }() -} - -var ( - glcontextc = make(chan uintptr) - publishc = make(chan *windowImpl) - uic = make(chan uiClosure) - - // TODO: don't assume that there is only one window, and hence only - // one (global) GL context. - // - // TODO: should we be able to make a shiny.Texture before having a - // shiny.Window's GL context? Should something like gl.IsProgram be a - // method instead of a function, and have each shiny.Window have its own - // gl.Context? - glctx gl.Context - worker gl.Worker -) - -// uiClosure is a closure to be run on C's UI thread. -type uiClosure struct { - f func() uintptr - retc chan uintptr -} - -func main(f func(screen.Screen)) error { - if gl.Version() == "GL_ES_2_0" { - return errors.New("gldriver: ES 3 required on X11") - } - C.startDriver() - glctx, worker = gl.NewContext() - - closec := make(chan struct{}) - go func() { - f(theScreen) - close(closec) - }() - - // heartbeat is a channel that, at regular intervals, directs the select - // below to also consider X11 events, not just Go events (channel - // communications). - // - // TODO: select instead of poll. Note that knowing whether to call - // C.processEvents needs to select on a file descriptor, and the other - // cases below select on Go channels. - heartbeat := time.NewTicker(time.Second / 60) - workAvailable := worker.WorkAvailable() - - for { - select { - case <-closec: - return nil - case ctx := <-glcontextc: - // TODO: do we need to synchronize with seeing a size event for - // this window's context before or after calling makeCurrent? - // Otherwise, are we racing with the gl.Viewport call? I've - // occasionally seen a stale viewport, if the window manager sets - // the window width and height to something other than that - // requested by XCreateWindow, but it's not easily reproducible. - C.makeCurrent(C.uintptr_t(ctx)) - case w := <-publishc: - C.swapBuffers(C.uintptr_t(w.ctx.(uintptr))) - w.publishDone <- screen.PublishResult{} - case req := <-uic: - ret := req.f() - if req.retc != nil { - req.retc <- ret - } - case <-heartbeat.C: - C.processEvents() - case <-workAvailable: - worker.DoWork() - } - } -} - -//export onExpose -func onExpose(id uintptr) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - - w.Send(paint.Event{External: true}) -} - -//export onKeysym -func onKeysym(k, unshifted, shifted uint32) { - theKeysyms.Table[k][0] = unshifted - theKeysyms.Table[k][1] = shifted -} - -//export onKey -func onKey(id uintptr, state uint16, detail, dir uint8) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - - r, c := theKeysyms.Lookup(detail, state) - w.Send(key.Event{ - Rune: r, - Code: c, - Modifiers: x11key.KeyModifiers(state), - Direction: key.Direction(dir), - }) -} - -//export onMouse -func onMouse(id uintptr, x, y int32, state uint16, button, dir uint8) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - - // TODO: should a mouse.Event have a separate MouseModifiers field, for - // which buttons are pressed during a mouse move? - btn := mouse.Button(button) - switch btn { - case 4: - btn = mouse.ButtonWheelUp - case 5: - btn = mouse.ButtonWheelDown - case 6: - btn = mouse.ButtonWheelLeft - case 7: - btn = mouse.ButtonWheelRight - } - if btn.IsWheel() { - if dir != uint8(mouse.DirPress) { - return - } - dir = uint8(mouse.DirStep) - } - w.Send(mouse.Event{ - X: float32(x), - Y: float32(y), - Button: btn, - Modifiers: x11key.KeyModifiers(state), - Direction: mouse.Direction(dir), - }) -} - -//export onFocus -func onFocus(id uintptr, focused bool) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - - w.lifecycler.SetFocused(focused) - w.lifecycler.SendEvent(w, w.glctx) -} - -//export onConfigure -func onConfigure(id uintptr, x, y, width, height, displayWidth, displayWidthMM int32) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - - w.lifecycler.SetVisible(x+width > 0 && y+height > 0) - w.lifecycler.SendEvent(w, w.glctx) - - const ( - mmPerInch = 25.4 - ptPerInch = 72 - ) - pixelsPerMM := float32(displayWidth) / float32(displayWidthMM) - w.Send(size.Event{ - WidthPx: int(width), - HeightPx: int(height), - WidthPt: geom.Pt(width), - HeightPt: geom.Pt(height), - PixelsPerPt: pixelsPerMM * mmPerInch / ptPerInch, - }) -} - -//export onDeleteWindow -func onDeleteWindow(id uintptr) { - theScreen.mu.Lock() - w := theScreen.windows[id] - theScreen.mu.Unlock() - - if w == nil { - return - } - - w.lifecycler.SetDead(true) - w.lifecycler.SendEvent(w, w.glctx) -} - -func surfaceCreate() error { - if C.surfaceCreate() == 0 { - return errors.New("gldriver: surface creation failed") - } - return nil -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/drawer/drawer.go b/vendor/golang.org/x/exp/shiny/driver/internal/drawer/drawer.go deleted file mode 100644 index 230a174..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/drawer/drawer.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package drawer provides functions that help implement screen.Drawer methods. -package drawer // import "golang.org/x/exp/shiny/driver/internal/drawer" - -import ( - "image" - "image/draw" - - "golang.org/x/exp/shiny/screen" - "golang.org/x/image/math/f64" -) - -// Copy implements the Copy method of the screen.Drawer interface by calling -// the Draw method of that same interface. -func Copy(dst screen.Drawer, dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { - dst.Draw(f64.Aff3{ - 1, 0, float64(dp.X - sr.Min.X), - 0, 1, float64(dp.Y - sr.Min.Y), - }, src, sr, op, opts) -} - -// Scale implements the Scale method of the screen.Drawer interface by calling -// the Draw method of that same interface. -func Scale(dst screen.Drawer, dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { - rx := float64(dr.Dx()) / float64(sr.Dx()) - ry := float64(dr.Dy()) / float64(sr.Dy()) - dst.Draw(f64.Aff3{ - rx, 0, float64(dr.Min.X) - rx*float64(sr.Min.X), - 0, ry, float64(dr.Min.Y) - ry*float64(sr.Min.Y), - }, src, sr, op, opts) -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/errscreen/errscreen.go b/vendor/golang.org/x/exp/shiny/driver/internal/errscreen/errscreen.go deleted file mode 100644 index 97f9773..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/errscreen/errscreen.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package errscreen provides a stub Screen implementation. -package errscreen // import "golang.org/x/exp/shiny/driver/internal/errscreen" - -import ( - "image" - - "golang.org/x/exp/shiny/screen" -) - -// Stub returns a Screen whose methods all return the given error. -func Stub(err error) screen.Screen { - return stub{err} -} - -type stub struct { - err error -} - -func (s stub) NewBuffer(size image.Point) (screen.Buffer, error) { return nil, s.err } -func (s stub) NewTexture(size image.Point) (screen.Texture, error) { return nil, s.err } -func (s stub) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) { return nil, s.err } diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/event/event.go b/vendor/golang.org/x/exp/shiny/driver/internal/event/event.go deleted file mode 100644 index 686a123..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/event/event.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package event provides an infinitely buffered double-ended queue of events. -package event // import "golang.org/x/exp/shiny/driver/internal/event" - -import ( - "sync" -) - -// Deque is an infinitely buffered double-ended queue of events. The zero value -// is usable, but a Deque value must not be copied. -type Deque struct { - mu sync.Mutex - cond sync.Cond // cond.L is lazily initialized to &Deque.mu. - back []interface{} // FIFO. - front []interface{} // LIFO. -} - -func (q *Deque) lockAndInit() { - q.mu.Lock() - if q.cond.L == nil { - q.cond.L = &q.mu - } -} - -// NextEvent implements the screen.EventDeque interface. -func (q *Deque) NextEvent() interface{} { - q.lockAndInit() - defer q.mu.Unlock() - - for { - if n := len(q.front); n > 0 { - e := q.front[n-1] - q.front[n-1] = nil - q.front = q.front[:n-1] - return e - } - - if n := len(q.back); n > 0 { - e := q.back[0] - q.back[0] = nil - q.back = q.back[1:] - return e - } - - q.cond.Wait() - } -} - -// Send implements the screen.EventDeque interface. -func (q *Deque) Send(event interface{}) { - q.lockAndInit() - defer q.mu.Unlock() - - q.back = append(q.back, event) - q.cond.Signal() -} - -// SendFirst implements the screen.EventDeque interface. -func (q *Deque) SendFirst(event interface{}) { - q.lockAndInit() - defer q.mu.Unlock() - - q.front = append(q.front, event) - q.cond.Signal() -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/lifecycler/lifecycler.go b/vendor/golang.org/x/exp/shiny/driver/internal/lifecycler/lifecycler.go deleted file mode 100644 index 53d3543..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/lifecycler/lifecycler.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package lifecycler tracks a window's lifecycle state. -// -// It eliminates sending redundant lifecycle events, ones where the From and To -// stages are equal. For example, moving a window from one part of the screen -// to another should not send multiple events from StageVisible to -// StageVisible, even though the underlying window system's message might only -// hold the new position, and not whether the window was previously visible. -package lifecycler // import "golang.org/x/exp/shiny/driver/internal/lifecycler" - -import ( - "sync" - - "golang.org/x/mobile/event/lifecycle" -) - -// State is a window's lifecycle state. -type State struct { - mu sync.Mutex - stage lifecycle.Stage - dead bool - focused bool - visible bool -} - -func (s *State) SetDead(b bool) { - s.mu.Lock() - s.dead = b - s.mu.Unlock() -} - -func (s *State) SetFocused(b bool) { - s.mu.Lock() - s.focused = b - s.mu.Unlock() -} - -func (s *State) SetVisible(b bool) { - s.mu.Lock() - s.visible = b - s.mu.Unlock() -} - -func (s *State) SendEvent(r Sender, drawContext interface{}) { - s.mu.Lock() - from, to := s.stage, lifecycle.StageAlive - // The order of these if's is important. For example, once a window becomes - // StageDead, it should never change stage again. - // - // Similarly, focused trumps visible. It's hard to imagine a situation - // where a window is focused and not visible on screen, but in that - // unlikely case, StageFocused seems the most appropriate stage. - if s.dead { - to = lifecycle.StageDead - } else if s.focused { - to = lifecycle.StageFocused - } else if s.visible { - to = lifecycle.StageVisible - } - s.stage = to - s.mu.Unlock() - - if from != to { - r.Send(lifecycle.Event{ - From: from, - To: to, - - // TODO: does shiny use this at all? - DrawContext: drawContext, - }) - } -} - -// Sender is who to send the lifecycle event to. -type Sender interface { - Send(event interface{}) -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/key.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/key.go deleted file mode 100644 index a5748c3..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/win32/key.go +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -package win32 - -import ( - "fmt" - "syscall" - "unicode/utf16" - - "golang.org/x/mobile/event/key" -) - -// convVirtualKeyCode converts a Win32 virtual key code number -// into the standard keycodes used by the key package. -func convVirtualKeyCode(vKey uint32) key.Code { - switch vKey { - case 0x01: // VK_LBUTTON left mouse button - case 0x02: // VK_RBUTTON right mouse button - case 0x03: // VK_CANCEL control-break processing - case 0x04: // VK_MBUTTON middle mouse button - case 0x05: // VK_XBUTTON1 X1 mouse button - case 0x06: // VK_XBUTTON2 X2 mouse button - case 0x08: // VK_BACK - return key.CodeDeleteBackspace - case 0x09: // VK_TAB - return key.CodeTab - case 0x0C: // VK_CLEAR - case 0x0D: // VK_RETURN - return key.CodeReturnEnter - case 0x10: // VK_SHIFT - return key.CodeLeftShift - case 0x11: // VK_CONTROL - return key.CodeLeftControl - case 0x12: // VK_MENU - return key.CodeLeftAlt - case 0x13: // VK_PAUSE - case 0x14: // VK_CAPITAL - return key.CodeCapsLock - case 0x15: // VK_KANA, VK_HANGUEL, VK_HANGUL - case 0x17: // VK_JUNJA - case 0x18: // VK_FINA, L - case 0x19: // VK_HANJA, VK_KANJI - case 0x1B: // VK_ESCAPE - return key.CodeEscape - case 0x1C: // VK_CONVERT - case 0x1D: // VK_NONCONVERT - case 0x1E: // VK_ACCEPT - case 0x1F: // VK_MODECHANGE - case 0x20: // VK_SPACE - return key.CodeSpacebar - case 0x21: // VK_PRIOR - return key.CodePageUp - case 0x22: // VK_NEXT - return key.CodePageDown - case 0x23: // VK_END - return key.CodeEnd - case 0x24: // VK_HOME - return key.CodeHome - case 0x25: // VK_LEFT - return key.CodeLeftArrow - case 0x26: // VK_UP - return key.CodeUpArrow - case 0x27: // VK_RIGHT - return key.CodeRightArrow - case 0x28: // VK_DOWN - return key.CodeDownArrow - case 0x29: // VK_SELECT - case 0x2A: // VK_PRINT - case 0x2B: // VK_EXECUTE - case 0x2C: // VK_SNAPSHOT - case 0x2D: // VK_INSERT - case 0x2E: // VK_DELETE - return key.CodeDeleteForward - case 0x2F: // VK_HELP - return key.CodeHelp - case 0x30: - return key.Code0 - case 0x31: - return key.Code1 - case 0x32: - return key.Code2 - case 0x33: - return key.Code3 - case 0x34: - return key.Code4 - case 0x35: - return key.Code5 - case 0x36: - return key.Code6 - case 0x37: - return key.Code7 - case 0x38: - return key.Code8 - case 0x39: - return key.Code9 - case 0x41: - return key.CodeA - case 0x42: - return key.CodeB - case 0x43: - return key.CodeC - case 0x44: - return key.CodeD - case 0x45: - return key.CodeE - case 0x46: - return key.CodeF - case 0x47: - return key.CodeG - case 0x48: - return key.CodeH - case 0x49: - return key.CodeI - case 0x4A: - return key.CodeJ - case 0x4B: - return key.CodeK - case 0x4C: - return key.CodeL - case 0x4D: - return key.CodeM - case 0x4E: - return key.CodeN - case 0x4F: - return key.CodeO - case 0x50: - return key.CodeP - case 0x51: - return key.CodeQ - case 0x52: - return key.CodeR - case 0x53: - return key.CodeS - case 0x54: - return key.CodeT - case 0x55: - return key.CodeU - case 0x56: - return key.CodeV - case 0x57: - return key.CodeW - case 0x58: - return key.CodeX - case 0x59: - return key.CodeY - case 0x5A: - return key.CodeZ - case 0x5B: // VK_LWIN - return key.CodeLeftGUI - case 0x5C: // VK_RWIN - return key.CodeRightGUI - case 0x5D: // VK_APPS - case 0x5F: // VK_SLEEP - case 0x60: // VK_NUMPAD0 - return key.CodeKeypad0 - case 0x61: // VK_NUMPAD1 - return key.CodeKeypad1 - case 0x62: // VK_NUMPAD2 - return key.CodeKeypad2 - case 0x63: // VK_NUMPAD3 - return key.CodeKeypad3 - case 0x64: // VK_NUMPAD4 - return key.CodeKeypad4 - case 0x65: // VK_NUMPAD5 - return key.CodeKeypad5 - case 0x66: // VK_NUMPAD6 - return key.CodeKeypad6 - case 0x67: // VK_NUMPAD7 - return key.CodeKeypad7 - case 0x68: // VK_NUMPAD8 - return key.CodeKeypad8 - case 0x69: // VK_NUMPAD9 - return key.CodeKeypad9 - case 0x6A: // VK_MULTIPLY - return key.CodeKeypadAsterisk - case 0x6B: // VK_ADD - return key.CodeKeypadPlusSign - case 0x6C: // VK_SEPARATOR - case 0x6D: // VK_SUBTRACT - return key.CodeKeypadHyphenMinus - case 0x6E: // VK_DECIMAL - return key.CodeFullStop - case 0x6F: // VK_DIVIDE - return key.CodeKeypadSlash - case 0x70: // VK_F1 - return key.CodeF1 - case 0x71: // VK_F2 - return key.CodeF2 - case 0x72: // VK_F3 - return key.CodeF3 - case 0x73: // VK_F4 - return key.CodeF4 - case 0x74: // VK_F5 - return key.CodeF5 - case 0x75: // VK_F6 - return key.CodeF6 - case 0x76: // VK_F7 - return key.CodeF7 - case 0x77: // VK_F8 - return key.CodeF8 - case 0x78: // VK_F9 - return key.CodeF9 - case 0x79: // VK_F10 - return key.CodeF10 - case 0x7A: // VK_F11 - return key.CodeF11 - case 0x7B: // VK_F12 - return key.CodeF12 - case 0x7C: // VK_F13 - return key.CodeF13 - case 0x7D: // VK_F14 - return key.CodeF14 - case 0x7E: // VK_F15 - return key.CodeF15 - case 0x7F: // VK_F16 - return key.CodeF16 - case 0x80: // VK_F17 - return key.CodeF17 - case 0x81: // VK_F18 - return key.CodeF18 - case 0x82: // VK_F19 - return key.CodeF19 - case 0x83: // VK_F20 - return key.CodeF20 - case 0x84: // VK_F21 - return key.CodeF21 - case 0x85: // VK_F22 - return key.CodeF22 - case 0x86: // VK_F23 - return key.CodeF23 - case 0x87: // VK_F24 - return key.CodeF24 - case 0x90: // VK_NUMLOCK - return key.CodeKeypadNumLock - case 0x91: // VK_SCROLL - case 0xA0: // VK_LSHIFT - return key.CodeLeftShift - case 0xA1: // VK_RSHIFT - return key.CodeRightShift - case 0xA2: // VK_LCONTROL - return key.CodeLeftControl - case 0xA3: // VK_RCONTROL - return key.CodeRightControl - case 0xA4: // VK_LMENU - case 0xA5: // VK_RMENU - case 0xA6: // VK_BROWSER_BACK - case 0xA7: // VK_BROWSER_FORWARD - case 0xA8: // VK_BROWSER_REFRESH - case 0xA9: // VK_BROWSER_STOP - case 0xAA: // VK_BROWSER_SEARCH - case 0xAB: // VK_BROWSER_FAVORITES - case 0xAC: // VK_BROWSER_HOME - case 0xAD: // VK_VOLUME_MUTE - return key.CodeMute - case 0xAE: // VK_VOLUME_DOWN - return key.CodeVolumeDown - case 0xAF: // VK_VOLUME_UP - return key.CodeVolumeUp - case 0xB0: // VK_MEDIA_NEXT_TRACK - case 0xB1: // VK_MEDIA_PREV_TRACK - case 0xB2: // VK_MEDIA_STOP - case 0xB3: // VK_MEDIA_PLAY_PAUSE - case 0xB4: // VK_LAUNCH_MAIL - case 0xB5: // VK_LAUNCH_MEDIA_SELECT - case 0xB6: // VK_LAUNCH_APP1 - case 0xB7: // VK_LAUNCH_APP2 - case 0xBA: // VK_OEM_1 ';:' - return key.CodeSemicolon - case 0xBB: // VK_OEM_PLUS '+' - return key.CodeEqualSign - case 0xBC: // VK_OEM_COMMA ',' - return key.CodeComma - case 0xBD: // VK_OEM_MINUS '-' - return key.CodeHyphenMinus - case 0xBE: // VK_OEM_PERIOD '.' - return key.CodeFullStop - case 0xBF: // VK_OEM_2 '/?' - return key.CodeSlash - case 0xC0: // VK_OEM_3 '`~' - return key.CodeGraveAccent - case 0xDB: // VK_OEM_4 '[{' - return key.CodeLeftSquareBracket - case 0xDC: // VK_OEM_5 '\|' - return key.CodeBackslash - case 0xDD: // VK_OEM_6 ']}' - return key.CodeRightSquareBracket - case 0xDE: // VK_OEM_7 'single-quote/double-quote' - return key.CodeApostrophe - case 0xDF: // VK_OEM_8 - return key.CodeUnknown - case 0xE2: // VK_OEM_102 - case 0xE5: // VK_PROCESSKEY - case 0xE7: // VK_PACKET - case 0xF6: // VK_ATTN - case 0xF7: // VK_CRSEL - case 0xF8: // VK_EXSEL - case 0xF9: // VK_EREOF - case 0xFA: // VK_PLAY - case 0xFB: // VK_ZOOM - case 0xFC: // VK_NONAME - case 0xFD: // VK_PA1 - case 0xFE: // VK_OEM_CLEAR - } - return key.CodeUnknown -} - -func readRune(vKey uint32, scanCode uint8) rune { - var ( - keystate [256]byte - buf [4]uint16 - ) - if err := _GetKeyboardState(&keystate[0]); err != nil { - panic(fmt.Sprintf("win32: %v", err)) - } - // TODO: cache GetKeyboardLayout result, update on WM_INPUTLANGCHANGE - layout := _GetKeyboardLayout(0) - ret := _ToUnicodeEx(vKey, uint32(scanCode), &keystate[0], &buf[0], int32(len(buf)), 0, layout) - if ret < 1 { - return -1 - } - return utf16.Decode(buf[:ret])[0] -} - -func sendKeyEvent(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - e := key.Event{ - Rune: readRune(uint32(wParam), uint8(lParam>>16)), - Code: convVirtualKeyCode(uint32(wParam)), - Modifiers: keyModifiers(), - } - switch uMsg { - case _WM_KEYDOWN, _WM_SYSKEYDOWN: - const prevMask = 1 << 30 - if repeat := lParam&prevMask == prevMask; repeat { - e.Direction = key.DirNone - } else { - e.Direction = key.DirPress - } - case _WM_KEYUP, _WM_SYSKEYUP: - e.Direction = key.DirRelease - default: - panic(fmt.Sprintf("win32: unexpected key message: %d", uMsg)) - } - - KeyEvent(hwnd, e) - return 0 -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall.go deleted file mode 100644 index 43366e9..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go - -package win32 diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall_windows.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall_windows.go deleted file mode 100644 index d71536d..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall_windows.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package win32 - -import ( - "syscall" -) - -type _COLORREF uint32 - -func _RGB(r, g, b byte) _COLORREF { - return _COLORREF(r) | _COLORREF(g)<<8 | _COLORREF(b)<<16 -} - -type _POINT struct { - X int32 - Y int32 -} - -type _RECT struct { - Left int32 - Top int32 - Right int32 - Bottom int32 -} - -type _MSG struct { - HWND syscall.Handle - Message uint32 - Wparam uintptr - Lparam uintptr - Time uint32 - Pt _POINT -} - -type _WNDCLASS struct { - Style uint32 - LpfnWndProc uintptr - CbClsExtra int32 - CbWndExtra int32 - HInstance syscall.Handle - HIcon syscall.Handle - HCursor syscall.Handle - HbrBackground syscall.Handle - LpszMenuName *uint16 - LpszClassName *uint16 -} - -type _WINDOWPOS struct { - HWND syscall.Handle - HWNDInsertAfter syscall.Handle - X int32 - Y int32 - Cx int32 - Cy int32 - Flags uint32 -} - -const ( - _WM_SETFOCUS = 7 - _WM_KILLFOCUS = 8 - _WM_PAINT = 15 - _WM_CLOSE = 16 - _WM_WINDOWPOSCHANGED = 71 - _WM_KEYDOWN = 256 - _WM_KEYUP = 257 - _WM_SYSKEYDOWN = 260 - _WM_SYSKEYUP = 261 - _WM_MOUSEMOVE = 512 - _WM_MOUSEWHEEL = 522 - _WM_LBUTTONDOWN = 513 - _WM_LBUTTONUP = 514 - _WM_RBUTTONDOWN = 516 - _WM_RBUTTONUP = 517 - _WM_MBUTTONDOWN = 519 - _WM_MBUTTONUP = 520 - _WM_USER = 0x0400 -) - -const ( - _WS_OVERLAPPED = 0x00000000 - _WS_CAPTION = 0x00C00000 - _WS_SYSMENU = 0x00080000 - _WS_THICKFRAME = 0x00040000 - _WS_MINIMIZEBOX = 0x00020000 - _WS_MAXIMIZEBOX = 0x00010000 - _WS_OVERLAPPEDWINDOW = _WS_OVERLAPPED | _WS_CAPTION | _WS_SYSMENU | _WS_THICKFRAME | _WS_MINIMIZEBOX | _WS_MAXIMIZEBOX -) - -const ( - _VK_SHIFT = 16 - _VK_CONTROL = 17 - _VK_MENU = 18 - _VK_LWIN = 0x5B - _VK_RWIN = 0x5C -) - -const ( - _MK_LBUTTON = 0x0001 - _MK_MBUTTON = 0x0010 - _MK_RBUTTON = 0x0002 -) - -const ( - _COLOR_BTNFACE = 15 -) - -const ( - _IDI_APPLICATION = 32512 - _IDC_ARROW = 32512 -) - -const ( - _CW_USEDEFAULT = 0x80000000 - 0x100000000 - - _SW_SHOWDEFAULT = 10 - - _HWND_MESSAGE = syscall.Handle(^uintptr(2)) // -3 - - _SWP_NOSIZE = 0x0001 -) - -const ( - _BI_RGB = 0 - _DIB_RGB_COLORS = 0 - - _AC_SRC_OVER = 0x00 - _AC_SRC_ALPHA = 0x01 - - _SRCCOPY = 0x00cc0020 - - _WHEEL_DELTA = 120 -) - -func _GET_X_LPARAM(lp uintptr) int32 { - return int32(_LOWORD(lp)) -} - -func _GET_Y_LPARAM(lp uintptr) int32 { - return int32(_HIWORD(lp)) -} - -func _GET_WHEEL_DELTA_WPARAM(lp uintptr) int16 { - return int16(_HIWORD(lp)) -} - -func _LOWORD(l uintptr) uint16 { - return uint16(uint32(l)) -} - -func _HIWORD(l uintptr) uint16 { - return uint16(uint32(l >> 16)) -} - -// notes to self -// UINT = uint32 -// callbacks = uintptr -// strings = *uint16 - -//sys GetDC(hwnd syscall.Handle) (dc syscall.Handle, err error) = user32.GetDC -//sys ReleaseDC(hwnd syscall.Handle, dc syscall.Handle) (err error) = user32.ReleaseDC -//sys sendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) = user32.SendMessageW - -//sys _CreateWindowEx(exstyle uint32, className *uint16, windowText *uint16, style uint32, x int32, y int32, width int32, height int32, parent syscall.Handle, menu syscall.Handle, hInstance syscall.Handle, lpParam uintptr) (hwnd syscall.Handle, err error) = user32.CreateWindowExW -//sys _DefWindowProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) = user32.DefWindowProcW -//sys _DestroyWindow(hwnd syscall.Handle) (err error) = user32.DestroyWindow -//sys _DispatchMessage(msg *_MSG) (ret int32) = user32.DispatchMessageW -//sys _GetClientRect(hwnd syscall.Handle, rect *_RECT) (err error) = user32.GetClientRect -//sys _GetWindowRect(hwnd syscall.Handle, rect *_RECT) (err error) = user32.GetWindowRect -//sys _GetKeyboardLayout(threadID uint32) (locale syscall.Handle) = user32.GetKeyboardLayout -//sys _GetKeyboardState(lpKeyState *byte) (err error) = user32.GetKeyboardState -//sys _GetKeyState(virtkey int32) (keystatus int16) = user32.GetKeyState -//sys _GetMessage(msg *_MSG, hwnd syscall.Handle, msgfiltermin uint32, msgfiltermax uint32) (ret int32, err error) [failretval==-1] = user32.GetMessageW -//sys _LoadCursor(hInstance syscall.Handle, cursorName uintptr) (cursor syscall.Handle, err error) = user32.LoadCursorW -//sys _LoadIcon(hInstance syscall.Handle, iconName uintptr) (icon syscall.Handle, err error) = user32.LoadIconW -//sys _MoveWindow(hwnd syscall.Handle, x int32, y int32, w int32, h int32, repaint bool) (err error) = user32.MoveWindow -//sys _PostMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult bool) = user32.PostMessageW -//sys _PostQuitMessage(exitCode int32) = user32.PostQuitMessage -//sys _RegisterClass(wc *_WNDCLASS) (atom uint16, err error) = user32.RegisterClassW -//sys _ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) = user32.ShowWindow -//sys _ScreenToClient(hwnd syscall.Handle, lpPoint *_POINT) (ok bool) = user32.ScreenToClient -//sys _ToUnicodeEx(wVirtKey uint32, wScanCode uint32, lpKeyState *byte, pwszBuff *uint16, cchBuff int32, wFlags uint32, dwhkl syscall.Handle) (ret int32) = user32.ToUnicodeEx -//sys _TranslateMessage(msg *_MSG) (done bool) = user32.TranslateMessage -//sys _UnregisterClass(lpClassName *uint16, hInstance syscall.Handle) (done bool) = user32.UnregisterClassW diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/win32.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/win32.go deleted file mode 100644 index 22a6013..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/win32/win32.go +++ /dev/null @@ -1,520 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -// Package win32 implements a partial shiny screen driver using the Win32 API. -// It provides window, lifecycle, key, and mouse management, but no drawing. -// That is left to windriver (using GDI) or gldriver (using DirectX via ANGLE). -package win32 // import "golang.org/x/exp/shiny/driver/internal/win32" - -import ( - "fmt" - "runtime" - "sync" - "syscall" - "unsafe" - - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/event/key" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/mouse" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/geom" -) - -// screenHWND is the handle to the "Screen window". -// The Screen window encapsulates all screen.Screen operations -// in an actual Windows window so they all run on the main thread. -// Since any messages sent to a window will be executed on the -// main thread, we can safely use the messages below. -var screenHWND syscall.Handle - -const ( - msgCreateWindow = _WM_USER + iota - msgMainCallback - msgShow - msgQuit - msgLast -) - -// userWM is used to generate private (WM_USER and above) window message IDs -// for use by screenWindowWndProc and windowWndProc. -type userWM struct { - sync.Mutex - id uint32 -} - -func (m *userWM) next() uint32 { - m.Lock() - if m.id == 0 { - m.id = msgLast - } - r := m.id - m.id++ - m.Unlock() - return r -} - -var currentUserWM userWM - -func newWindow(opts *screen.NewWindowOptions) (syscall.Handle, error) { - // TODO(brainman): convert windowClass to *uint16 once (in initWindowClass) - wcname, err := syscall.UTF16PtrFromString(windowClass) - if err != nil { - return 0, err - } - title, err := syscall.UTF16PtrFromString(opts.GetTitle()) - if err != nil { - return 0, err - } - hwnd, err := _CreateWindowEx(0, - wcname, title, - _WS_OVERLAPPEDWINDOW, - _CW_USEDEFAULT, _CW_USEDEFAULT, - _CW_USEDEFAULT, _CW_USEDEFAULT, - 0, 0, hThisInstance, 0) - if err != nil { - return 0, err - } - // TODO(andlabs): use proper nCmdShow - // TODO(andlabs): call UpdateWindow() - - return hwnd, nil -} - -// ResizeClientRect makes hwnd client rectangle opts.Width by opts.Height in size. -func ResizeClientRect(hwnd syscall.Handle, opts *screen.NewWindowOptions) error { - if opts == nil || opts.Width <= 0 || opts.Height <= 0 { - return nil - } - var cr, wr _RECT - err := _GetClientRect(hwnd, &cr) - if err != nil { - return err - } - err = _GetWindowRect(hwnd, &wr) - if err != nil { - return err - } - w := (wr.Right - wr.Left) - (cr.Right - int32(opts.Width)) - h := (wr.Bottom - wr.Top) - (cr.Bottom - int32(opts.Height)) - return _MoveWindow(hwnd, wr.Left, wr.Top, w, h, false) -} - -// Show shows a newly created window. -// It sends the appropriate lifecycle events, makes the window appear -// on the screen, and sends an initial size event. -// -// This is a separate step from NewWindow to give the driver a chance -// to setup its internal state for a window before events start being -// delivered. -func Show(hwnd syscall.Handle) { - SendMessage(hwnd, msgShow, 0, 0) -} - -func Release(hwnd syscall.Handle) { - SendMessage(hwnd, _WM_CLOSE, 0, 0) -} - -func sendFocus(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - switch uMsg { - case _WM_SETFOCUS: - LifecycleEvent(hwnd, lifecycle.StageFocused) - case _WM_KILLFOCUS: - LifecycleEvent(hwnd, lifecycle.StageVisible) - default: - panic(fmt.Sprintf("unexpected focus message: %d", uMsg)) - } - return _DefWindowProc(hwnd, uMsg, wParam, lParam) -} - -func sendShow(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - LifecycleEvent(hwnd, lifecycle.StageVisible) - _ShowWindow(hwnd, _SW_SHOWDEFAULT) - sendSize(hwnd) - return 0 -} - -func sendSizeEvent(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - wp := (*_WINDOWPOS)(unsafe.Pointer(lParam)) - if wp.Flags&_SWP_NOSIZE != 0 { - return 0 - } - sendSize(hwnd) - return 0 -} - -func sendSize(hwnd syscall.Handle) { - var r _RECT - if err := _GetClientRect(hwnd, &r); err != nil { - panic(err) // TODO(andlabs) - } - - width := int(r.Right - r.Left) - height := int(r.Bottom - r.Top) - - // TODO(andlabs): don't assume that PixelsPerPt == 1 - SizeEvent(hwnd, size.Event{ - WidthPx: width, - HeightPx: height, - WidthPt: geom.Pt(width), - HeightPt: geom.Pt(height), - PixelsPerPt: 1, - }) -} - -func sendClose(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - // TODO(ktye): DefWindowProc calls DestroyWindow by default. - // To intercept destruction of the window, return 0 and call - // DestroyWindow when appropriate. - LifecycleEvent(hwnd, lifecycle.StageDead) - return _DefWindowProc(hwnd, uMsg, wParam, lParam) -} - -func sendMouseEvent(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - e := mouse.Event{ - X: float32(_GET_X_LPARAM(lParam)), - Y: float32(_GET_Y_LPARAM(lParam)), - Modifiers: keyModifiers(), - } - - switch uMsg { - case _WM_MOUSEMOVE: - e.Direction = mouse.DirNone - case _WM_LBUTTONDOWN, _WM_MBUTTONDOWN, _WM_RBUTTONDOWN: - e.Direction = mouse.DirPress - case _WM_LBUTTONUP, _WM_MBUTTONUP, _WM_RBUTTONUP: - e.Direction = mouse.DirRelease - case _WM_MOUSEWHEEL: - // TODO: On a trackpad, a scroll can be a drawn-out affair with a - // distinct beginning and end. Should the intermediate events be - // DirNone? - e.Direction = mouse.DirStep - - // Convert from screen to window coordinates. - p := _POINT{ - int32(e.X), - int32(e.Y), - } - _ScreenToClient(hwnd, &p) - e.X = float32(p.X) - e.Y = float32(p.Y) - default: - panic("sendMouseEvent() called on non-mouse message") - } - - switch uMsg { - case _WM_MOUSEMOVE: - // No-op. - case _WM_LBUTTONDOWN, _WM_LBUTTONUP: - e.Button = mouse.ButtonLeft - case _WM_MBUTTONDOWN, _WM_MBUTTONUP: - e.Button = mouse.ButtonMiddle - case _WM_RBUTTONDOWN, _WM_RBUTTONUP: - e.Button = mouse.ButtonRight - case _WM_MOUSEWHEEL: - // TODO: handle horizontal scrolling - delta := _GET_WHEEL_DELTA_WPARAM(wParam) / _WHEEL_DELTA - switch { - case delta > 0: - e.Button = mouse.ButtonWheelUp - case delta < 0: - e.Button = mouse.ButtonWheelDown - delta = -delta - default: - return - } - for delta > 0 { - MouseEvent(hwnd, e) - delta-- - } - return - } - - MouseEvent(hwnd, e) - - return 0 -} - -// Precondition: this is called in immediate response to the message that triggered the event (so not after w.Send). -func keyModifiers() (m key.Modifiers) { - down := func(x int32) bool { - // GetKeyState gets the key state at the time of the message, so this is what we want. - return _GetKeyState(x)&0x80 != 0 - } - - if down(_VK_CONTROL) { - m |= key.ModControl - } - if down(_VK_MENU) { - m |= key.ModAlt - } - if down(_VK_SHIFT) { - m |= key.ModShift - } - if down(_VK_LWIN) || down(_VK_RWIN) { - m |= key.ModMeta - } - return m -} - -var ( - MouseEvent func(hwnd syscall.Handle, e mouse.Event) - PaintEvent func(hwnd syscall.Handle, e paint.Event) - SizeEvent func(hwnd syscall.Handle, e size.Event) - KeyEvent func(hwnd syscall.Handle, e key.Event) - LifecycleEvent func(hwnd syscall.Handle, e lifecycle.Stage) - - // TODO: use the golang.org/x/exp/shiny/driver/internal/lifecycler package - // instead of or together with the LifecycleEvent callback? -) - -func sendPaint(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { - PaintEvent(hwnd, paint.Event{}) - return _DefWindowProc(hwnd, uMsg, wParam, lParam) -} - -var screenMsgs = map[uint32]func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr){} - -func AddScreenMsg(fn func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr)) uint32 { - uMsg := currentUserWM.next() - screenMsgs[uMsg] = func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) uintptr { - fn(hwnd, uMsg, wParam, lParam) - return 0 - } - return uMsg -} - -func screenWindowWndProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { - switch uMsg { - case msgCreateWindow: - p := (*newWindowParams)(unsafe.Pointer(lParam)) - p.w, p.err = newWindow(p.opts) - case msgMainCallback: - go func() { - mainCallback() - SendScreenMessage(msgQuit, 0, 0) - }() - case msgQuit: - _PostQuitMessage(0) - } - fn := screenMsgs[uMsg] - if fn != nil { - return fn(hwnd, uMsg, wParam, lParam) - } - return _DefWindowProc(hwnd, uMsg, wParam, lParam) -} - -//go:uintptrescapes - -func SendScreenMessage(uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { - return SendMessage(screenHWND, uMsg, wParam, lParam) -} - -var windowMsgs = map[uint32]func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr){ - _WM_SETFOCUS: sendFocus, - _WM_KILLFOCUS: sendFocus, - _WM_PAINT: sendPaint, - msgShow: sendShow, - _WM_WINDOWPOSCHANGED: sendSizeEvent, - _WM_CLOSE: sendClose, - - _WM_LBUTTONDOWN: sendMouseEvent, - _WM_LBUTTONUP: sendMouseEvent, - _WM_MBUTTONDOWN: sendMouseEvent, - _WM_MBUTTONUP: sendMouseEvent, - _WM_RBUTTONDOWN: sendMouseEvent, - _WM_RBUTTONUP: sendMouseEvent, - _WM_MOUSEMOVE: sendMouseEvent, - _WM_MOUSEWHEEL: sendMouseEvent, - - _WM_KEYDOWN: sendKeyEvent, - _WM_KEYUP: sendKeyEvent, - _WM_SYSKEYDOWN: sendKeyEvent, - _WM_SYSKEYUP: sendKeyEvent, -} - -func AddWindowMsg(fn func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr)) uint32 { - uMsg := currentUserWM.next() - windowMsgs[uMsg] = func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) uintptr { - fn(hwnd, uMsg, wParam, lParam) - return 0 - } - return uMsg -} - -func windowWndProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { - fn := windowMsgs[uMsg] - if fn != nil { - return fn(hwnd, uMsg, wParam, lParam) - } - return _DefWindowProc(hwnd, uMsg, wParam, lParam) -} - -type newWindowParams struct { - opts *screen.NewWindowOptions - w syscall.Handle - err error -} - -func NewWindow(opts *screen.NewWindowOptions) (syscall.Handle, error) { - var p newWindowParams - p.opts = opts - SendScreenMessage(msgCreateWindow, 0, uintptr(unsafe.Pointer(&p))) - return p.w, p.err -} - -const windowClass = "shiny_Window" -const screenWindowClass = "shiny_ScreenWindow" - -func initWindowClass() (err error) { - wcname, err := syscall.UTF16PtrFromString(windowClass) - if err != nil { - return err - } - _, err = _RegisterClass(&_WNDCLASS{ - LpszClassName: wcname, - LpfnWndProc: syscall.NewCallback(windowWndProc), - HIcon: hDefaultIcon, - HCursor: hDefaultCursor, - HInstance: hThisInstance, - // TODO(andlabs): change this to something else? NULL? the hollow brush? - HbrBackground: syscall.Handle(_COLOR_BTNFACE + 1), - }) - return err -} - -func closeWindowClass() (err error) { - wcname, err := syscall.UTF16PtrFromString(windowClass) - if err != nil { - return err - } - _UnregisterClass(wcname, hThisInstance) - - return nil -} - -func initScreenWindow() (err error) { - swc, err := syscall.UTF16PtrFromString(screenWindowClass) - if err != nil { - return err - } - emptyString, err := syscall.UTF16PtrFromString("") - if err != nil { - return err - } - wc := _WNDCLASS{ - LpszClassName: swc, - LpfnWndProc: syscall.NewCallback(screenWindowWndProc), - HIcon: hDefaultIcon, - HCursor: hDefaultCursor, - HInstance: hThisInstance, - HbrBackground: syscall.Handle(_COLOR_BTNFACE + 1), - } - _, err = _RegisterClass(&wc) - if err != nil { - return err - } - screenHWND, err = _CreateWindowEx(0, - swc, emptyString, - _WS_OVERLAPPEDWINDOW, - _CW_USEDEFAULT, _CW_USEDEFAULT, - _CW_USEDEFAULT, _CW_USEDEFAULT, - _HWND_MESSAGE, 0, hThisInstance, 0) - if err != nil { - return err - } - return nil -} - -func closeScreenWindow() (err error) { - // first destroy window - _DestroyWindow(screenHWND) - - // then unregister class - swc, err := syscall.UTF16PtrFromString(screenWindowClass) - if err != nil { - return err - } - _UnregisterClass(swc, hThisInstance) - - return nil -} - -var ( - hDefaultIcon syscall.Handle - hDefaultCursor syscall.Handle - hThisInstance syscall.Handle -) - -func initCommon() (err error) { - hDefaultIcon, err = _LoadIcon(0, _IDI_APPLICATION) - if err != nil { - return err - } - hDefaultCursor, err = _LoadCursor(0, _IDC_ARROW) - if err != nil { - return err - } - // TODO(andlabs) hThisInstance - return nil -} - -//go:uintptrescapes - -func SendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { - return sendMessage(hwnd, uMsg, wParam, lParam) -} - -var mainCallback func() - -func Main(f func()) (retErr error) { - // It does not matter which OS thread we are on. - // All that matters is that we confine all UI operations - // to the thread that created the respective window. - runtime.LockOSThread() - - if err := initCommon(); err != nil { - return err - } - - if err := initScreenWindow(); err != nil { - return err - } - defer func() { - // TODO(andlabs): log an error if this fails? - closeScreenWindow() - }() - - if err := initWindowClass(); err != nil { - return err - } - defer func() { - // TODO(andlabs): log an error if this fails? - closeWindowClass() - }() - - // Prime the pump. - mainCallback = f - _PostMessage(screenHWND, msgMainCallback, 0, 0) - - // Main message pump. - var m _MSG - for { - done, err := _GetMessage(&m, 0, 0, 0) - if err != nil { - return fmt.Errorf("win32 GetMessage failed: %v", err) - } - if done == 0 { // WM_QUIT - break - } - _TranslateMessage(&m) - _DispatchMessage(&m) - } - - return nil -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/zsyscall_windows.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/zsyscall_windows.go deleted file mode 100644 index 26999f6..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/win32/zsyscall_windows.go +++ /dev/null @@ -1,293 +0,0 @@ -// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT - -package win32 - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return nil - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) - return e -} - -var ( - moduser32 = windows.NewLazySystemDLL("user32.dll") - - procGetDC = moduser32.NewProc("GetDC") - procReleaseDC = moduser32.NewProc("ReleaseDC") - procSendMessageW = moduser32.NewProc("SendMessageW") - procCreateWindowExW = moduser32.NewProc("CreateWindowExW") - procDefWindowProcW = moduser32.NewProc("DefWindowProcW") - procDestroyWindow = moduser32.NewProc("DestroyWindow") - procDispatchMessageW = moduser32.NewProc("DispatchMessageW") - procGetClientRect = moduser32.NewProc("GetClientRect") - procGetWindowRect = moduser32.NewProc("GetWindowRect") - procGetKeyboardLayout = moduser32.NewProc("GetKeyboardLayout") - procGetKeyboardState = moduser32.NewProc("GetKeyboardState") - procGetKeyState = moduser32.NewProc("GetKeyState") - procGetMessageW = moduser32.NewProc("GetMessageW") - procLoadCursorW = moduser32.NewProc("LoadCursorW") - procLoadIconW = moduser32.NewProc("LoadIconW") - procMoveWindow = moduser32.NewProc("MoveWindow") - procPostMessageW = moduser32.NewProc("PostMessageW") - procPostQuitMessage = moduser32.NewProc("PostQuitMessage") - procRegisterClassW = moduser32.NewProc("RegisterClassW") - procShowWindow = moduser32.NewProc("ShowWindow") - procScreenToClient = moduser32.NewProc("ScreenToClient") - procToUnicodeEx = moduser32.NewProc("ToUnicodeEx") - procTranslateMessage = moduser32.NewProc("TranslateMessage") - procUnregisterClassW = moduser32.NewProc("UnregisterClassW") -) - -func GetDC(hwnd syscall.Handle) (dc syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetDC.Addr(), 1, uintptr(hwnd), 0, 0) - dc = syscall.Handle(r0) - if dc == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ReleaseDC(hwnd syscall.Handle, dc syscall.Handle) (err error) { - r1, _, e1 := syscall.Syscall(procReleaseDC.Addr(), 2, uintptr(hwnd), uintptr(dc), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func sendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { - r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(hwnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0) - lResult = uintptr(r0) - return -} - -func _CreateWindowEx(exstyle uint32, className *uint16, windowText *uint16, style uint32, x int32, y int32, width int32, height int32, parent syscall.Handle, menu syscall.Handle, hInstance syscall.Handle, lpParam uintptr) (hwnd syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall12(procCreateWindowExW.Addr(), 12, uintptr(exstyle), uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(windowText)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(parent), uintptr(menu), uintptr(hInstance), uintptr(lpParam)) - hwnd = syscall.Handle(r0) - if hwnd == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _DefWindowProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { - r0, _, _ := syscall.Syscall6(procDefWindowProcW.Addr(), 4, uintptr(hwnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0) - lResult = uintptr(r0) - return -} - -func _DestroyWindow(hwnd syscall.Handle) (err error) { - r1, _, e1 := syscall.Syscall(procDestroyWindow.Addr(), 1, uintptr(hwnd), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _DispatchMessage(msg *_MSG) (ret int32) { - r0, _, _ := syscall.Syscall(procDispatchMessageW.Addr(), 1, uintptr(unsafe.Pointer(msg)), 0, 0) - ret = int32(r0) - return -} - -func _GetClientRect(hwnd syscall.Handle, rect *_RECT) (err error) { - r1, _, e1 := syscall.Syscall(procGetClientRect.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(rect)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _GetWindowRect(hwnd syscall.Handle, rect *_RECT) (err error) { - r1, _, e1 := syscall.Syscall(procGetWindowRect.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(rect)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _GetKeyboardLayout(threadID uint32) (locale syscall.Handle) { - r0, _, _ := syscall.Syscall(procGetKeyboardLayout.Addr(), 1, uintptr(threadID), 0, 0) - locale = syscall.Handle(r0) - return -} - -func _GetKeyboardState(lpKeyState *byte) (err error) { - r1, _, e1 := syscall.Syscall(procGetKeyboardState.Addr(), 1, uintptr(unsafe.Pointer(lpKeyState)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _GetKeyState(virtkey int32) (keystatus int16) { - r0, _, _ := syscall.Syscall(procGetKeyState.Addr(), 1, uintptr(virtkey), 0, 0) - keystatus = int16(r0) - return -} - -func _GetMessage(msg *_MSG, hwnd syscall.Handle, msgfiltermin uint32, msgfiltermax uint32) (ret int32, err error) { - r0, _, e1 := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(msgfiltermin), uintptr(msgfiltermax), 0, 0) - ret = int32(r0) - if ret == -1 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _LoadCursor(hInstance syscall.Handle, cursorName uintptr) (cursor syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadCursorW.Addr(), 2, uintptr(hInstance), uintptr(cursorName), 0) - cursor = syscall.Handle(r0) - if cursor == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _LoadIcon(hInstance syscall.Handle, iconName uintptr) (icon syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadIconW.Addr(), 2, uintptr(hInstance), uintptr(iconName), 0) - icon = syscall.Handle(r0) - if icon == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _MoveWindow(hwnd syscall.Handle, x int32, y int32, w int32, h int32, repaint bool) (err error) { - var _p0 uint32 - if repaint { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall6(procMoveWindow.Addr(), 6, uintptr(hwnd), uintptr(x), uintptr(y), uintptr(w), uintptr(h), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _PostMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult bool) { - r0, _, _ := syscall.Syscall6(procPostMessageW.Addr(), 4, uintptr(hwnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0) - lResult = r0 != 0 - return -} - -func _PostQuitMessage(exitCode int32) { - syscall.Syscall(procPostQuitMessage.Addr(), 1, uintptr(exitCode), 0, 0) - return -} - -func _RegisterClass(wc *_WNDCLASS) (atom uint16, err error) { - r0, _, e1 := syscall.Syscall(procRegisterClassW.Addr(), 1, uintptr(unsafe.Pointer(wc)), 0, 0) - atom = uint16(r0) - if atom == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func _ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) { - r0, _, _ := syscall.Syscall(procShowWindow.Addr(), 2, uintptr(hwnd), uintptr(cmdshow), 0) - wasvisible = r0 != 0 - return -} - -func _ScreenToClient(hwnd syscall.Handle, lpPoint *_POINT) (ok bool) { - r0, _, _ := syscall.Syscall(procScreenToClient.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(lpPoint)), 0) - ok = r0 != 0 - return -} - -func _ToUnicodeEx(wVirtKey uint32, wScanCode uint32, lpKeyState *byte, pwszBuff *uint16, cchBuff int32, wFlags uint32, dwhkl syscall.Handle) (ret int32) { - r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(wVirtKey), uintptr(wScanCode), uintptr(unsafe.Pointer(lpKeyState)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(wFlags), uintptr(dwhkl), 0, 0) - ret = int32(r0) - return -} - -func _TranslateMessage(msg *_MSG) (done bool) { - r0, _, _ := syscall.Syscall(procTranslateMessage.Addr(), 1, uintptr(unsafe.Pointer(msg)), 0, 0) - done = r0 != 0 - return -} - -func _UnregisterClass(lpClassName *uint16, hInstance syscall.Handle) (done bool) { - r0, _, _ := syscall.Syscall(procUnregisterClassW.Addr(), 2, uintptr(unsafe.Pointer(lpClassName)), uintptr(hInstance), 0) - done = r0 != 0 - return -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/x11key/table.go b/vendor/golang.org/x/exp/shiny/driver/internal/x11key/table.go deleted file mode 100644 index 63e8344..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/x11key/table.go +++ /dev/null @@ -1,1577 +0,0 @@ -// generated by go generate; DO NOT EDIT. - -package x11key - -// keysymCodePoints maps xproto.Keysym values to their corresponding unicode code point. -var keysymCodePoints = map[rune]rune{ - 0x0020: 0x0020, // XK_space: SPACE - 0x0021: 0x0021, // XK_exclam: EXCLAMATION MARK - 0x0022: 0x0022, // XK_quotedbl: QUOTATION MARK - 0x0023: 0x0023, // XK_numbersign: NUMBER SIGN - 0x0024: 0x0024, // XK_dollar: DOLLAR SIGN - 0x0025: 0x0025, // XK_percent: PERCENT SIGN - 0x0026: 0x0026, // XK_ampersand: AMPERSAND - 0x0027: 0x0027, // XK_apostrophe: APOSTROPHE - 0x0028: 0x0028, // XK_parenleft: LEFT PARENTHESIS - 0x0029: 0x0029, // XK_parenright: RIGHT PARENTHESIS - 0x002a: 0x002A, // XK_asterisk: ASTERISK - 0x002b: 0x002B, // XK_plus: PLUS SIGN - 0x002c: 0x002C, // XK_comma: COMMA - 0x002d: 0x002D, // XK_minus: HYPHEN-MINUS - 0x002e: 0x002E, // XK_period: FULL STOP - 0x002f: 0x002F, // XK_slash: SOLIDUS - 0x0030: 0x0030, // XK_0: DIGIT ZERO - 0x0031: 0x0031, // XK_1: DIGIT ONE - 0x0032: 0x0032, // XK_2: DIGIT TWO - 0x0033: 0x0033, // XK_3: DIGIT THREE - 0x0034: 0x0034, // XK_4: DIGIT FOUR - 0x0035: 0x0035, // XK_5: DIGIT FIVE - 0x0036: 0x0036, // XK_6: DIGIT SIX - 0x0037: 0x0037, // XK_7: DIGIT SEVEN - 0x0038: 0x0038, // XK_8: DIGIT EIGHT - 0x0039: 0x0039, // XK_9: DIGIT NINE - 0x003a: 0x003A, // XK_colon: COLON - 0x003b: 0x003B, // XK_semicolon: SEMICOLON - 0x003c: 0x003C, // XK_less: LESS-THAN SIGN - 0x003d: 0x003D, // XK_equal: EQUALS SIGN - 0x003e: 0x003E, // XK_greater: GREATER-THAN SIGN - 0x003f: 0x003F, // XK_question: QUESTION MARK - 0x0040: 0x0040, // XK_at: COMMERCIAL AT - 0x0041: 0x0041, // XK_A: LATIN CAPITAL LETTER A - 0x0042: 0x0042, // XK_B: LATIN CAPITAL LETTER B - 0x0043: 0x0043, // XK_C: LATIN CAPITAL LETTER C - 0x0044: 0x0044, // XK_D: LATIN CAPITAL LETTER D - 0x0045: 0x0045, // XK_E: LATIN CAPITAL LETTER E - 0x0046: 0x0046, // XK_F: LATIN CAPITAL LETTER F - 0x0047: 0x0047, // XK_G: LATIN CAPITAL LETTER G - 0x0048: 0x0048, // XK_H: LATIN CAPITAL LETTER H - 0x0049: 0x0049, // XK_I: LATIN CAPITAL LETTER I - 0x004a: 0x004A, // XK_J: LATIN CAPITAL LETTER J - 0x004b: 0x004B, // XK_K: LATIN CAPITAL LETTER K - 0x004c: 0x004C, // XK_L: LATIN CAPITAL LETTER L - 0x004d: 0x004D, // XK_M: LATIN CAPITAL LETTER M - 0x004e: 0x004E, // XK_N: LATIN CAPITAL LETTER N - 0x004f: 0x004F, // XK_O: LATIN CAPITAL LETTER O - 0x0050: 0x0050, // XK_P: LATIN CAPITAL LETTER P - 0x0051: 0x0051, // XK_Q: LATIN CAPITAL LETTER Q - 0x0052: 0x0052, // XK_R: LATIN CAPITAL LETTER R - 0x0053: 0x0053, // XK_S: LATIN CAPITAL LETTER S - 0x0054: 0x0054, // XK_T: LATIN CAPITAL LETTER T - 0x0055: 0x0055, // XK_U: LATIN CAPITAL LETTER U - 0x0056: 0x0056, // XK_V: LATIN CAPITAL LETTER V - 0x0057: 0x0057, // XK_W: LATIN CAPITAL LETTER W - 0x0058: 0x0058, // XK_X: LATIN CAPITAL LETTER X - 0x0059: 0x0059, // XK_Y: LATIN CAPITAL LETTER Y - 0x005a: 0x005A, // XK_Z: LATIN CAPITAL LETTER Z - 0x005b: 0x005B, // XK_bracketleft: LEFT SQUARE BRACKET - 0x005c: 0x005C, // XK_backslash: REVERSE SOLIDUS - 0x005d: 0x005D, // XK_bracketright: RIGHT SQUARE BRACKET - 0x005e: 0x005E, // XK_asciicircum: CIRCUMFLEX ACCENT - 0x005f: 0x005F, // XK_underscore: LOW LINE - 0x0060: 0x0060, // XK_grave: GRAVE ACCENT - 0x0061: 0x0061, // XK_a: LATIN SMALL LETTER A - 0x0062: 0x0062, // XK_b: LATIN SMALL LETTER B - 0x0063: 0x0063, // XK_c: LATIN SMALL LETTER C - 0x0064: 0x0064, // XK_d: LATIN SMALL LETTER D - 0x0065: 0x0065, // XK_e: LATIN SMALL LETTER E - 0x0066: 0x0066, // XK_f: LATIN SMALL LETTER F - 0x0067: 0x0067, // XK_g: LATIN SMALL LETTER G - 0x0068: 0x0068, // XK_h: LATIN SMALL LETTER H - 0x0069: 0x0069, // XK_i: LATIN SMALL LETTER I - 0x006a: 0x006A, // XK_j: LATIN SMALL LETTER J - 0x006b: 0x006B, // XK_k: LATIN SMALL LETTER K - 0x006c: 0x006C, // XK_l: LATIN SMALL LETTER L - 0x006d: 0x006D, // XK_m: LATIN SMALL LETTER M - 0x006e: 0x006E, // XK_n: LATIN SMALL LETTER N - 0x006f: 0x006F, // XK_o: LATIN SMALL LETTER O - 0x0070: 0x0070, // XK_p: LATIN SMALL LETTER P - 0x0071: 0x0071, // XK_q: LATIN SMALL LETTER Q - 0x0072: 0x0072, // XK_r: LATIN SMALL LETTER R - 0x0073: 0x0073, // XK_s: LATIN SMALL LETTER S - 0x0074: 0x0074, // XK_t: LATIN SMALL LETTER T - 0x0075: 0x0075, // XK_u: LATIN SMALL LETTER U - 0x0076: 0x0076, // XK_v: LATIN SMALL LETTER V - 0x0077: 0x0077, // XK_w: LATIN SMALL LETTER W - 0x0078: 0x0078, // XK_x: LATIN SMALL LETTER X - 0x0079: 0x0079, // XK_y: LATIN SMALL LETTER Y - 0x007a: 0x007A, // XK_z: LATIN SMALL LETTER Z - 0x007b: 0x007B, // XK_braceleft: LEFT CURLY BRACKET - 0x007c: 0x007C, // XK_bar: VERTICAL LINE - 0x007d: 0x007D, // XK_braceright: RIGHT CURLY BRACKET - 0x007e: 0x007E, // XK_asciitilde: TILDE - 0x00a0: 0x00A0, // XK_nobreakspace: NO-BREAK SPACE - 0x00a1: 0x00A1, // XK_exclamdown: INVERTED EXCLAMATION MARK - 0x00a2: 0x00A2, // XK_cent: CENT SIGN - 0x00a3: 0x00A3, // XK_sterling: POUND SIGN - 0x00a4: 0x00A4, // XK_currency: CURRENCY SIGN - 0x00a5: 0x00A5, // XK_yen: YEN SIGN - 0x00a6: 0x00A6, // XK_brokenbar: BROKEN BAR - 0x00a7: 0x00A7, // XK_section: SECTION SIGN - 0x00a8: 0x00A8, // XK_diaeresis: DIAERESIS - 0x00a9: 0x00A9, // XK_copyright: COPYRIGHT SIGN - 0x00aa: 0x00AA, // XK_ordfeminine: FEMININE ORDINAL INDICATOR - 0x00ab: 0x00AB, // XK_guillemotleft: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x00ac: 0x00AC, // XK_notsign: NOT SIGN - 0x00ad: 0x00AD, // XK_hyphen: SOFT HYPHEN - 0x00ae: 0x00AE, // XK_registered: REGISTERED SIGN - 0x00af: 0x00AF, // XK_macron: MACRON - 0x00b0: 0x00B0, // XK_degree: DEGREE SIGN - 0x00b1: 0x00B1, // XK_plusminus: PLUS-MINUS SIGN - 0x00b2: 0x00B2, // XK_twosuperior: SUPERSCRIPT TWO - 0x00b3: 0x00B3, // XK_threesuperior: SUPERSCRIPT THREE - 0x00b4: 0x00B4, // XK_acute: ACUTE ACCENT - 0x00b5: 0x00B5, // XK_mu: MICRO SIGN - 0x00b6: 0x00B6, // XK_paragraph: PILCROW SIGN - 0x00b7: 0x00B7, // XK_periodcentered: MIDDLE DOT - 0x00b8: 0x00B8, // XK_cedilla: CEDILLA - 0x00b9: 0x00B9, // XK_onesuperior: SUPERSCRIPT ONE - 0x00ba: 0x00BA, // XK_masculine: MASCULINE ORDINAL INDICATOR - 0x00bb: 0x00BB, // XK_guillemotright: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - 0x00bc: 0x00BC, // XK_onequarter: VULGAR FRACTION ONE QUARTER - 0x00bd: 0x00BD, // XK_onehalf: VULGAR FRACTION ONE HALF - 0x00be: 0x00BE, // XK_threequarters: VULGAR FRACTION THREE QUARTERS - 0x00bf: 0x00BF, // XK_questiondown: INVERTED QUESTION MARK - 0x00c0: 0x00C0, // XK_Agrave: LATIN CAPITAL LETTER A WITH GRAVE - 0x00c1: 0x00C1, // XK_Aacute: LATIN CAPITAL LETTER A WITH ACUTE - 0x00c2: 0x00C2, // XK_Acircumflex: LATIN CAPITAL LETTER A WITH CIRCUMFLEX - 0x00c3: 0x00C3, // XK_Atilde: LATIN CAPITAL LETTER A WITH TILDE - 0x00c4: 0x00C4, // XK_Adiaeresis: LATIN CAPITAL LETTER A WITH DIAERESIS - 0x00c5: 0x00C5, // XK_Aring: LATIN CAPITAL LETTER A WITH RING ABOVE - 0x00c6: 0x00C6, // XK_AE: LATIN CAPITAL LETTER AE - 0x00c7: 0x00C7, // XK_Ccedilla: LATIN CAPITAL LETTER C WITH CEDILLA - 0x00c8: 0x00C8, // XK_Egrave: LATIN CAPITAL LETTER E WITH GRAVE - 0x00c9: 0x00C9, // XK_Eacute: LATIN CAPITAL LETTER E WITH ACUTE - 0x00ca: 0x00CA, // XK_Ecircumflex: LATIN CAPITAL LETTER E WITH CIRCUMFLEX - 0x00cb: 0x00CB, // XK_Ediaeresis: LATIN CAPITAL LETTER E WITH DIAERESIS - 0x00cc: 0x00CC, // XK_Igrave: LATIN CAPITAL LETTER I WITH GRAVE - 0x00cd: 0x00CD, // XK_Iacute: LATIN CAPITAL LETTER I WITH ACUTE - 0x00ce: 0x00CE, // XK_Icircumflex: LATIN CAPITAL LETTER I WITH CIRCUMFLEX - 0x00cf: 0x00CF, // XK_Idiaeresis: LATIN CAPITAL LETTER I WITH DIAERESIS - 0x00d0: 0x00D0, // XK_ETH: LATIN CAPITAL LETTER ETH - 0x00d1: 0x00D1, // XK_Ntilde: LATIN CAPITAL LETTER N WITH TILDE - 0x00d2: 0x00D2, // XK_Ograve: LATIN CAPITAL LETTER O WITH GRAVE - 0x00d3: 0x00D3, // XK_Oacute: LATIN CAPITAL LETTER O WITH ACUTE - 0x00d4: 0x00D4, // XK_Ocircumflex: LATIN CAPITAL LETTER O WITH CIRCUMFLEX - 0x00d5: 0x00D5, // XK_Otilde: LATIN CAPITAL LETTER O WITH TILDE - 0x00d6: 0x00D6, // XK_Odiaeresis: LATIN CAPITAL LETTER O WITH DIAERESIS - 0x00d7: 0x00D7, // XK_multiply: MULTIPLICATION SIGN - 0x00d8: 0x00D8, // XK_Oslash: LATIN CAPITAL LETTER O WITH STROKE - 0x00d9: 0x00D9, // XK_Ugrave: LATIN CAPITAL LETTER U WITH GRAVE - 0x00da: 0x00DA, // XK_Uacute: LATIN CAPITAL LETTER U WITH ACUTE - 0x00db: 0x00DB, // XK_Ucircumflex: LATIN CAPITAL LETTER U WITH CIRCUMFLEX - 0x00dc: 0x00DC, // XK_Udiaeresis: LATIN CAPITAL LETTER U WITH DIAERESIS - 0x00dd: 0x00DD, // XK_Yacute: LATIN CAPITAL LETTER Y WITH ACUTE - 0x00de: 0x00DE, // XK_THORN: LATIN CAPITAL LETTER THORN - 0x00df: 0x00DF, // XK_ssharp: LATIN SMALL LETTER SHARP S - 0x00e0: 0x00E0, // XK_agrave: LATIN SMALL LETTER A WITH GRAVE - 0x00e1: 0x00E1, // XK_aacute: LATIN SMALL LETTER A WITH ACUTE - 0x00e2: 0x00E2, // XK_acircumflex: LATIN SMALL LETTER A WITH CIRCUMFLEX - 0x00e3: 0x00E3, // XK_atilde: LATIN SMALL LETTER A WITH TILDE - 0x00e4: 0x00E4, // XK_adiaeresis: LATIN SMALL LETTER A WITH DIAERESIS - 0x00e5: 0x00E5, // XK_aring: LATIN SMALL LETTER A WITH RING ABOVE - 0x00e6: 0x00E6, // XK_ae: LATIN SMALL LETTER AE - 0x00e7: 0x00E7, // XK_ccedilla: LATIN SMALL LETTER C WITH CEDILLA - 0x00e8: 0x00E8, // XK_egrave: LATIN SMALL LETTER E WITH GRAVE - 0x00e9: 0x00E9, // XK_eacute: LATIN SMALL LETTER E WITH ACUTE - 0x00ea: 0x00EA, // XK_ecircumflex: LATIN SMALL LETTER E WITH CIRCUMFLEX - 0x00eb: 0x00EB, // XK_ediaeresis: LATIN SMALL LETTER E WITH DIAERESIS - 0x00ec: 0x00EC, // XK_igrave: LATIN SMALL LETTER I WITH GRAVE - 0x00ed: 0x00ED, // XK_iacute: LATIN SMALL LETTER I WITH ACUTE - 0x00ee: 0x00EE, // XK_icircumflex: LATIN SMALL LETTER I WITH CIRCUMFLEX - 0x00ef: 0x00EF, // XK_idiaeresis: LATIN SMALL LETTER I WITH DIAERESIS - 0x00f0: 0x00F0, // XK_eth: LATIN SMALL LETTER ETH - 0x00f1: 0x00F1, // XK_ntilde: LATIN SMALL LETTER N WITH TILDE - 0x00f2: 0x00F2, // XK_ograve: LATIN SMALL LETTER O WITH GRAVE - 0x00f3: 0x00F3, // XK_oacute: LATIN SMALL LETTER O WITH ACUTE - 0x00f4: 0x00F4, // XK_ocircumflex: LATIN SMALL LETTER O WITH CIRCUMFLEX - 0x00f5: 0x00F5, // XK_otilde: LATIN SMALL LETTER O WITH TILDE - 0x00f6: 0x00F6, // XK_odiaeresis: LATIN SMALL LETTER O WITH DIAERESIS - 0x00f7: 0x00F7, // XK_division: DIVISION SIGN - 0x00f8: 0x00F8, // XK_oslash: LATIN SMALL LETTER O WITH STROKE - 0x00f9: 0x00F9, // XK_ugrave: LATIN SMALL LETTER U WITH GRAVE - 0x00fa: 0x00FA, // XK_uacute: LATIN SMALL LETTER U WITH ACUTE - 0x00fb: 0x00FB, // XK_ucircumflex: LATIN SMALL LETTER U WITH CIRCUMFLEX - 0x00fc: 0x00FC, // XK_udiaeresis: LATIN SMALL LETTER U WITH DIAERESIS - 0x00fd: 0x00FD, // XK_yacute: LATIN SMALL LETTER Y WITH ACUTE - 0x00fe: 0x00FE, // XK_thorn: LATIN SMALL LETTER THORN - 0x00ff: 0x00FF, // XK_ydiaeresis: LATIN SMALL LETTER Y WITH DIAERESIS - 0x01a1: 0x0104, // XK_Aogonek: LATIN CAPITAL LETTER A WITH OGONEK - 0x01a2: 0x02D8, // XK_breve: BREVE - 0x01a3: 0x0141, // XK_Lstroke: LATIN CAPITAL LETTER L WITH STROKE - 0x01a5: 0x013D, // XK_Lcaron: LATIN CAPITAL LETTER L WITH CARON - 0x01a6: 0x015A, // XK_Sacute: LATIN CAPITAL LETTER S WITH ACUTE - 0x01a9: 0x0160, // XK_Scaron: LATIN CAPITAL LETTER S WITH CARON - 0x01aa: 0x015E, // XK_Scedilla: LATIN CAPITAL LETTER S WITH CEDILLA - 0x01ab: 0x0164, // XK_Tcaron: LATIN CAPITAL LETTER T WITH CARON - 0x01ac: 0x0179, // XK_Zacute: LATIN CAPITAL LETTER Z WITH ACUTE - 0x01ae: 0x017D, // XK_Zcaron: LATIN CAPITAL LETTER Z WITH CARON - 0x01af: 0x017B, // XK_Zabovedot: LATIN CAPITAL LETTER Z WITH DOT ABOVE - 0x01b1: 0x0105, // XK_aogonek: LATIN SMALL LETTER A WITH OGONEK - 0x01b2: 0x02DB, // XK_ogonek: OGONEK - 0x01b3: 0x0142, // XK_lstroke: LATIN SMALL LETTER L WITH STROKE - 0x01b5: 0x013E, // XK_lcaron: LATIN SMALL LETTER L WITH CARON - 0x01b6: 0x015B, // XK_sacute: LATIN SMALL LETTER S WITH ACUTE - 0x01b7: 0x02C7, // XK_caron: CARON - 0x01b9: 0x0161, // XK_scaron: LATIN SMALL LETTER S WITH CARON - 0x01ba: 0x015F, // XK_scedilla: LATIN SMALL LETTER S WITH CEDILLA - 0x01bb: 0x0165, // XK_tcaron: LATIN SMALL LETTER T WITH CARON - 0x01bc: 0x017A, // XK_zacute: LATIN SMALL LETTER Z WITH ACUTE - 0x01bd: 0x02DD, // XK_doubleacute: DOUBLE ACUTE ACCENT - 0x01be: 0x017E, // XK_zcaron: LATIN SMALL LETTER Z WITH CARON - 0x01bf: 0x017C, // XK_zabovedot: LATIN SMALL LETTER Z WITH DOT ABOVE - 0x01c0: 0x0154, // XK_Racute: LATIN CAPITAL LETTER R WITH ACUTE - 0x01c3: 0x0102, // XK_Abreve: LATIN CAPITAL LETTER A WITH BREVE - 0x01c5: 0x0139, // XK_Lacute: LATIN CAPITAL LETTER L WITH ACUTE - 0x01c6: 0x0106, // XK_Cacute: LATIN CAPITAL LETTER C WITH ACUTE - 0x01c8: 0x010C, // XK_Ccaron: LATIN CAPITAL LETTER C WITH CARON - 0x01ca: 0x0118, // XK_Eogonek: LATIN CAPITAL LETTER E WITH OGONEK - 0x01cc: 0x011A, // XK_Ecaron: LATIN CAPITAL LETTER E WITH CARON - 0x01cf: 0x010E, // XK_Dcaron: LATIN CAPITAL LETTER D WITH CARON - 0x01d0: 0x0110, // XK_Dstroke: LATIN CAPITAL LETTER D WITH STROKE - 0x01d1: 0x0143, // XK_Nacute: LATIN CAPITAL LETTER N WITH ACUTE - 0x01d2: 0x0147, // XK_Ncaron: LATIN CAPITAL LETTER N WITH CARON - 0x01d5: 0x0150, // XK_Odoubleacute: LATIN CAPITAL LETTER O WITH DOUBLE ACUTE - 0x01d8: 0x0158, // XK_Rcaron: LATIN CAPITAL LETTER R WITH CARON - 0x01d9: 0x016E, // XK_Uring: LATIN CAPITAL LETTER U WITH RING ABOVE - 0x01db: 0x0170, // XK_Udoubleacute: LATIN CAPITAL LETTER U WITH DOUBLE ACUTE - 0x01de: 0x0162, // XK_Tcedilla: LATIN CAPITAL LETTER T WITH CEDILLA - 0x01e0: 0x0155, // XK_racute: LATIN SMALL LETTER R WITH ACUTE - 0x01e3: 0x0103, // XK_abreve: LATIN SMALL LETTER A WITH BREVE - 0x01e5: 0x013A, // XK_lacute: LATIN SMALL LETTER L WITH ACUTE - 0x01e6: 0x0107, // XK_cacute: LATIN SMALL LETTER C WITH ACUTE - 0x01e8: 0x010D, // XK_ccaron: LATIN SMALL LETTER C WITH CARON - 0x01ea: 0x0119, // XK_eogonek: LATIN SMALL LETTER E WITH OGONEK - 0x01ec: 0x011B, // XK_ecaron: LATIN SMALL LETTER E WITH CARON - 0x01ef: 0x010F, // XK_dcaron: LATIN SMALL LETTER D WITH CARON - 0x01f0: 0x0111, // XK_dstroke: LATIN SMALL LETTER D WITH STROKE - 0x01f1: 0x0144, // XK_nacute: LATIN SMALL LETTER N WITH ACUTE - 0x01f2: 0x0148, // XK_ncaron: LATIN SMALL LETTER N WITH CARON - 0x01f5: 0x0151, // XK_odoubleacute: LATIN SMALL LETTER O WITH DOUBLE ACUTE - 0x01f8: 0x0159, // XK_rcaron: LATIN SMALL LETTER R WITH CARON - 0x01f9: 0x016F, // XK_uring: LATIN SMALL LETTER U WITH RING ABOVE - 0x01fb: 0x0171, // XK_udoubleacute: LATIN SMALL LETTER U WITH DOUBLE ACUTE - 0x01fe: 0x0163, // XK_tcedilla: LATIN SMALL LETTER T WITH CEDILLA - 0x01ff: 0x02D9, // XK_abovedot: DOT ABOVE - 0x02a1: 0x0126, // XK_Hstroke: LATIN CAPITAL LETTER H WITH STROKE - 0x02a6: 0x0124, // XK_Hcircumflex: LATIN CAPITAL LETTER H WITH CIRCUMFLEX - 0x02a9: 0x0130, // XK_Iabovedot: LATIN CAPITAL LETTER I WITH DOT ABOVE - 0x02ab: 0x011E, // XK_Gbreve: LATIN CAPITAL LETTER G WITH BREVE - 0x02ac: 0x0134, // XK_Jcircumflex: LATIN CAPITAL LETTER J WITH CIRCUMFLEX - 0x02b1: 0x0127, // XK_hstroke: LATIN SMALL LETTER H WITH STROKE - 0x02b6: 0x0125, // XK_hcircumflex: LATIN SMALL LETTER H WITH CIRCUMFLEX - 0x02b9: 0x0131, // XK_idotless: LATIN SMALL LETTER DOTLESS I - 0x02bb: 0x011F, // XK_gbreve: LATIN SMALL LETTER G WITH BREVE - 0x02bc: 0x0135, // XK_jcircumflex: LATIN SMALL LETTER J WITH CIRCUMFLEX - 0x02c5: 0x010A, // XK_Cabovedot: LATIN CAPITAL LETTER C WITH DOT ABOVE - 0x02c6: 0x0108, // XK_Ccircumflex: LATIN CAPITAL LETTER C WITH CIRCUMFLEX - 0x02d5: 0x0120, // XK_Gabovedot: LATIN CAPITAL LETTER G WITH DOT ABOVE - 0x02d8: 0x011C, // XK_Gcircumflex: LATIN CAPITAL LETTER G WITH CIRCUMFLEX - 0x02dd: 0x016C, // XK_Ubreve: LATIN CAPITAL LETTER U WITH BREVE - 0x02de: 0x015C, // XK_Scircumflex: LATIN CAPITAL LETTER S WITH CIRCUMFLEX - 0x02e5: 0x010B, // XK_cabovedot: LATIN SMALL LETTER C WITH DOT ABOVE - 0x02e6: 0x0109, // XK_ccircumflex: LATIN SMALL LETTER C WITH CIRCUMFLEX - 0x02f5: 0x0121, // XK_gabovedot: LATIN SMALL LETTER G WITH DOT ABOVE - 0x02f8: 0x011D, // XK_gcircumflex: LATIN SMALL LETTER G WITH CIRCUMFLEX - 0x02fd: 0x016D, // XK_ubreve: LATIN SMALL LETTER U WITH BREVE - 0x02fe: 0x015D, // XK_scircumflex: LATIN SMALL LETTER S WITH CIRCUMFLEX - 0x03a2: 0x0138, // XK_kra: LATIN SMALL LETTER KRA - 0x03a3: 0x0156, // XK_Rcedilla: LATIN CAPITAL LETTER R WITH CEDILLA - 0x03a5: 0x0128, // XK_Itilde: LATIN CAPITAL LETTER I WITH TILDE - 0x03a6: 0x013B, // XK_Lcedilla: LATIN CAPITAL LETTER L WITH CEDILLA - 0x03aa: 0x0112, // XK_Emacron: LATIN CAPITAL LETTER E WITH MACRON - 0x03ab: 0x0122, // XK_Gcedilla: LATIN CAPITAL LETTER G WITH CEDILLA - 0x03ac: 0x0166, // XK_Tslash: LATIN CAPITAL LETTER T WITH STROKE - 0x03b3: 0x0157, // XK_rcedilla: LATIN SMALL LETTER R WITH CEDILLA - 0x03b5: 0x0129, // XK_itilde: LATIN SMALL LETTER I WITH TILDE - 0x03b6: 0x013C, // XK_lcedilla: LATIN SMALL LETTER L WITH CEDILLA - 0x03ba: 0x0113, // XK_emacron: LATIN SMALL LETTER E WITH MACRON - 0x03bb: 0x0123, // XK_gcedilla: LATIN SMALL LETTER G WITH CEDILLA - 0x03bc: 0x0167, // XK_tslash: LATIN SMALL LETTER T WITH STROKE - 0x03bd: 0x014A, // XK_ENG: LATIN CAPITAL LETTER ENG - 0x03bf: 0x014B, // XK_eng: LATIN SMALL LETTER ENG - 0x03c0: 0x0100, // XK_Amacron: LATIN CAPITAL LETTER A WITH MACRON - 0x03c7: 0x012E, // XK_Iogonek: LATIN CAPITAL LETTER I WITH OGONEK - 0x03cc: 0x0116, // XK_Eabovedot: LATIN CAPITAL LETTER E WITH DOT ABOVE - 0x03cf: 0x012A, // XK_Imacron: LATIN CAPITAL LETTER I WITH MACRON - 0x03d1: 0x0145, // XK_Ncedilla: LATIN CAPITAL LETTER N WITH CEDILLA - 0x03d2: 0x014C, // XK_Omacron: LATIN CAPITAL LETTER O WITH MACRON - 0x03d3: 0x0136, // XK_Kcedilla: LATIN CAPITAL LETTER K WITH CEDILLA - 0x03d9: 0x0172, // XK_Uogonek: LATIN CAPITAL LETTER U WITH OGONEK - 0x03dd: 0x0168, // XK_Utilde: LATIN CAPITAL LETTER U WITH TILDE - 0x03de: 0x016A, // XK_Umacron: LATIN CAPITAL LETTER U WITH MACRON - 0x03e0: 0x0101, // XK_amacron: LATIN SMALL LETTER A WITH MACRON - 0x03e7: 0x012F, // XK_iogonek: LATIN SMALL LETTER I WITH OGONEK - 0x03ec: 0x0117, // XK_eabovedot: LATIN SMALL LETTER E WITH DOT ABOVE - 0x03ef: 0x012B, // XK_imacron: LATIN SMALL LETTER I WITH MACRON - 0x03f1: 0x0146, // XK_ncedilla: LATIN SMALL LETTER N WITH CEDILLA - 0x03f2: 0x014D, // XK_omacron: LATIN SMALL LETTER O WITH MACRON - 0x03f3: 0x0137, // XK_kcedilla: LATIN SMALL LETTER K WITH CEDILLA - 0x03f9: 0x0173, // XK_uogonek: LATIN SMALL LETTER U WITH OGONEK - 0x03fd: 0x0169, // XK_utilde: LATIN SMALL LETTER U WITH TILDE - 0x03fe: 0x016B, // XK_umacron: LATIN SMALL LETTER U WITH MACRON - 0x1000174: 0x0174, // XK_Wcircumflex: LATIN CAPITAL LETTER W WITH CIRCUMFLEX - 0x1000175: 0x0175, // XK_wcircumflex: LATIN SMALL LETTER W WITH CIRCUMFLEX - 0x1000176: 0x0176, // XK_Ycircumflex: LATIN CAPITAL LETTER Y WITH CIRCUMFLEX - 0x1000177: 0x0177, // XK_ycircumflex: LATIN SMALL LETTER Y WITH CIRCUMFLEX - 0x1001e02: 0x1E02, // XK_Babovedot: LATIN CAPITAL LETTER B WITH DOT ABOVE - 0x1001e03: 0x1E03, // XK_babovedot: LATIN SMALL LETTER B WITH DOT ABOVE - 0x1001e0a: 0x1E0A, // XK_Dabovedot: LATIN CAPITAL LETTER D WITH DOT ABOVE - 0x1001e0b: 0x1E0B, // XK_dabovedot: LATIN SMALL LETTER D WITH DOT ABOVE - 0x1001e1e: 0x1E1E, // XK_Fabovedot: LATIN CAPITAL LETTER F WITH DOT ABOVE - 0x1001e1f: 0x1E1F, // XK_fabovedot: LATIN SMALL LETTER F WITH DOT ABOVE - 0x1001e40: 0x1E40, // XK_Mabovedot: LATIN CAPITAL LETTER M WITH DOT ABOVE - 0x1001e41: 0x1E41, // XK_mabovedot: LATIN SMALL LETTER M WITH DOT ABOVE - 0x1001e56: 0x1E56, // XK_Pabovedot: LATIN CAPITAL LETTER P WITH DOT ABOVE - 0x1001e57: 0x1E57, // XK_pabovedot: LATIN SMALL LETTER P WITH DOT ABOVE - 0x1001e60: 0x1E60, // XK_Sabovedot: LATIN CAPITAL LETTER S WITH DOT ABOVE - 0x1001e61: 0x1E61, // XK_sabovedot: LATIN SMALL LETTER S WITH DOT ABOVE - 0x1001e6a: 0x1E6A, // XK_Tabovedot: LATIN CAPITAL LETTER T WITH DOT ABOVE - 0x1001e6b: 0x1E6B, // XK_tabovedot: LATIN SMALL LETTER T WITH DOT ABOVE - 0x1001e80: 0x1E80, // XK_Wgrave: LATIN CAPITAL LETTER W WITH GRAVE - 0x1001e81: 0x1E81, // XK_wgrave: LATIN SMALL LETTER W WITH GRAVE - 0x1001e82: 0x1E82, // XK_Wacute: LATIN CAPITAL LETTER W WITH ACUTE - 0x1001e83: 0x1E83, // XK_wacute: LATIN SMALL LETTER W WITH ACUTE - 0x1001e84: 0x1E84, // XK_Wdiaeresis: LATIN CAPITAL LETTER W WITH DIAERESIS - 0x1001e85: 0x1E85, // XK_wdiaeresis: LATIN SMALL LETTER W WITH DIAERESIS - 0x1001ef2: 0x1EF2, // XK_Ygrave: LATIN CAPITAL LETTER Y WITH GRAVE - 0x1001ef3: 0x1EF3, // XK_ygrave: LATIN SMALL LETTER Y WITH GRAVE - 0x13bc: 0x0152, // XK_OE: LATIN CAPITAL LIGATURE OE - 0x13bd: 0x0153, // XK_oe: LATIN SMALL LIGATURE OE - 0x13be: 0x0178, // XK_Ydiaeresis: LATIN CAPITAL LETTER Y WITH DIAERESIS - 0x047e: 0x203E, // XK_overline: OVERLINE - 0x04a1: 0x3002, // XK_kana_fullstop: IDEOGRAPHIC FULL STOP - 0x04a2: 0x300C, // XK_kana_openingbracket: LEFT CORNER BRACKET - 0x04a3: 0x300D, // XK_kana_closingbracket: RIGHT CORNER BRACKET - 0x04a4: 0x3001, // XK_kana_comma: IDEOGRAPHIC COMMA - 0x04a5: 0x30FB, // XK_kana_conjunctive: KATAKANA MIDDLE DOT - 0x04a6: 0x30F2, // XK_kana_WO: KATAKANA LETTER WO - 0x04a7: 0x30A1, // XK_kana_a: KATAKANA LETTER SMALL A - 0x04a8: 0x30A3, // XK_kana_i: KATAKANA LETTER SMALL I - 0x04a9: 0x30A5, // XK_kana_u: KATAKANA LETTER SMALL U - 0x04aa: 0x30A7, // XK_kana_e: KATAKANA LETTER SMALL E - 0x04ab: 0x30A9, // XK_kana_o: KATAKANA LETTER SMALL O - 0x04ac: 0x30E3, // XK_kana_ya: KATAKANA LETTER SMALL YA - 0x04ad: 0x30E5, // XK_kana_yu: KATAKANA LETTER SMALL YU - 0x04ae: 0x30E7, // XK_kana_yo: KATAKANA LETTER SMALL YO - 0x04af: 0x30C3, // XK_kana_tsu: KATAKANA LETTER SMALL TU - 0x04b0: 0x30FC, // XK_prolongedsound: KATAKANA-HIRAGANA PROLONGED SOUND MARK - 0x04b1: 0x30A2, // XK_kana_A: KATAKANA LETTER A - 0x04b2: 0x30A4, // XK_kana_I: KATAKANA LETTER I - 0x04b3: 0x30A6, // XK_kana_U: KATAKANA LETTER U - 0x04b4: 0x30A8, // XK_kana_E: KATAKANA LETTER E - 0x04b5: 0x30AA, // XK_kana_O: KATAKANA LETTER O - 0x04b6: 0x30AB, // XK_kana_KA: KATAKANA LETTER KA - 0x04b7: 0x30AD, // XK_kana_KI: KATAKANA LETTER KI - 0x04b8: 0x30AF, // XK_kana_KU: KATAKANA LETTER KU - 0x04b9: 0x30B1, // XK_kana_KE: KATAKANA LETTER KE - 0x04ba: 0x30B3, // XK_kana_KO: KATAKANA LETTER KO - 0x04bb: 0x30B5, // XK_kana_SA: KATAKANA LETTER SA - 0x04bc: 0x30B7, // XK_kana_SHI: KATAKANA LETTER SI - 0x04bd: 0x30B9, // XK_kana_SU: KATAKANA LETTER SU - 0x04be: 0x30BB, // XK_kana_SE: KATAKANA LETTER SE - 0x04bf: 0x30BD, // XK_kana_SO: KATAKANA LETTER SO - 0x04c0: 0x30BF, // XK_kana_TA: KATAKANA LETTER TA - 0x04c1: 0x30C1, // XK_kana_CHI: KATAKANA LETTER TI - 0x04c2: 0x30C4, // XK_kana_TSU: KATAKANA LETTER TU - 0x04c3: 0x30C6, // XK_kana_TE: KATAKANA LETTER TE - 0x04c4: 0x30C8, // XK_kana_TO: KATAKANA LETTER TO - 0x04c5: 0x30CA, // XK_kana_NA: KATAKANA LETTER NA - 0x04c6: 0x30CB, // XK_kana_NI: KATAKANA LETTER NI - 0x04c7: 0x30CC, // XK_kana_NU: KATAKANA LETTER NU - 0x04c8: 0x30CD, // XK_kana_NE: KATAKANA LETTER NE - 0x04c9: 0x30CE, // XK_kana_NO: KATAKANA LETTER NO - 0x04ca: 0x30CF, // XK_kana_HA: KATAKANA LETTER HA - 0x04cb: 0x30D2, // XK_kana_HI: KATAKANA LETTER HI - 0x04cc: 0x30D5, // XK_kana_FU: KATAKANA LETTER HU - 0x04cd: 0x30D8, // XK_kana_HE: KATAKANA LETTER HE - 0x04ce: 0x30DB, // XK_kana_HO: KATAKANA LETTER HO - 0x04cf: 0x30DE, // XK_kana_MA: KATAKANA LETTER MA - 0x04d0: 0x30DF, // XK_kana_MI: KATAKANA LETTER MI - 0x04d1: 0x30E0, // XK_kana_MU: KATAKANA LETTER MU - 0x04d2: 0x30E1, // XK_kana_ME: KATAKANA LETTER ME - 0x04d3: 0x30E2, // XK_kana_MO: KATAKANA LETTER MO - 0x04d4: 0x30E4, // XK_kana_YA: KATAKANA LETTER YA - 0x04d5: 0x30E6, // XK_kana_YU: KATAKANA LETTER YU - 0x04d6: 0x30E8, // XK_kana_YO: KATAKANA LETTER YO - 0x04d7: 0x30E9, // XK_kana_RA: KATAKANA LETTER RA - 0x04d8: 0x30EA, // XK_kana_RI: KATAKANA LETTER RI - 0x04d9: 0x30EB, // XK_kana_RU: KATAKANA LETTER RU - 0x04da: 0x30EC, // XK_kana_RE: KATAKANA LETTER RE - 0x04db: 0x30ED, // XK_kana_RO: KATAKANA LETTER RO - 0x04dc: 0x30EF, // XK_kana_WA: KATAKANA LETTER WA - 0x04dd: 0x30F3, // XK_kana_N: KATAKANA LETTER N - 0x04de: 0x309B, // XK_voicedsound: KATAKANA-HIRAGANA VOICED SOUND MARK - 0x04df: 0x309C, // XK_semivoicedsound: KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK - 0x10006f0: 0x06F0, // XK_Farsi_0: EXTENDED ARABIC-INDIC DIGIT ZERO - 0x10006f1: 0x06F1, // XK_Farsi_1: EXTENDED ARABIC-INDIC DIGIT ONE - 0x10006f2: 0x06F2, // XK_Farsi_2: EXTENDED ARABIC-INDIC DIGIT TWO - 0x10006f3: 0x06F3, // XK_Farsi_3: EXTENDED ARABIC-INDIC DIGIT THREE - 0x10006f4: 0x06F4, // XK_Farsi_4: EXTENDED ARABIC-INDIC DIGIT FOUR - 0x10006f5: 0x06F5, // XK_Farsi_5: EXTENDED ARABIC-INDIC DIGIT FIVE - 0x10006f6: 0x06F6, // XK_Farsi_6: EXTENDED ARABIC-INDIC DIGIT SIX - 0x10006f7: 0x06F7, // XK_Farsi_7: EXTENDED ARABIC-INDIC DIGIT SEVEN - 0x10006f8: 0x06F8, // XK_Farsi_8: EXTENDED ARABIC-INDIC DIGIT EIGHT - 0x10006f9: 0x06F9, // XK_Farsi_9: EXTENDED ARABIC-INDIC DIGIT NINE - 0x100066a: 0x066A, // XK_Arabic_percent: ARABIC PERCENT SIGN - 0x1000670: 0x0670, // XK_Arabic_superscript_alef: ARABIC LETTER SUPERSCRIPT ALEF - 0x1000679: 0x0679, // XK_Arabic_tteh: ARABIC LETTER TTEH - 0x100067e: 0x067E, // XK_Arabic_peh: ARABIC LETTER PEH - 0x1000686: 0x0686, // XK_Arabic_tcheh: ARABIC LETTER TCHEH - 0x1000688: 0x0688, // XK_Arabic_ddal: ARABIC LETTER DDAL - 0x1000691: 0x0691, // XK_Arabic_rreh: ARABIC LETTER RREH - 0x05ac: 0x060C, // XK_Arabic_comma: ARABIC COMMA - 0x10006d4: 0x06D4, // XK_Arabic_fullstop: ARABIC FULL STOP - 0x1000660: 0x0660, // XK_Arabic_0: ARABIC-INDIC DIGIT ZERO - 0x1000661: 0x0661, // XK_Arabic_1: ARABIC-INDIC DIGIT ONE - 0x1000662: 0x0662, // XK_Arabic_2: ARABIC-INDIC DIGIT TWO - 0x1000663: 0x0663, // XK_Arabic_3: ARABIC-INDIC DIGIT THREE - 0x1000664: 0x0664, // XK_Arabic_4: ARABIC-INDIC DIGIT FOUR - 0x1000665: 0x0665, // XK_Arabic_5: ARABIC-INDIC DIGIT FIVE - 0x1000666: 0x0666, // XK_Arabic_6: ARABIC-INDIC DIGIT SIX - 0x1000667: 0x0667, // XK_Arabic_7: ARABIC-INDIC DIGIT SEVEN - 0x1000668: 0x0668, // XK_Arabic_8: ARABIC-INDIC DIGIT EIGHT - 0x1000669: 0x0669, // XK_Arabic_9: ARABIC-INDIC DIGIT NINE - 0x05bb: 0x061B, // XK_Arabic_semicolon: ARABIC SEMICOLON - 0x05bf: 0x061F, // XK_Arabic_question_mark: ARABIC QUESTION MARK - 0x05c1: 0x0621, // XK_Arabic_hamza: ARABIC LETTER HAMZA - 0x05c2: 0x0622, // XK_Arabic_maddaonalef: ARABIC LETTER ALEF WITH MADDA ABOVE - 0x05c3: 0x0623, // XK_Arabic_hamzaonalef: ARABIC LETTER ALEF WITH HAMZA ABOVE - 0x05c4: 0x0624, // XK_Arabic_hamzaonwaw: ARABIC LETTER WAW WITH HAMZA ABOVE - 0x05c5: 0x0625, // XK_Arabic_hamzaunderalef: ARABIC LETTER ALEF WITH HAMZA BELOW - 0x05c6: 0x0626, // XK_Arabic_hamzaonyeh: ARABIC LETTER YEH WITH HAMZA ABOVE - 0x05c7: 0x0627, // XK_Arabic_alef: ARABIC LETTER ALEF - 0x05c8: 0x0628, // XK_Arabic_beh: ARABIC LETTER BEH - 0x05c9: 0x0629, // XK_Arabic_tehmarbuta: ARABIC LETTER TEH MARBUTA - 0x05ca: 0x062A, // XK_Arabic_teh: ARABIC LETTER TEH - 0x05cb: 0x062B, // XK_Arabic_theh: ARABIC LETTER THEH - 0x05cc: 0x062C, // XK_Arabic_jeem: ARABIC LETTER JEEM - 0x05cd: 0x062D, // XK_Arabic_hah: ARABIC LETTER HAH - 0x05ce: 0x062E, // XK_Arabic_khah: ARABIC LETTER KHAH - 0x05cf: 0x062F, // XK_Arabic_dal: ARABIC LETTER DAL - 0x05d0: 0x0630, // XK_Arabic_thal: ARABIC LETTER THAL - 0x05d1: 0x0631, // XK_Arabic_ra: ARABIC LETTER REH - 0x05d2: 0x0632, // XK_Arabic_zain: ARABIC LETTER ZAIN - 0x05d3: 0x0633, // XK_Arabic_seen: ARABIC LETTER SEEN - 0x05d4: 0x0634, // XK_Arabic_sheen: ARABIC LETTER SHEEN - 0x05d5: 0x0635, // XK_Arabic_sad: ARABIC LETTER SAD - 0x05d6: 0x0636, // XK_Arabic_dad: ARABIC LETTER DAD - 0x05d7: 0x0637, // XK_Arabic_tah: ARABIC LETTER TAH - 0x05d8: 0x0638, // XK_Arabic_zah: ARABIC LETTER ZAH - 0x05d9: 0x0639, // XK_Arabic_ain: ARABIC LETTER AIN - 0x05da: 0x063A, // XK_Arabic_ghain: ARABIC LETTER GHAIN - 0x05e0: 0x0640, // XK_Arabic_tatweel: ARABIC TATWEEL - 0x05e1: 0x0641, // XK_Arabic_feh: ARABIC LETTER FEH - 0x05e2: 0x0642, // XK_Arabic_qaf: ARABIC LETTER QAF - 0x05e3: 0x0643, // XK_Arabic_kaf: ARABIC LETTER KAF - 0x05e4: 0x0644, // XK_Arabic_lam: ARABIC LETTER LAM - 0x05e5: 0x0645, // XK_Arabic_meem: ARABIC LETTER MEEM - 0x05e6: 0x0646, // XK_Arabic_noon: ARABIC LETTER NOON - 0x05e7: 0x0647, // XK_Arabic_ha: ARABIC LETTER HEH - 0x05e8: 0x0648, // XK_Arabic_waw: ARABIC LETTER WAW - 0x05e9: 0x0649, // XK_Arabic_alefmaksura: ARABIC LETTER ALEF MAKSURA - 0x05ea: 0x064A, // XK_Arabic_yeh: ARABIC LETTER YEH - 0x05eb: 0x064B, // XK_Arabic_fathatan: ARABIC FATHATAN - 0x05ec: 0x064C, // XK_Arabic_dammatan: ARABIC DAMMATAN - 0x05ed: 0x064D, // XK_Arabic_kasratan: ARABIC KASRATAN - 0x05ee: 0x064E, // XK_Arabic_fatha: ARABIC FATHA - 0x05ef: 0x064F, // XK_Arabic_damma: ARABIC DAMMA - 0x05f0: 0x0650, // XK_Arabic_kasra: ARABIC KASRA - 0x05f1: 0x0651, // XK_Arabic_shadda: ARABIC SHADDA - 0x05f2: 0x0652, // XK_Arabic_sukun: ARABIC SUKUN - 0x1000653: 0x0653, // XK_Arabic_madda_above: ARABIC MADDAH ABOVE - 0x1000654: 0x0654, // XK_Arabic_hamza_above: ARABIC HAMZA ABOVE - 0x1000655: 0x0655, // XK_Arabic_hamza_below: ARABIC HAMZA BELOW - 0x1000698: 0x0698, // XK_Arabic_jeh: ARABIC LETTER JEH - 0x10006a4: 0x06A4, // XK_Arabic_veh: ARABIC LETTER VEH - 0x10006a9: 0x06A9, // XK_Arabic_keheh: ARABIC LETTER KEHEH - 0x10006af: 0x06AF, // XK_Arabic_gaf: ARABIC LETTER GAF - 0x10006ba: 0x06BA, // XK_Arabic_noon_ghunna: ARABIC LETTER NOON GHUNNA - 0x10006be: 0x06BE, // XK_Arabic_heh_doachashmee: ARABIC LETTER HEH DOACHASHMEE - 0x10006cc: 0x06CC, // XK_Farsi_yeh: ARABIC LETTER FARSI YEH - 0x10006d2: 0x06D2, // XK_Arabic_yeh_baree: ARABIC LETTER YEH BARREE - 0x10006c1: 0x06C1, // XK_Arabic_heh_goal: ARABIC LETTER HEH GOAL - 0x1000492: 0x0492, // XK_Cyrillic_GHE_bar: CYRILLIC CAPITAL LETTER GHE WITH STROKE - 0x1000493: 0x0493, // XK_Cyrillic_ghe_bar: CYRILLIC SMALL LETTER GHE WITH STROKE - 0x1000496: 0x0496, // XK_Cyrillic_ZHE_descender: CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER - 0x1000497: 0x0497, // XK_Cyrillic_zhe_descender: CYRILLIC SMALL LETTER ZHE WITH DESCENDER - 0x100049a: 0x049A, // XK_Cyrillic_KA_descender: CYRILLIC CAPITAL LETTER KA WITH DESCENDER - 0x100049b: 0x049B, // XK_Cyrillic_ka_descender: CYRILLIC SMALL LETTER KA WITH DESCENDER - 0x100049c: 0x049C, // XK_Cyrillic_KA_vertstroke: CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE - 0x100049d: 0x049D, // XK_Cyrillic_ka_vertstroke: CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE - 0x10004a2: 0x04A2, // XK_Cyrillic_EN_descender: CYRILLIC CAPITAL LETTER EN WITH DESCENDER - 0x10004a3: 0x04A3, // XK_Cyrillic_en_descender: CYRILLIC SMALL LETTER EN WITH DESCENDER - 0x10004ae: 0x04AE, // XK_Cyrillic_U_straight: CYRILLIC CAPITAL LETTER STRAIGHT U - 0x10004af: 0x04AF, // XK_Cyrillic_u_straight: CYRILLIC SMALL LETTER STRAIGHT U - 0x10004b0: 0x04B0, // XK_Cyrillic_U_straight_bar: CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE - 0x10004b1: 0x04B1, // XK_Cyrillic_u_straight_bar: CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE - 0x10004b2: 0x04B2, // XK_Cyrillic_HA_descender: CYRILLIC CAPITAL LETTER HA WITH DESCENDER - 0x10004b3: 0x04B3, // XK_Cyrillic_ha_descender: CYRILLIC SMALL LETTER HA WITH DESCENDER - 0x10004b6: 0x04B6, // XK_Cyrillic_CHE_descender: CYRILLIC CAPITAL LETTER CHE WITH DESCENDER - 0x10004b7: 0x04B7, // XK_Cyrillic_che_descender: CYRILLIC SMALL LETTER CHE WITH DESCENDER - 0x10004b8: 0x04B8, // XK_Cyrillic_CHE_vertstroke: CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE - 0x10004b9: 0x04B9, // XK_Cyrillic_che_vertstroke: CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE - 0x10004ba: 0x04BA, // XK_Cyrillic_SHHA: CYRILLIC CAPITAL LETTER SHHA - 0x10004bb: 0x04BB, // XK_Cyrillic_shha: CYRILLIC SMALL LETTER SHHA - 0x10004d8: 0x04D8, // XK_Cyrillic_SCHWA: CYRILLIC CAPITAL LETTER SCHWA - 0x10004d9: 0x04D9, // XK_Cyrillic_schwa: CYRILLIC SMALL LETTER SCHWA - 0x10004e2: 0x04E2, // XK_Cyrillic_I_macron: CYRILLIC CAPITAL LETTER I WITH MACRON - 0x10004e3: 0x04E3, // XK_Cyrillic_i_macron: CYRILLIC SMALL LETTER I WITH MACRON - 0x10004e8: 0x04E8, // XK_Cyrillic_O_bar: CYRILLIC CAPITAL LETTER BARRED O - 0x10004e9: 0x04E9, // XK_Cyrillic_o_bar: CYRILLIC SMALL LETTER BARRED O - 0x10004ee: 0x04EE, // XK_Cyrillic_U_macron: CYRILLIC CAPITAL LETTER U WITH MACRON - 0x10004ef: 0x04EF, // XK_Cyrillic_u_macron: CYRILLIC SMALL LETTER U WITH MACRON - 0x06a1: 0x0452, // XK_Serbian_dje: CYRILLIC SMALL LETTER DJE - 0x06a2: 0x0453, // XK_Macedonia_gje: CYRILLIC SMALL LETTER GJE - 0x06a3: 0x0451, // XK_Cyrillic_io: CYRILLIC SMALL LETTER IO - 0x06a4: 0x0454, // XK_Ukrainian_ie: CYRILLIC SMALL LETTER UKRAINIAN IE - 0x06a5: 0x0455, // XK_Macedonia_dse: CYRILLIC SMALL LETTER DZE - 0x06a6: 0x0456, // XK_Ukrainian_i: CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I - 0x06a7: 0x0457, // XK_Ukrainian_yi: CYRILLIC SMALL LETTER YI - 0x06a8: 0x0458, // XK_Cyrillic_je: CYRILLIC SMALL LETTER JE - 0x06a9: 0x0459, // XK_Cyrillic_lje: CYRILLIC SMALL LETTER LJE - 0x06aa: 0x045A, // XK_Cyrillic_nje: CYRILLIC SMALL LETTER NJE - 0x06ab: 0x045B, // XK_Serbian_tshe: CYRILLIC SMALL LETTER TSHE - 0x06ac: 0x045C, // XK_Macedonia_kje: CYRILLIC SMALL LETTER KJE - 0x06ad: 0x0491, // XK_Ukrainian_ghe_with_upturn: CYRILLIC SMALL LETTER GHE WITH UPTURN - 0x06ae: 0x045E, // XK_Byelorussian_shortu: CYRILLIC SMALL LETTER SHORT U - 0x06af: 0x045F, // XK_Cyrillic_dzhe: CYRILLIC SMALL LETTER DZHE - 0x06b0: 0x2116, // XK_numerosign: NUMERO SIGN - 0x06b1: 0x0402, // XK_Serbian_DJE: CYRILLIC CAPITAL LETTER DJE - 0x06b2: 0x0403, // XK_Macedonia_GJE: CYRILLIC CAPITAL LETTER GJE - 0x06b3: 0x0401, // XK_Cyrillic_IO: CYRILLIC CAPITAL LETTER IO - 0x06b4: 0x0404, // XK_Ukrainian_IE: CYRILLIC CAPITAL LETTER UKRAINIAN IE - 0x06b5: 0x0405, // XK_Macedonia_DSE: CYRILLIC CAPITAL LETTER DZE - 0x06b6: 0x0406, // XK_Ukrainian_I: CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I - 0x06b7: 0x0407, // XK_Ukrainian_YI: CYRILLIC CAPITAL LETTER YI - 0x06b8: 0x0408, // XK_Cyrillic_JE: CYRILLIC CAPITAL LETTER JE - 0x06b9: 0x0409, // XK_Cyrillic_LJE: CYRILLIC CAPITAL LETTER LJE - 0x06ba: 0x040A, // XK_Cyrillic_NJE: CYRILLIC CAPITAL LETTER NJE - 0x06bb: 0x040B, // XK_Serbian_TSHE: CYRILLIC CAPITAL LETTER TSHE - 0x06bc: 0x040C, // XK_Macedonia_KJE: CYRILLIC CAPITAL LETTER KJE - 0x06bd: 0x0490, // XK_Ukrainian_GHE_WITH_UPTURN: CYRILLIC CAPITAL LETTER GHE WITH UPTURN - 0x06be: 0x040E, // XK_Byelorussian_SHORTU: CYRILLIC CAPITAL LETTER SHORT U - 0x06bf: 0x040F, // XK_Cyrillic_DZHE: CYRILLIC CAPITAL LETTER DZHE - 0x06c0: 0x044E, // XK_Cyrillic_yu: CYRILLIC SMALL LETTER YU - 0x06c1: 0x0430, // XK_Cyrillic_a: CYRILLIC SMALL LETTER A - 0x06c2: 0x0431, // XK_Cyrillic_be: CYRILLIC SMALL LETTER BE - 0x06c3: 0x0446, // XK_Cyrillic_tse: CYRILLIC SMALL LETTER TSE - 0x06c4: 0x0434, // XK_Cyrillic_de: CYRILLIC SMALL LETTER DE - 0x06c5: 0x0435, // XK_Cyrillic_ie: CYRILLIC SMALL LETTER IE - 0x06c6: 0x0444, // XK_Cyrillic_ef: CYRILLIC SMALL LETTER EF - 0x06c7: 0x0433, // XK_Cyrillic_ghe: CYRILLIC SMALL LETTER GHE - 0x06c8: 0x0445, // XK_Cyrillic_ha: CYRILLIC SMALL LETTER HA - 0x06c9: 0x0438, // XK_Cyrillic_i: CYRILLIC SMALL LETTER I - 0x06ca: 0x0439, // XK_Cyrillic_shorti: CYRILLIC SMALL LETTER SHORT I - 0x06cb: 0x043A, // XK_Cyrillic_ka: CYRILLIC SMALL LETTER KA - 0x06cc: 0x043B, // XK_Cyrillic_el: CYRILLIC SMALL LETTER EL - 0x06cd: 0x043C, // XK_Cyrillic_em: CYRILLIC SMALL LETTER EM - 0x06ce: 0x043D, // XK_Cyrillic_en: CYRILLIC SMALL LETTER EN - 0x06cf: 0x043E, // XK_Cyrillic_o: CYRILLIC SMALL LETTER O - 0x06d0: 0x043F, // XK_Cyrillic_pe: CYRILLIC SMALL LETTER PE - 0x06d1: 0x044F, // XK_Cyrillic_ya: CYRILLIC SMALL LETTER YA - 0x06d2: 0x0440, // XK_Cyrillic_er: CYRILLIC SMALL LETTER ER - 0x06d3: 0x0441, // XK_Cyrillic_es: CYRILLIC SMALL LETTER ES - 0x06d4: 0x0442, // XK_Cyrillic_te: CYRILLIC SMALL LETTER TE - 0x06d5: 0x0443, // XK_Cyrillic_u: CYRILLIC SMALL LETTER U - 0x06d6: 0x0436, // XK_Cyrillic_zhe: CYRILLIC SMALL LETTER ZHE - 0x06d7: 0x0432, // XK_Cyrillic_ve: CYRILLIC SMALL LETTER VE - 0x06d8: 0x044C, // XK_Cyrillic_softsign: CYRILLIC SMALL LETTER SOFT SIGN - 0x06d9: 0x044B, // XK_Cyrillic_yeru: CYRILLIC SMALL LETTER YERU - 0x06da: 0x0437, // XK_Cyrillic_ze: CYRILLIC SMALL LETTER ZE - 0x06db: 0x0448, // XK_Cyrillic_sha: CYRILLIC SMALL LETTER SHA - 0x06dc: 0x044D, // XK_Cyrillic_e: CYRILLIC SMALL LETTER E - 0x06dd: 0x0449, // XK_Cyrillic_shcha: CYRILLIC SMALL LETTER SHCHA - 0x06de: 0x0447, // XK_Cyrillic_che: CYRILLIC SMALL LETTER CHE - 0x06df: 0x044A, // XK_Cyrillic_hardsign: CYRILLIC SMALL LETTER HARD SIGN - 0x06e0: 0x042E, // XK_Cyrillic_YU: CYRILLIC CAPITAL LETTER YU - 0x06e1: 0x0410, // XK_Cyrillic_A: CYRILLIC CAPITAL LETTER A - 0x06e2: 0x0411, // XK_Cyrillic_BE: CYRILLIC CAPITAL LETTER BE - 0x06e3: 0x0426, // XK_Cyrillic_TSE: CYRILLIC CAPITAL LETTER TSE - 0x06e4: 0x0414, // XK_Cyrillic_DE: CYRILLIC CAPITAL LETTER DE - 0x06e5: 0x0415, // XK_Cyrillic_IE: CYRILLIC CAPITAL LETTER IE - 0x06e6: 0x0424, // XK_Cyrillic_EF: CYRILLIC CAPITAL LETTER EF - 0x06e7: 0x0413, // XK_Cyrillic_GHE: CYRILLIC CAPITAL LETTER GHE - 0x06e8: 0x0425, // XK_Cyrillic_HA: CYRILLIC CAPITAL LETTER HA - 0x06e9: 0x0418, // XK_Cyrillic_I: CYRILLIC CAPITAL LETTER I - 0x06ea: 0x0419, // XK_Cyrillic_SHORTI: CYRILLIC CAPITAL LETTER SHORT I - 0x06eb: 0x041A, // XK_Cyrillic_KA: CYRILLIC CAPITAL LETTER KA - 0x06ec: 0x041B, // XK_Cyrillic_EL: CYRILLIC CAPITAL LETTER EL - 0x06ed: 0x041C, // XK_Cyrillic_EM: CYRILLIC CAPITAL LETTER EM - 0x06ee: 0x041D, // XK_Cyrillic_EN: CYRILLIC CAPITAL LETTER EN - 0x06ef: 0x041E, // XK_Cyrillic_O: CYRILLIC CAPITAL LETTER O - 0x06f0: 0x041F, // XK_Cyrillic_PE: CYRILLIC CAPITAL LETTER PE - 0x06f1: 0x042F, // XK_Cyrillic_YA: CYRILLIC CAPITAL LETTER YA - 0x06f2: 0x0420, // XK_Cyrillic_ER: CYRILLIC CAPITAL LETTER ER - 0x06f3: 0x0421, // XK_Cyrillic_ES: CYRILLIC CAPITAL LETTER ES - 0x06f4: 0x0422, // XK_Cyrillic_TE: CYRILLIC CAPITAL LETTER TE - 0x06f5: 0x0423, // XK_Cyrillic_U: CYRILLIC CAPITAL LETTER U - 0x06f6: 0x0416, // XK_Cyrillic_ZHE: CYRILLIC CAPITAL LETTER ZHE - 0x06f7: 0x0412, // XK_Cyrillic_VE: CYRILLIC CAPITAL LETTER VE - 0x06f8: 0x042C, // XK_Cyrillic_SOFTSIGN: CYRILLIC CAPITAL LETTER SOFT SIGN - 0x06f9: 0x042B, // XK_Cyrillic_YERU: CYRILLIC CAPITAL LETTER YERU - 0x06fa: 0x0417, // XK_Cyrillic_ZE: CYRILLIC CAPITAL LETTER ZE - 0x06fb: 0x0428, // XK_Cyrillic_SHA: CYRILLIC CAPITAL LETTER SHA - 0x06fc: 0x042D, // XK_Cyrillic_E: CYRILLIC CAPITAL LETTER E - 0x06fd: 0x0429, // XK_Cyrillic_SHCHA: CYRILLIC CAPITAL LETTER SHCHA - 0x06fe: 0x0427, // XK_Cyrillic_CHE: CYRILLIC CAPITAL LETTER CHE - 0x06ff: 0x042A, // XK_Cyrillic_HARDSIGN: CYRILLIC CAPITAL LETTER HARD SIGN - 0x07a1: 0x0386, // XK_Greek_ALPHAaccent: GREEK CAPITAL LETTER ALPHA WITH TONOS - 0x07a2: 0x0388, // XK_Greek_EPSILONaccent: GREEK CAPITAL LETTER EPSILON WITH TONOS - 0x07a3: 0x0389, // XK_Greek_ETAaccent: GREEK CAPITAL LETTER ETA WITH TONOS - 0x07a4: 0x038A, // XK_Greek_IOTAaccent: GREEK CAPITAL LETTER IOTA WITH TONOS - 0x07a5: 0x03AA, // XK_Greek_IOTAdieresis: GREEK CAPITAL LETTER IOTA WITH DIALYTIKA - 0x07a7: 0x038C, // XK_Greek_OMICRONaccent: GREEK CAPITAL LETTER OMICRON WITH TONOS - 0x07a8: 0x038E, // XK_Greek_UPSILONaccent: GREEK CAPITAL LETTER UPSILON WITH TONOS - 0x07a9: 0x03AB, // XK_Greek_UPSILONdieresis: GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA - 0x07ab: 0x038F, // XK_Greek_OMEGAaccent: GREEK CAPITAL LETTER OMEGA WITH TONOS - 0x07ae: 0x0385, // XK_Greek_accentdieresis: GREEK DIALYTIKA TONOS - 0x07af: 0x2015, // XK_Greek_horizbar: HORIZONTAL BAR - 0x07b1: 0x03AC, // XK_Greek_alphaaccent: GREEK SMALL LETTER ALPHA WITH TONOS - 0x07b2: 0x03AD, // XK_Greek_epsilonaccent: GREEK SMALL LETTER EPSILON WITH TONOS - 0x07b3: 0x03AE, // XK_Greek_etaaccent: GREEK SMALL LETTER ETA WITH TONOS - 0x07b4: 0x03AF, // XK_Greek_iotaaccent: GREEK SMALL LETTER IOTA WITH TONOS - 0x07b5: 0x03CA, // XK_Greek_iotadieresis: GREEK SMALL LETTER IOTA WITH DIALYTIKA - 0x07b6: 0x0390, // XK_Greek_iotaaccentdieresis: GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS - 0x07b7: 0x03CC, // XK_Greek_omicronaccent: GREEK SMALL LETTER OMICRON WITH TONOS - 0x07b8: 0x03CD, // XK_Greek_upsilonaccent: GREEK SMALL LETTER UPSILON WITH TONOS - 0x07b9: 0x03CB, // XK_Greek_upsilondieresis: GREEK SMALL LETTER UPSILON WITH DIALYTIKA - 0x07ba: 0x03B0, // XK_Greek_upsilonaccentdieresis: GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS - 0x07bb: 0x03CE, // XK_Greek_omegaaccent: GREEK SMALL LETTER OMEGA WITH TONOS - 0x07c1: 0x0391, // XK_Greek_ALPHA: GREEK CAPITAL LETTER ALPHA - 0x07c2: 0x0392, // XK_Greek_BETA: GREEK CAPITAL LETTER BETA - 0x07c3: 0x0393, // XK_Greek_GAMMA: GREEK CAPITAL LETTER GAMMA - 0x07c4: 0x0394, // XK_Greek_DELTA: GREEK CAPITAL LETTER DELTA - 0x07c5: 0x0395, // XK_Greek_EPSILON: GREEK CAPITAL LETTER EPSILON - 0x07c6: 0x0396, // XK_Greek_ZETA: GREEK CAPITAL LETTER ZETA - 0x07c7: 0x0397, // XK_Greek_ETA: GREEK CAPITAL LETTER ETA - 0x07c8: 0x0398, // XK_Greek_THETA: GREEK CAPITAL LETTER THETA - 0x07c9: 0x0399, // XK_Greek_IOTA: GREEK CAPITAL LETTER IOTA - 0x07ca: 0x039A, // XK_Greek_KAPPA: GREEK CAPITAL LETTER KAPPA - 0x07cb: 0x039B, // XK_Greek_LAMDA: GREEK CAPITAL LETTER LAMDA - 0x07cc: 0x039C, // XK_Greek_MU: GREEK CAPITAL LETTER MU - 0x07cd: 0x039D, // XK_Greek_NU: GREEK CAPITAL LETTER NU - 0x07ce: 0x039E, // XK_Greek_XI: GREEK CAPITAL LETTER XI - 0x07cf: 0x039F, // XK_Greek_OMICRON: GREEK CAPITAL LETTER OMICRON - 0x07d0: 0x03A0, // XK_Greek_PI: GREEK CAPITAL LETTER PI - 0x07d1: 0x03A1, // XK_Greek_RHO: GREEK CAPITAL LETTER RHO - 0x07d2: 0x03A3, // XK_Greek_SIGMA: GREEK CAPITAL LETTER SIGMA - 0x07d4: 0x03A4, // XK_Greek_TAU: GREEK CAPITAL LETTER TAU - 0x07d5: 0x03A5, // XK_Greek_UPSILON: GREEK CAPITAL LETTER UPSILON - 0x07d6: 0x03A6, // XK_Greek_PHI: GREEK CAPITAL LETTER PHI - 0x07d7: 0x03A7, // XK_Greek_CHI: GREEK CAPITAL LETTER CHI - 0x07d8: 0x03A8, // XK_Greek_PSI: GREEK CAPITAL LETTER PSI - 0x07d9: 0x03A9, // XK_Greek_OMEGA: GREEK CAPITAL LETTER OMEGA - 0x07e1: 0x03B1, // XK_Greek_alpha: GREEK SMALL LETTER ALPHA - 0x07e2: 0x03B2, // XK_Greek_beta: GREEK SMALL LETTER BETA - 0x07e3: 0x03B3, // XK_Greek_gamma: GREEK SMALL LETTER GAMMA - 0x07e4: 0x03B4, // XK_Greek_delta: GREEK SMALL LETTER DELTA - 0x07e5: 0x03B5, // XK_Greek_epsilon: GREEK SMALL LETTER EPSILON - 0x07e6: 0x03B6, // XK_Greek_zeta: GREEK SMALL LETTER ZETA - 0x07e7: 0x03B7, // XK_Greek_eta: GREEK SMALL LETTER ETA - 0x07e8: 0x03B8, // XK_Greek_theta: GREEK SMALL LETTER THETA - 0x07e9: 0x03B9, // XK_Greek_iota: GREEK SMALL LETTER IOTA - 0x07ea: 0x03BA, // XK_Greek_kappa: GREEK SMALL LETTER KAPPA - 0x07eb: 0x03BB, // XK_Greek_lamda: GREEK SMALL LETTER LAMDA - 0x07ec: 0x03BC, // XK_Greek_mu: GREEK SMALL LETTER MU - 0x07ed: 0x03BD, // XK_Greek_nu: GREEK SMALL LETTER NU - 0x07ee: 0x03BE, // XK_Greek_xi: GREEK SMALL LETTER XI - 0x07ef: 0x03BF, // XK_Greek_omicron: GREEK SMALL LETTER OMICRON - 0x07f0: 0x03C0, // XK_Greek_pi: GREEK SMALL LETTER PI - 0x07f1: 0x03C1, // XK_Greek_rho: GREEK SMALL LETTER RHO - 0x07f2: 0x03C3, // XK_Greek_sigma: GREEK SMALL LETTER SIGMA - 0x07f3: 0x03C2, // XK_Greek_finalsmallsigma: GREEK SMALL LETTER FINAL SIGMA - 0x07f4: 0x03C4, // XK_Greek_tau: GREEK SMALL LETTER TAU - 0x07f5: 0x03C5, // XK_Greek_upsilon: GREEK SMALL LETTER UPSILON - 0x07f6: 0x03C6, // XK_Greek_phi: GREEK SMALL LETTER PHI - 0x07f7: 0x03C7, // XK_Greek_chi: GREEK SMALL LETTER CHI - 0x07f8: 0x03C8, // XK_Greek_psi: GREEK SMALL LETTER PSI - 0x07f9: 0x03C9, // XK_Greek_omega: GREEK SMALL LETTER OMEGA - 0x08a1: 0x23B7, // XK_leftradical: RADICAL SYMBOL BOTTOM - 0x08a2: 0x250C, // XK_topleftradical: BOX DRAWINGS LIGHT DOWN AND RIGHT - 0x08a3: 0x2500, // XK_horizconnector: BOX DRAWINGS LIGHT HORIZONTAL - 0x08a4: 0x2320, // XK_topintegral: TOP HALF INTEGRAL - 0x08a5: 0x2321, // XK_botintegral: BOTTOM HALF INTEGRAL - 0x08a6: 0x2502, // XK_vertconnector: BOX DRAWINGS LIGHT VERTICAL - 0x08a7: 0x23A1, // XK_topleftsqbracket: LEFT SQUARE BRACKET UPPER CORNER - 0x08a8: 0x23A3, // XK_botleftsqbracket: LEFT SQUARE BRACKET LOWER CORNER - 0x08a9: 0x23A4, // XK_toprightsqbracket: RIGHT SQUARE BRACKET UPPER CORNER - 0x08aa: 0x23A6, // XK_botrightsqbracket: RIGHT SQUARE BRACKET LOWER CORNER - 0x08ab: 0x239B, // XK_topleftparens: LEFT PARENTHESIS UPPER HOOK - 0x08ac: 0x239D, // XK_botleftparens: LEFT PARENTHESIS LOWER HOOK - 0x08ad: 0x239E, // XK_toprightparens: RIGHT PARENTHESIS UPPER HOOK - 0x08ae: 0x23A0, // XK_botrightparens: RIGHT PARENTHESIS LOWER HOOK - 0x08af: 0x23A8, // XK_leftmiddlecurlybrace: LEFT CURLY BRACKET MIDDLE PIECE - 0x08b0: 0x23AC, // XK_rightmiddlecurlybrace: RIGHT CURLY BRACKET MIDDLE PIECE - 0x08bc: 0x2264, // XK_lessthanequal: LESS-THAN OR EQUAL TO - 0x08bd: 0x2260, // XK_notequal: NOT EQUAL TO - 0x08be: 0x2265, // XK_greaterthanequal: GREATER-THAN OR EQUAL TO - 0x08bf: 0x222B, // XK_integral: INTEGRAL - 0x08c0: 0x2234, // XK_therefore: THEREFORE - 0x08c1: 0x221D, // XK_variation: PROPORTIONAL TO - 0x08c2: 0x221E, // XK_infinity: INFINITY - 0x08c5: 0x2207, // XK_nabla: NABLA - 0x08c8: 0x223C, // XK_approximate: TILDE OPERATOR - 0x08c9: 0x2243, // XK_similarequal: ASYMPTOTICALLY EQUAL TO - 0x08cd: 0x21D4, // XK_ifonlyif: LEFT RIGHT DOUBLE ARROW - 0x08ce: 0x21D2, // XK_implies: RIGHTWARDS DOUBLE ARROW - 0x08cf: 0x2261, // XK_identical: IDENTICAL TO - 0x08d6: 0x221A, // XK_radical: SQUARE ROOT - 0x08da: 0x2282, // XK_includedin: SUBSET OF - 0x08db: 0x2283, // XK_includes: SUPERSET OF - 0x08dc: 0x2229, // XK_intersection: INTERSECTION - 0x08dd: 0x222A, // XK_union: UNION - 0x08de: 0x2227, // XK_logicaland: LOGICAL AND - 0x08df: 0x2228, // XK_logicalor: LOGICAL OR - 0x08ef: 0x2202, // XK_partialderivative: PARTIAL DIFFERENTIAL - 0x08f6: 0x0192, // XK_function: LATIN SMALL LETTER F WITH HOOK - 0x08fb: 0x2190, // XK_leftarrow: LEFTWARDS ARROW - 0x08fc: 0x2191, // XK_uparrow: UPWARDS ARROW - 0x08fd: 0x2192, // XK_rightarrow: RIGHTWARDS ARROW - 0x08fe: 0x2193, // XK_downarrow: DOWNWARDS ARROW - 0x09e0: 0x25C6, // XK_soliddiamond: BLACK DIAMOND - 0x09e1: 0x2592, // XK_checkerboard: MEDIUM SHADE - 0x09e2: 0x2409, // XK_ht: SYMBOL FOR HORIZONTAL TABULATION - 0x09e3: 0x240C, // XK_ff: SYMBOL FOR FORM FEED - 0x09e4: 0x240D, // XK_cr: SYMBOL FOR CARRIAGE RETURN - 0x09e5: 0x240A, // XK_lf: SYMBOL FOR LINE FEED - 0x09e8: 0x2424, // XK_nl: SYMBOL FOR NEWLINE - 0x09e9: 0x240B, // XK_vt: SYMBOL FOR VERTICAL TABULATION - 0x09ea: 0x2518, // XK_lowrightcorner: BOX DRAWINGS LIGHT UP AND LEFT - 0x09eb: 0x2510, // XK_uprightcorner: BOX DRAWINGS LIGHT DOWN AND LEFT - 0x09ec: 0x250C, // XK_upleftcorner: BOX DRAWINGS LIGHT DOWN AND RIGHT - 0x09ed: 0x2514, // XK_lowleftcorner: BOX DRAWINGS LIGHT UP AND RIGHT - 0x09ee: 0x253C, // XK_crossinglines: BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - 0x09ef: 0x23BA, // XK_horizlinescan1: HORIZONTAL SCAN LINE-1 - 0x09f0: 0x23BB, // XK_horizlinescan3: HORIZONTAL SCAN LINE-3 - 0x09f1: 0x2500, // XK_horizlinescan5: BOX DRAWINGS LIGHT HORIZONTAL - 0x09f2: 0x23BC, // XK_horizlinescan7: HORIZONTAL SCAN LINE-7 - 0x09f3: 0x23BD, // XK_horizlinescan9: HORIZONTAL SCAN LINE-9 - 0x09f4: 0x251C, // XK_leftt: BOX DRAWINGS LIGHT VERTICAL AND RIGHT - 0x09f5: 0x2524, // XK_rightt: BOX DRAWINGS LIGHT VERTICAL AND LEFT - 0x09f6: 0x2534, // XK_bott: BOX DRAWINGS LIGHT UP AND HORIZONTAL - 0x09f7: 0x252C, // XK_topt: BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - 0x09f8: 0x2502, // XK_vertbar: BOX DRAWINGS LIGHT VERTICAL - 0x0aa1: 0x2003, // XK_emspace: EM SPACE - 0x0aa2: 0x2002, // XK_enspace: EN SPACE - 0x0aa3: 0x2004, // XK_em3space: THREE-PER-EM SPACE - 0x0aa4: 0x2005, // XK_em4space: FOUR-PER-EM SPACE - 0x0aa5: 0x2007, // XK_digitspace: FIGURE SPACE - 0x0aa6: 0x2008, // XK_punctspace: PUNCTUATION SPACE - 0x0aa7: 0x2009, // XK_thinspace: THIN SPACE - 0x0aa8: 0x200A, // XK_hairspace: HAIR SPACE - 0x0aa9: 0x2014, // XK_emdash: EM DASH - 0x0aaa: 0x2013, // XK_endash: EN DASH - 0x0aac: 0x2423, // XK_signifblank: OPEN BOX - 0x0aae: 0x2026, // XK_ellipsis: HORIZONTAL ELLIPSIS - 0x0aaf: 0x2025, // XK_doubbaselinedot: TWO DOT LEADER - 0x0ab0: 0x2153, // XK_onethird: VULGAR FRACTION ONE THIRD - 0x0ab1: 0x2154, // XK_twothirds: VULGAR FRACTION TWO THIRDS - 0x0ab2: 0x2155, // XK_onefifth: VULGAR FRACTION ONE FIFTH - 0x0ab3: 0x2156, // XK_twofifths: VULGAR FRACTION TWO FIFTHS - 0x0ab4: 0x2157, // XK_threefifths: VULGAR FRACTION THREE FIFTHS - 0x0ab5: 0x2158, // XK_fourfifths: VULGAR FRACTION FOUR FIFTHS - 0x0ab6: 0x2159, // XK_onesixth: VULGAR FRACTION ONE SIXTH - 0x0ab7: 0x215A, // XK_fivesixths: VULGAR FRACTION FIVE SIXTHS - 0x0ab8: 0x2105, // XK_careof: CARE OF - 0x0abb: 0x2012, // XK_figdash: FIGURE DASH - 0x0abc: 0x27E8, // XK_leftanglebracket: MATHEMATICAL LEFT ANGLE BRACKET - 0x0abd: 0x002E, // XK_decimalpoint: FULL STOP - 0x0abe: 0x27E9, // XK_rightanglebracket: MATHEMATICAL RIGHT ANGLE BRACKET - 0x0ac3: 0x215B, // XK_oneeighth: VULGAR FRACTION ONE EIGHTH - 0x0ac4: 0x215C, // XK_threeeighths: VULGAR FRACTION THREE EIGHTHS - 0x0ac5: 0x215D, // XK_fiveeighths: VULGAR FRACTION FIVE EIGHTHS - 0x0ac6: 0x215E, // XK_seveneighths: VULGAR FRACTION SEVEN EIGHTHS - 0x0ac9: 0x2122, // XK_trademark: TRADE MARK SIGN - 0x0aca: 0x2613, // XK_signaturemark: SALTIRE - 0x0acc: 0x25C1, // XK_leftopentriangle: WHITE LEFT-POINTING TRIANGLE - 0x0acd: 0x25B7, // XK_rightopentriangle: WHITE RIGHT-POINTING TRIANGLE - 0x0ace: 0x25CB, // XK_emopencircle: WHITE CIRCLE - 0x0acf: 0x25AF, // XK_emopenrectangle: WHITE VERTICAL RECTANGLE - 0x0ad0: 0x2018, // XK_leftsinglequotemark: LEFT SINGLE QUOTATION MARK - 0x0ad1: 0x2019, // XK_rightsinglequotemark: RIGHT SINGLE QUOTATION MARK - 0x0ad2: 0x201C, // XK_leftdoublequotemark: LEFT DOUBLE QUOTATION MARK - 0x0ad3: 0x201D, // XK_rightdoublequotemark: RIGHT DOUBLE QUOTATION MARK - 0x0ad4: 0x211E, // XK_prescription: PRESCRIPTION TAKE - 0x0ad5: 0x2030, // XK_permille: PER MILLE SIGN - 0x0ad6: 0x2032, // XK_minutes: PRIME - 0x0ad7: 0x2033, // XK_seconds: DOUBLE PRIME - 0x0ad9: 0x271D, // XK_latincross: LATIN CROSS - 0x0adb: 0x25AC, // XK_filledrectbullet: BLACK RECTANGLE - 0x0adc: 0x25C0, // XK_filledlefttribullet: BLACK LEFT-POINTING TRIANGLE - 0x0add: 0x25B6, // XK_filledrighttribullet: BLACK RIGHT-POINTING TRIANGLE - 0x0ade: 0x25CF, // XK_emfilledcircle: BLACK CIRCLE - 0x0adf: 0x25AE, // XK_emfilledrect: BLACK VERTICAL RECTANGLE - 0x0ae0: 0x25E6, // XK_enopencircbullet: WHITE BULLET - 0x0ae1: 0x25AB, // XK_enopensquarebullet: WHITE SMALL SQUARE - 0x0ae2: 0x25AD, // XK_openrectbullet: WHITE RECTANGLE - 0x0ae3: 0x25B3, // XK_opentribulletup: WHITE UP-POINTING TRIANGLE - 0x0ae4: 0x25BD, // XK_opentribulletdown: WHITE DOWN-POINTING TRIANGLE - 0x0ae5: 0x2606, // XK_openstar: WHITE STAR - 0x0ae6: 0x2022, // XK_enfilledcircbullet: BULLET - 0x0ae7: 0x25AA, // XK_enfilledsqbullet: BLACK SMALL SQUARE - 0x0ae8: 0x25B2, // XK_filledtribulletup: BLACK UP-POINTING TRIANGLE - 0x0ae9: 0x25BC, // XK_filledtribulletdown: BLACK DOWN-POINTING TRIANGLE - 0x0aea: 0x261C, // XK_leftpointer: WHITE LEFT POINTING INDEX - 0x0aeb: 0x261E, // XK_rightpointer: WHITE RIGHT POINTING INDEX - 0x0aec: 0x2663, // XK_club: BLACK CLUB SUIT - 0x0aed: 0x2666, // XK_diamond: BLACK DIAMOND SUIT - 0x0aee: 0x2665, // XK_heart: BLACK HEART SUIT - 0x0af0: 0x2720, // XK_maltesecross: MALTESE CROSS - 0x0af1: 0x2020, // XK_dagger: DAGGER - 0x0af2: 0x2021, // XK_doubledagger: DOUBLE DAGGER - 0x0af3: 0x2713, // XK_checkmark: CHECK MARK - 0x0af4: 0x2717, // XK_ballotcross: BALLOT X - 0x0af5: 0x266F, // XK_musicalsharp: MUSIC SHARP SIGN - 0x0af6: 0x266D, // XK_musicalflat: MUSIC FLAT SIGN - 0x0af7: 0x2642, // XK_malesymbol: MALE SIGN - 0x0af8: 0x2640, // XK_femalesymbol: FEMALE SIGN - 0x0af9: 0x260E, // XK_telephone: BLACK TELEPHONE - 0x0afa: 0x2315, // XK_telephonerecorder: TELEPHONE RECORDER - 0x0afb: 0x2117, // XK_phonographcopyright: SOUND RECORDING COPYRIGHT - 0x0afc: 0x2038, // XK_caret: CARET - 0x0afd: 0x201A, // XK_singlelowquotemark: SINGLE LOW-9 QUOTATION MARK - 0x0afe: 0x201E, // XK_doublelowquotemark: DOUBLE LOW-9 QUOTATION MARK - 0x0ba3: 0x003C, // XK_leftcaret: LESS-THAN SIGN - 0x0ba6: 0x003E, // XK_rightcaret: GREATER-THAN SIGN - 0x0ba8: 0x2228, // XK_downcaret: LOGICAL OR - 0x0ba9: 0x2227, // XK_upcaret: LOGICAL AND - 0x0bc0: 0x00AF, // XK_overbar: MACRON - 0x0bc2: 0x22A4, // XK_downtack: DOWN TACK - 0x0bc3: 0x2229, // XK_upshoe: INTERSECTION - 0x0bc4: 0x230A, // XK_downstile: LEFT FLOOR - 0x0bc6: 0x005F, // XK_underbar: LOW LINE - 0x0bca: 0x2218, // XK_jot: RING OPERATOR - 0x0bcc: 0x2395, // XK_quad: APL FUNCTIONAL SYMBOL QUAD - 0x0bce: 0x22A5, // XK_uptack: UP TACK - 0x0bcf: 0x25CB, // XK_circle: WHITE CIRCLE - 0x0bd3: 0x2308, // XK_upstile: LEFT CEILING - 0x0bd6: 0x222A, // XK_downshoe: UNION - 0x0bd8: 0x2283, // XK_rightshoe: SUPERSET OF - 0x0bda: 0x2282, // XK_leftshoe: SUBSET OF - 0x0bdc: 0x22A3, // XK_lefttack: LEFT TACK - 0x0bfc: 0x22A2, // XK_righttack: RIGHT TACK - 0x0cdf: 0x2017, // XK_hebrew_doublelowline: DOUBLE LOW LINE - 0x0ce0: 0x05D0, // XK_hebrew_aleph: HEBREW LETTER ALEF - 0x0ce1: 0x05D1, // XK_hebrew_bet: HEBREW LETTER BET - 0x0ce2: 0x05D2, // XK_hebrew_gimel: HEBREW LETTER GIMEL - 0x0ce3: 0x05D3, // XK_hebrew_dalet: HEBREW LETTER DALET - 0x0ce4: 0x05D4, // XK_hebrew_he: HEBREW LETTER HE - 0x0ce5: 0x05D5, // XK_hebrew_waw: HEBREW LETTER VAV - 0x0ce6: 0x05D6, // XK_hebrew_zain: HEBREW LETTER ZAYIN - 0x0ce7: 0x05D7, // XK_hebrew_chet: HEBREW LETTER HET - 0x0ce8: 0x05D8, // XK_hebrew_tet: HEBREW LETTER TET - 0x0ce9: 0x05D9, // XK_hebrew_yod: HEBREW LETTER YOD - 0x0cea: 0x05DA, // XK_hebrew_finalkaph: HEBREW LETTER FINAL KAF - 0x0ceb: 0x05DB, // XK_hebrew_kaph: HEBREW LETTER KAF - 0x0cec: 0x05DC, // XK_hebrew_lamed: HEBREW LETTER LAMED - 0x0ced: 0x05DD, // XK_hebrew_finalmem: HEBREW LETTER FINAL MEM - 0x0cee: 0x05DE, // XK_hebrew_mem: HEBREW LETTER MEM - 0x0cef: 0x05DF, // XK_hebrew_finalnun: HEBREW LETTER FINAL NUN - 0x0cf0: 0x05E0, // XK_hebrew_nun: HEBREW LETTER NUN - 0x0cf1: 0x05E1, // XK_hebrew_samech: HEBREW LETTER SAMEKH - 0x0cf2: 0x05E2, // XK_hebrew_ayin: HEBREW LETTER AYIN - 0x0cf3: 0x05E3, // XK_hebrew_finalpe: HEBREW LETTER FINAL PE - 0x0cf4: 0x05E4, // XK_hebrew_pe: HEBREW LETTER PE - 0x0cf5: 0x05E5, // XK_hebrew_finalzade: HEBREW LETTER FINAL TSADI - 0x0cf6: 0x05E6, // XK_hebrew_zade: HEBREW LETTER TSADI - 0x0cf7: 0x05E7, // XK_hebrew_qoph: HEBREW LETTER QOF - 0x0cf8: 0x05E8, // XK_hebrew_resh: HEBREW LETTER RESH - 0x0cf9: 0x05E9, // XK_hebrew_shin: HEBREW LETTER SHIN - 0x0cfa: 0x05EA, // XK_hebrew_taw: HEBREW LETTER TAV - 0x0da1: 0x0E01, // XK_Thai_kokai: THAI CHARACTER KO KAI - 0x0da2: 0x0E02, // XK_Thai_khokhai: THAI CHARACTER KHO KHAI - 0x0da3: 0x0E03, // XK_Thai_khokhuat: THAI CHARACTER KHO KHUAT - 0x0da4: 0x0E04, // XK_Thai_khokhwai: THAI CHARACTER KHO KHWAI - 0x0da5: 0x0E05, // XK_Thai_khokhon: THAI CHARACTER KHO KHON - 0x0da6: 0x0E06, // XK_Thai_khorakhang: THAI CHARACTER KHO RAKHANG - 0x0da7: 0x0E07, // XK_Thai_ngongu: THAI CHARACTER NGO NGU - 0x0da8: 0x0E08, // XK_Thai_chochan: THAI CHARACTER CHO CHAN - 0x0da9: 0x0E09, // XK_Thai_choching: THAI CHARACTER CHO CHING - 0x0daa: 0x0E0A, // XK_Thai_chochang: THAI CHARACTER CHO CHANG - 0x0dab: 0x0E0B, // XK_Thai_soso: THAI CHARACTER SO SO - 0x0dac: 0x0E0C, // XK_Thai_chochoe: THAI CHARACTER CHO CHOE - 0x0dad: 0x0E0D, // XK_Thai_yoying: THAI CHARACTER YO YING - 0x0dae: 0x0E0E, // XK_Thai_dochada: THAI CHARACTER DO CHADA - 0x0daf: 0x0E0F, // XK_Thai_topatak: THAI CHARACTER TO PATAK - 0x0db0: 0x0E10, // XK_Thai_thothan: THAI CHARACTER THO THAN - 0x0db1: 0x0E11, // XK_Thai_thonangmontho: THAI CHARACTER THO NANGMONTHO - 0x0db2: 0x0E12, // XK_Thai_thophuthao: THAI CHARACTER THO PHUTHAO - 0x0db3: 0x0E13, // XK_Thai_nonen: THAI CHARACTER NO NEN - 0x0db4: 0x0E14, // XK_Thai_dodek: THAI CHARACTER DO DEK - 0x0db5: 0x0E15, // XK_Thai_totao: THAI CHARACTER TO TAO - 0x0db6: 0x0E16, // XK_Thai_thothung: THAI CHARACTER THO THUNG - 0x0db7: 0x0E17, // XK_Thai_thothahan: THAI CHARACTER THO THAHAN - 0x0db8: 0x0E18, // XK_Thai_thothong: THAI CHARACTER THO THONG - 0x0db9: 0x0E19, // XK_Thai_nonu: THAI CHARACTER NO NU - 0x0dba: 0x0E1A, // XK_Thai_bobaimai: THAI CHARACTER BO BAIMAI - 0x0dbb: 0x0E1B, // XK_Thai_popla: THAI CHARACTER PO PLA - 0x0dbc: 0x0E1C, // XK_Thai_phophung: THAI CHARACTER PHO PHUNG - 0x0dbd: 0x0E1D, // XK_Thai_fofa: THAI CHARACTER FO FA - 0x0dbe: 0x0E1E, // XK_Thai_phophan: THAI CHARACTER PHO PHAN - 0x0dbf: 0x0E1F, // XK_Thai_fofan: THAI CHARACTER FO FAN - 0x0dc0: 0x0E20, // XK_Thai_phosamphao: THAI CHARACTER PHO SAMPHAO - 0x0dc1: 0x0E21, // XK_Thai_moma: THAI CHARACTER MO MA - 0x0dc2: 0x0E22, // XK_Thai_yoyak: THAI CHARACTER YO YAK - 0x0dc3: 0x0E23, // XK_Thai_rorua: THAI CHARACTER RO RUA - 0x0dc4: 0x0E24, // XK_Thai_ru: THAI CHARACTER RU - 0x0dc5: 0x0E25, // XK_Thai_loling: THAI CHARACTER LO LING - 0x0dc6: 0x0E26, // XK_Thai_lu: THAI CHARACTER LU - 0x0dc7: 0x0E27, // XK_Thai_wowaen: THAI CHARACTER WO WAEN - 0x0dc8: 0x0E28, // XK_Thai_sosala: THAI CHARACTER SO SALA - 0x0dc9: 0x0E29, // XK_Thai_sorusi: THAI CHARACTER SO RUSI - 0x0dca: 0x0E2A, // XK_Thai_sosua: THAI CHARACTER SO SUA - 0x0dcb: 0x0E2B, // XK_Thai_hohip: THAI CHARACTER HO HIP - 0x0dcc: 0x0E2C, // XK_Thai_lochula: THAI CHARACTER LO CHULA - 0x0dcd: 0x0E2D, // XK_Thai_oang: THAI CHARACTER O ANG - 0x0dce: 0x0E2E, // XK_Thai_honokhuk: THAI CHARACTER HO NOKHUK - 0x0dcf: 0x0E2F, // XK_Thai_paiyannoi: THAI CHARACTER PAIYANNOI - 0x0dd0: 0x0E30, // XK_Thai_saraa: THAI CHARACTER SARA A - 0x0dd1: 0x0E31, // XK_Thai_maihanakat: THAI CHARACTER MAI HAN-AKAT - 0x0dd2: 0x0E32, // XK_Thai_saraaa: THAI CHARACTER SARA AA - 0x0dd3: 0x0E33, // XK_Thai_saraam: THAI CHARACTER SARA AM - 0x0dd4: 0x0E34, // XK_Thai_sarai: THAI CHARACTER SARA I - 0x0dd5: 0x0E35, // XK_Thai_saraii: THAI CHARACTER SARA II - 0x0dd6: 0x0E36, // XK_Thai_saraue: THAI CHARACTER SARA UE - 0x0dd7: 0x0E37, // XK_Thai_sarauee: THAI CHARACTER SARA UEE - 0x0dd8: 0x0E38, // XK_Thai_sarau: THAI CHARACTER SARA U - 0x0dd9: 0x0E39, // XK_Thai_sarauu: THAI CHARACTER SARA UU - 0x0dda: 0x0E3A, // XK_Thai_phinthu: THAI CHARACTER PHINTHU - 0x0ddf: 0x0E3F, // XK_Thai_baht: THAI CURRENCY SYMBOL BAHT - 0x0de0: 0x0E40, // XK_Thai_sarae: THAI CHARACTER SARA E - 0x0de1: 0x0E41, // XK_Thai_saraae: THAI CHARACTER SARA AE - 0x0de2: 0x0E42, // XK_Thai_sarao: THAI CHARACTER SARA O - 0x0de3: 0x0E43, // XK_Thai_saraaimaimuan: THAI CHARACTER SARA AI MAIMUAN - 0x0de4: 0x0E44, // XK_Thai_saraaimaimalai: THAI CHARACTER SARA AI MAIMALAI - 0x0de5: 0x0E45, // XK_Thai_lakkhangyao: THAI CHARACTER LAKKHANGYAO - 0x0de6: 0x0E46, // XK_Thai_maiyamok: THAI CHARACTER MAIYAMOK - 0x0de7: 0x0E47, // XK_Thai_maitaikhu: THAI CHARACTER MAITAIKHU - 0x0de8: 0x0E48, // XK_Thai_maiek: THAI CHARACTER MAI EK - 0x0de9: 0x0E49, // XK_Thai_maitho: THAI CHARACTER MAI THO - 0x0dea: 0x0E4A, // XK_Thai_maitri: THAI CHARACTER MAI TRI - 0x0deb: 0x0E4B, // XK_Thai_maichattawa: THAI CHARACTER MAI CHATTAWA - 0x0dec: 0x0E4C, // XK_Thai_thanthakhat: THAI CHARACTER THANTHAKHAT - 0x0ded: 0x0E4D, // XK_Thai_nikhahit: THAI CHARACTER NIKHAHIT - 0x0df0: 0x0E50, // XK_Thai_leksun: THAI DIGIT ZERO - 0x0df1: 0x0E51, // XK_Thai_leknung: THAI DIGIT ONE - 0x0df2: 0x0E52, // XK_Thai_leksong: THAI DIGIT TWO - 0x0df3: 0x0E53, // XK_Thai_leksam: THAI DIGIT THREE - 0x0df4: 0x0E54, // XK_Thai_leksi: THAI DIGIT FOUR - 0x0df5: 0x0E55, // XK_Thai_lekha: THAI DIGIT FIVE - 0x0df6: 0x0E56, // XK_Thai_lekhok: THAI DIGIT SIX - 0x0df7: 0x0E57, // XK_Thai_lekchet: THAI DIGIT SEVEN - 0x0df8: 0x0E58, // XK_Thai_lekpaet: THAI DIGIT EIGHT - 0x0df9: 0x0E59, // XK_Thai_lekkao: THAI DIGIT NINE - 0x0eff: 0x20A9, // XK_Korean_Won: WON SIGN - 0x1000587: 0x0587, // XK_Armenian_ligature_ew: ARMENIAN SMALL LIGATURE ECH YIWN - 0x1000589: 0x0589, // XK_Armenian_full_stop: ARMENIAN FULL STOP - 0x100055d: 0x055D, // XK_Armenian_separation_mark: ARMENIAN COMMA - 0x100058a: 0x058A, // XK_Armenian_hyphen: ARMENIAN HYPHEN - 0x100055c: 0x055C, // XK_Armenian_exclam: ARMENIAN EXCLAMATION MARK - 0x100055b: 0x055B, // XK_Armenian_accent: ARMENIAN EMPHASIS MARK - 0x100055e: 0x055E, // XK_Armenian_question: ARMENIAN QUESTION MARK - 0x1000531: 0x0531, // XK_Armenian_AYB: ARMENIAN CAPITAL LETTER AYB - 0x1000561: 0x0561, // XK_Armenian_ayb: ARMENIAN SMALL LETTER AYB - 0x1000532: 0x0532, // XK_Armenian_BEN: ARMENIAN CAPITAL LETTER BEN - 0x1000562: 0x0562, // XK_Armenian_ben: ARMENIAN SMALL LETTER BEN - 0x1000533: 0x0533, // XK_Armenian_GIM: ARMENIAN CAPITAL LETTER GIM - 0x1000563: 0x0563, // XK_Armenian_gim: ARMENIAN SMALL LETTER GIM - 0x1000534: 0x0534, // XK_Armenian_DA: ARMENIAN CAPITAL LETTER DA - 0x1000564: 0x0564, // XK_Armenian_da: ARMENIAN SMALL LETTER DA - 0x1000535: 0x0535, // XK_Armenian_YECH: ARMENIAN CAPITAL LETTER ECH - 0x1000565: 0x0565, // XK_Armenian_yech: ARMENIAN SMALL LETTER ECH - 0x1000536: 0x0536, // XK_Armenian_ZA: ARMENIAN CAPITAL LETTER ZA - 0x1000566: 0x0566, // XK_Armenian_za: ARMENIAN SMALL LETTER ZA - 0x1000537: 0x0537, // XK_Armenian_E: ARMENIAN CAPITAL LETTER EH - 0x1000567: 0x0567, // XK_Armenian_e: ARMENIAN SMALL LETTER EH - 0x1000538: 0x0538, // XK_Armenian_AT: ARMENIAN CAPITAL LETTER ET - 0x1000568: 0x0568, // XK_Armenian_at: ARMENIAN SMALL LETTER ET - 0x1000539: 0x0539, // XK_Armenian_TO: ARMENIAN CAPITAL LETTER TO - 0x1000569: 0x0569, // XK_Armenian_to: ARMENIAN SMALL LETTER TO - 0x100053a: 0x053A, // XK_Armenian_ZHE: ARMENIAN CAPITAL LETTER ZHE - 0x100056a: 0x056A, // XK_Armenian_zhe: ARMENIAN SMALL LETTER ZHE - 0x100053b: 0x053B, // XK_Armenian_INI: ARMENIAN CAPITAL LETTER INI - 0x100056b: 0x056B, // XK_Armenian_ini: ARMENIAN SMALL LETTER INI - 0x100053c: 0x053C, // XK_Armenian_LYUN: ARMENIAN CAPITAL LETTER LIWN - 0x100056c: 0x056C, // XK_Armenian_lyun: ARMENIAN SMALL LETTER LIWN - 0x100053d: 0x053D, // XK_Armenian_KHE: ARMENIAN CAPITAL LETTER XEH - 0x100056d: 0x056D, // XK_Armenian_khe: ARMENIAN SMALL LETTER XEH - 0x100053e: 0x053E, // XK_Armenian_TSA: ARMENIAN CAPITAL LETTER CA - 0x100056e: 0x056E, // XK_Armenian_tsa: ARMENIAN SMALL LETTER CA - 0x100053f: 0x053F, // XK_Armenian_KEN: ARMENIAN CAPITAL LETTER KEN - 0x100056f: 0x056F, // XK_Armenian_ken: ARMENIAN SMALL LETTER KEN - 0x1000540: 0x0540, // XK_Armenian_HO: ARMENIAN CAPITAL LETTER HO - 0x1000570: 0x0570, // XK_Armenian_ho: ARMENIAN SMALL LETTER HO - 0x1000541: 0x0541, // XK_Armenian_DZA: ARMENIAN CAPITAL LETTER JA - 0x1000571: 0x0571, // XK_Armenian_dza: ARMENIAN SMALL LETTER JA - 0x1000542: 0x0542, // XK_Armenian_GHAT: ARMENIAN CAPITAL LETTER GHAD - 0x1000572: 0x0572, // XK_Armenian_ghat: ARMENIAN SMALL LETTER GHAD - 0x1000543: 0x0543, // XK_Armenian_TCHE: ARMENIAN CAPITAL LETTER CHEH - 0x1000573: 0x0573, // XK_Armenian_tche: ARMENIAN SMALL LETTER CHEH - 0x1000544: 0x0544, // XK_Armenian_MEN: ARMENIAN CAPITAL LETTER MEN - 0x1000574: 0x0574, // XK_Armenian_men: ARMENIAN SMALL LETTER MEN - 0x1000545: 0x0545, // XK_Armenian_HI: ARMENIAN CAPITAL LETTER YI - 0x1000575: 0x0575, // XK_Armenian_hi: ARMENIAN SMALL LETTER YI - 0x1000546: 0x0546, // XK_Armenian_NU: ARMENIAN CAPITAL LETTER NOW - 0x1000576: 0x0576, // XK_Armenian_nu: ARMENIAN SMALL LETTER NOW - 0x1000547: 0x0547, // XK_Armenian_SHA: ARMENIAN CAPITAL LETTER SHA - 0x1000577: 0x0577, // XK_Armenian_sha: ARMENIAN SMALL LETTER SHA - 0x1000548: 0x0548, // XK_Armenian_VO: ARMENIAN CAPITAL LETTER VO - 0x1000578: 0x0578, // XK_Armenian_vo: ARMENIAN SMALL LETTER VO - 0x1000549: 0x0549, // XK_Armenian_CHA: ARMENIAN CAPITAL LETTER CHA - 0x1000579: 0x0579, // XK_Armenian_cha: ARMENIAN SMALL LETTER CHA - 0x100054a: 0x054A, // XK_Armenian_PE: ARMENIAN CAPITAL LETTER PEH - 0x100057a: 0x057A, // XK_Armenian_pe: ARMENIAN SMALL LETTER PEH - 0x100054b: 0x054B, // XK_Armenian_JE: ARMENIAN CAPITAL LETTER JHEH - 0x100057b: 0x057B, // XK_Armenian_je: ARMENIAN SMALL LETTER JHEH - 0x100054c: 0x054C, // XK_Armenian_RA: ARMENIAN CAPITAL LETTER RA - 0x100057c: 0x057C, // XK_Armenian_ra: ARMENIAN SMALL LETTER RA - 0x100054d: 0x054D, // XK_Armenian_SE: ARMENIAN CAPITAL LETTER SEH - 0x100057d: 0x057D, // XK_Armenian_se: ARMENIAN SMALL LETTER SEH - 0x100054e: 0x054E, // XK_Armenian_VEV: ARMENIAN CAPITAL LETTER VEW - 0x100057e: 0x057E, // XK_Armenian_vev: ARMENIAN SMALL LETTER VEW - 0x100054f: 0x054F, // XK_Armenian_TYUN: ARMENIAN CAPITAL LETTER TIWN - 0x100057f: 0x057F, // XK_Armenian_tyun: ARMENIAN SMALL LETTER TIWN - 0x1000550: 0x0550, // XK_Armenian_RE: ARMENIAN CAPITAL LETTER REH - 0x1000580: 0x0580, // XK_Armenian_re: ARMENIAN SMALL LETTER REH - 0x1000551: 0x0551, // XK_Armenian_TSO: ARMENIAN CAPITAL LETTER CO - 0x1000581: 0x0581, // XK_Armenian_tso: ARMENIAN SMALL LETTER CO - 0x1000552: 0x0552, // XK_Armenian_VYUN: ARMENIAN CAPITAL LETTER YIWN - 0x1000582: 0x0582, // XK_Armenian_vyun: ARMENIAN SMALL LETTER YIWN - 0x1000553: 0x0553, // XK_Armenian_PYUR: ARMENIAN CAPITAL LETTER PIWR - 0x1000583: 0x0583, // XK_Armenian_pyur: ARMENIAN SMALL LETTER PIWR - 0x1000554: 0x0554, // XK_Armenian_KE: ARMENIAN CAPITAL LETTER KEH - 0x1000584: 0x0584, // XK_Armenian_ke: ARMENIAN SMALL LETTER KEH - 0x1000555: 0x0555, // XK_Armenian_O: ARMENIAN CAPITAL LETTER OH - 0x1000585: 0x0585, // XK_Armenian_o: ARMENIAN SMALL LETTER OH - 0x1000556: 0x0556, // XK_Armenian_FE: ARMENIAN CAPITAL LETTER FEH - 0x1000586: 0x0586, // XK_Armenian_fe: ARMENIAN SMALL LETTER FEH - 0x100055a: 0x055A, // XK_Armenian_apostrophe: ARMENIAN APOSTROPHE - 0x10010d0: 0x10D0, // XK_Georgian_an: GEORGIAN LETTER AN - 0x10010d1: 0x10D1, // XK_Georgian_ban: GEORGIAN LETTER BAN - 0x10010d2: 0x10D2, // XK_Georgian_gan: GEORGIAN LETTER GAN - 0x10010d3: 0x10D3, // XK_Georgian_don: GEORGIAN LETTER DON - 0x10010d4: 0x10D4, // XK_Georgian_en: GEORGIAN LETTER EN - 0x10010d5: 0x10D5, // XK_Georgian_vin: GEORGIAN LETTER VIN - 0x10010d6: 0x10D6, // XK_Georgian_zen: GEORGIAN LETTER ZEN - 0x10010d7: 0x10D7, // XK_Georgian_tan: GEORGIAN LETTER TAN - 0x10010d8: 0x10D8, // XK_Georgian_in: GEORGIAN LETTER IN - 0x10010d9: 0x10D9, // XK_Georgian_kan: GEORGIAN LETTER KAN - 0x10010da: 0x10DA, // XK_Georgian_las: GEORGIAN LETTER LAS - 0x10010db: 0x10DB, // XK_Georgian_man: GEORGIAN LETTER MAN - 0x10010dc: 0x10DC, // XK_Georgian_nar: GEORGIAN LETTER NAR - 0x10010dd: 0x10DD, // XK_Georgian_on: GEORGIAN LETTER ON - 0x10010de: 0x10DE, // XK_Georgian_par: GEORGIAN LETTER PAR - 0x10010df: 0x10DF, // XK_Georgian_zhar: GEORGIAN LETTER ZHAR - 0x10010e0: 0x10E0, // XK_Georgian_rae: GEORGIAN LETTER RAE - 0x10010e1: 0x10E1, // XK_Georgian_san: GEORGIAN LETTER SAN - 0x10010e2: 0x10E2, // XK_Georgian_tar: GEORGIAN LETTER TAR - 0x10010e3: 0x10E3, // XK_Georgian_un: GEORGIAN LETTER UN - 0x10010e4: 0x10E4, // XK_Georgian_phar: GEORGIAN LETTER PHAR - 0x10010e5: 0x10E5, // XK_Georgian_khar: GEORGIAN LETTER KHAR - 0x10010e6: 0x10E6, // XK_Georgian_ghan: GEORGIAN LETTER GHAN - 0x10010e7: 0x10E7, // XK_Georgian_qar: GEORGIAN LETTER QAR - 0x10010e8: 0x10E8, // XK_Georgian_shin: GEORGIAN LETTER SHIN - 0x10010e9: 0x10E9, // XK_Georgian_chin: GEORGIAN LETTER CHIN - 0x10010ea: 0x10EA, // XK_Georgian_can: GEORGIAN LETTER CAN - 0x10010eb: 0x10EB, // XK_Georgian_jil: GEORGIAN LETTER JIL - 0x10010ec: 0x10EC, // XK_Georgian_cil: GEORGIAN LETTER CIL - 0x10010ed: 0x10ED, // XK_Georgian_char: GEORGIAN LETTER CHAR - 0x10010ee: 0x10EE, // XK_Georgian_xan: GEORGIAN LETTER XAN - 0x10010ef: 0x10EF, // XK_Georgian_jhan: GEORGIAN LETTER JHAN - 0x10010f0: 0x10F0, // XK_Georgian_hae: GEORGIAN LETTER HAE - 0x10010f1: 0x10F1, // XK_Georgian_he: GEORGIAN LETTER HE - 0x10010f2: 0x10F2, // XK_Georgian_hie: GEORGIAN LETTER HIE - 0x10010f3: 0x10F3, // XK_Georgian_we: GEORGIAN LETTER WE - 0x10010f4: 0x10F4, // XK_Georgian_har: GEORGIAN LETTER HAR - 0x10010f5: 0x10F5, // XK_Georgian_hoe: GEORGIAN LETTER HOE - 0x10010f6: 0x10F6, // XK_Georgian_fi: GEORGIAN LETTER FI - 0x1001e8a: 0x1E8A, // XK_Xabovedot: LATIN CAPITAL LETTER X WITH DOT ABOVE - 0x100012c: 0x012C, // XK_Ibreve: LATIN CAPITAL LETTER I WITH BREVE - 0x10001b5: 0x01B5, // XK_Zstroke: LATIN CAPITAL LETTER Z WITH STROKE - 0x10001e6: 0x01E6, // XK_Gcaron: LATIN CAPITAL LETTER G WITH CARON - 0x10001d1: 0x01D2, // XK_Ocaron: LATIN CAPITAL LETTER O WITH CARON - 0x100019f: 0x019F, // XK_Obarred: LATIN CAPITAL LETTER O WITH MIDDLE TILDE - 0x1001e8b: 0x1E8B, // XK_xabovedot: LATIN SMALL LETTER X WITH DOT ABOVE - 0x100012d: 0x012D, // XK_ibreve: LATIN SMALL LETTER I WITH BREVE - 0x10001b6: 0x01B6, // XK_zstroke: LATIN SMALL LETTER Z WITH STROKE - 0x10001e7: 0x01E7, // XK_gcaron: LATIN SMALL LETTER G WITH CARON - 0x10001d2: 0x01D2, // XK_ocaron: LATIN SMALL LETTER O WITH CARON - 0x1000275: 0x0275, // XK_obarred: LATIN SMALL LETTER BARRED O - 0x100018f: 0x018F, // XK_SCHWA: LATIN CAPITAL LETTER SCHWA - 0x1000259: 0x0259, // XK_schwa: LATIN SMALL LETTER SCHWA - 0x10001b7: 0x01B7, // XK_EZH: LATIN CAPITAL LETTER EZH - 0x1000292: 0x0292, // XK_ezh: LATIN SMALL LETTER EZH - 0x1001e36: 0x1E36, // XK_Lbelowdot: LATIN CAPITAL LETTER L WITH DOT BELOW - 0x1001e37: 0x1E37, // XK_lbelowdot: LATIN SMALL LETTER L WITH DOT BELOW - 0x1001ea0: 0x1EA0, // XK_Abelowdot: LATIN CAPITAL LETTER A WITH DOT BELOW - 0x1001ea1: 0x1EA1, // XK_abelowdot: LATIN SMALL LETTER A WITH DOT BELOW - 0x1001ea2: 0x1EA2, // XK_Ahook: LATIN CAPITAL LETTER A WITH HOOK ABOVE - 0x1001ea3: 0x1EA3, // XK_ahook: LATIN SMALL LETTER A WITH HOOK ABOVE - 0x1001ea4: 0x1EA4, // XK_Acircumflexacute: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE - 0x1001ea5: 0x1EA5, // XK_acircumflexacute: LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE - 0x1001ea6: 0x1EA6, // XK_Acircumflexgrave: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE - 0x1001ea7: 0x1EA7, // XK_acircumflexgrave: LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE - 0x1001ea8: 0x1EA8, // XK_Acircumflexhook: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE - 0x1001ea9: 0x1EA9, // XK_acircumflexhook: LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE - 0x1001eaa: 0x1EAA, // XK_Acircumflextilde: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE - 0x1001eab: 0x1EAB, // XK_acircumflextilde: LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE - 0x1001eac: 0x1EAC, // XK_Acircumflexbelowdot: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW - 0x1001ead: 0x1EAD, // XK_acircumflexbelowdot: LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW - 0x1001eae: 0x1EAE, // XK_Abreveacute: LATIN CAPITAL LETTER A WITH BREVE AND ACUTE - 0x1001eaf: 0x1EAF, // XK_abreveacute: LATIN SMALL LETTER A WITH BREVE AND ACUTE - 0x1001eb0: 0x1EB0, // XK_Abrevegrave: LATIN CAPITAL LETTER A WITH BREVE AND GRAVE - 0x1001eb1: 0x1EB1, // XK_abrevegrave: LATIN SMALL LETTER A WITH BREVE AND GRAVE - 0x1001eb2: 0x1EB2, // XK_Abrevehook: LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE - 0x1001eb3: 0x1EB3, // XK_abrevehook: LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE - 0x1001eb4: 0x1EB4, // XK_Abrevetilde: LATIN CAPITAL LETTER A WITH BREVE AND TILDE - 0x1001eb5: 0x1EB5, // XK_abrevetilde: LATIN SMALL LETTER A WITH BREVE AND TILDE - 0x1001eb6: 0x1EB6, // XK_Abrevebelowdot: LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW - 0x1001eb7: 0x1EB7, // XK_abrevebelowdot: LATIN SMALL LETTER A WITH BREVE AND DOT BELOW - 0x1001eb8: 0x1EB8, // XK_Ebelowdot: LATIN CAPITAL LETTER E WITH DOT BELOW - 0x1001eb9: 0x1EB9, // XK_ebelowdot: LATIN SMALL LETTER E WITH DOT BELOW - 0x1001eba: 0x1EBA, // XK_Ehook: LATIN CAPITAL LETTER E WITH HOOK ABOVE - 0x1001ebb: 0x1EBB, // XK_ehook: LATIN SMALL LETTER E WITH HOOK ABOVE - 0x1001ebc: 0x1EBC, // XK_Etilde: LATIN CAPITAL LETTER E WITH TILDE - 0x1001ebd: 0x1EBD, // XK_etilde: LATIN SMALL LETTER E WITH TILDE - 0x1001ebe: 0x1EBE, // XK_Ecircumflexacute: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE - 0x1001ebf: 0x1EBF, // XK_ecircumflexacute: LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE - 0x1001ec0: 0x1EC0, // XK_Ecircumflexgrave: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE - 0x1001ec1: 0x1EC1, // XK_ecircumflexgrave: LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE - 0x1001ec2: 0x1EC2, // XK_Ecircumflexhook: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE - 0x1001ec3: 0x1EC3, // XK_ecircumflexhook: LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE - 0x1001ec4: 0x1EC4, // XK_Ecircumflextilde: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE - 0x1001ec5: 0x1EC5, // XK_ecircumflextilde: LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE - 0x1001ec6: 0x1EC6, // XK_Ecircumflexbelowdot: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW - 0x1001ec7: 0x1EC7, // XK_ecircumflexbelowdot: LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW - 0x1001ec8: 0x1EC8, // XK_Ihook: LATIN CAPITAL LETTER I WITH HOOK ABOVE - 0x1001ec9: 0x1EC9, // XK_ihook: LATIN SMALL LETTER I WITH HOOK ABOVE - 0x1001eca: 0x1ECA, // XK_Ibelowdot: LATIN CAPITAL LETTER I WITH DOT BELOW - 0x1001ecb: 0x1ECB, // XK_ibelowdot: LATIN SMALL LETTER I WITH DOT BELOW - 0x1001ecc: 0x1ECC, // XK_Obelowdot: LATIN CAPITAL LETTER O WITH DOT BELOW - 0x1001ecd: 0x1ECD, // XK_obelowdot: LATIN SMALL LETTER O WITH DOT BELOW - 0x1001ece: 0x1ECE, // XK_Ohook: LATIN CAPITAL LETTER O WITH HOOK ABOVE - 0x1001ecf: 0x1ECF, // XK_ohook: LATIN SMALL LETTER O WITH HOOK ABOVE - 0x1001ed0: 0x1ED0, // XK_Ocircumflexacute: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE - 0x1001ed1: 0x1ED1, // XK_ocircumflexacute: LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE - 0x1001ed2: 0x1ED2, // XK_Ocircumflexgrave: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE - 0x1001ed3: 0x1ED3, // XK_ocircumflexgrave: LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE - 0x1001ed4: 0x1ED4, // XK_Ocircumflexhook: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE - 0x1001ed5: 0x1ED5, // XK_ocircumflexhook: LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE - 0x1001ed6: 0x1ED6, // XK_Ocircumflextilde: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE - 0x1001ed7: 0x1ED7, // XK_ocircumflextilde: LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE - 0x1001ed8: 0x1ED8, // XK_Ocircumflexbelowdot: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW - 0x1001ed9: 0x1ED9, // XK_ocircumflexbelowdot: LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW - 0x1001eda: 0x1EDA, // XK_Ohornacute: LATIN CAPITAL LETTER O WITH HORN AND ACUTE - 0x1001edb: 0x1EDB, // XK_ohornacute: LATIN SMALL LETTER O WITH HORN AND ACUTE - 0x1001edc: 0x1EDC, // XK_Ohorngrave: LATIN CAPITAL LETTER O WITH HORN AND GRAVE - 0x1001edd: 0x1EDD, // XK_ohorngrave: LATIN SMALL LETTER O WITH HORN AND GRAVE - 0x1001ede: 0x1EDE, // XK_Ohornhook: LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE - 0x1001edf: 0x1EDF, // XK_ohornhook: LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE - 0x1001ee0: 0x1EE0, // XK_Ohorntilde: LATIN CAPITAL LETTER O WITH HORN AND TILDE - 0x1001ee1: 0x1EE1, // XK_ohorntilde: LATIN SMALL LETTER O WITH HORN AND TILDE - 0x1001ee2: 0x1EE2, // XK_Ohornbelowdot: LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW - 0x1001ee3: 0x1EE3, // XK_ohornbelowdot: LATIN SMALL LETTER O WITH HORN AND DOT BELOW - 0x1001ee4: 0x1EE4, // XK_Ubelowdot: LATIN CAPITAL LETTER U WITH DOT BELOW - 0x1001ee5: 0x1EE5, // XK_ubelowdot: LATIN SMALL LETTER U WITH DOT BELOW - 0x1001ee6: 0x1EE6, // XK_Uhook: LATIN CAPITAL LETTER U WITH HOOK ABOVE - 0x1001ee7: 0x1EE7, // XK_uhook: LATIN SMALL LETTER U WITH HOOK ABOVE - 0x1001ee8: 0x1EE8, // XK_Uhornacute: LATIN CAPITAL LETTER U WITH HORN AND ACUTE - 0x1001ee9: 0x1EE9, // XK_uhornacute: LATIN SMALL LETTER U WITH HORN AND ACUTE - 0x1001eea: 0x1EEA, // XK_Uhorngrave: LATIN CAPITAL LETTER U WITH HORN AND GRAVE - 0x1001eeb: 0x1EEB, // XK_uhorngrave: LATIN SMALL LETTER U WITH HORN AND GRAVE - 0x1001eec: 0x1EEC, // XK_Uhornhook: LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE - 0x1001eed: 0x1EED, // XK_uhornhook: LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE - 0x1001eee: 0x1EEE, // XK_Uhorntilde: LATIN CAPITAL LETTER U WITH HORN AND TILDE - 0x1001eef: 0x1EEF, // XK_uhorntilde: LATIN SMALL LETTER U WITH HORN AND TILDE - 0x1001ef0: 0x1EF0, // XK_Uhornbelowdot: LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW - 0x1001ef1: 0x1EF1, // XK_uhornbelowdot: LATIN SMALL LETTER U WITH HORN AND DOT BELOW - 0x1001ef4: 0x1EF4, // XK_Ybelowdot: LATIN CAPITAL LETTER Y WITH DOT BELOW - 0x1001ef5: 0x1EF5, // XK_ybelowdot: LATIN SMALL LETTER Y WITH DOT BELOW - 0x1001ef6: 0x1EF6, // XK_Yhook: LATIN CAPITAL LETTER Y WITH HOOK ABOVE - 0x1001ef7: 0x1EF7, // XK_yhook: LATIN SMALL LETTER Y WITH HOOK ABOVE - 0x1001ef8: 0x1EF8, // XK_Ytilde: LATIN CAPITAL LETTER Y WITH TILDE - 0x1001ef9: 0x1EF9, // XK_ytilde: LATIN SMALL LETTER Y WITH TILDE - 0x10001a0: 0x01A0, // XK_Ohorn: LATIN CAPITAL LETTER O WITH HORN - 0x10001a1: 0x01A1, // XK_ohorn: LATIN SMALL LETTER O WITH HORN - 0x10001af: 0x01AF, // XK_Uhorn: LATIN CAPITAL LETTER U WITH HORN - 0x10001b0: 0x01B0, // XK_uhorn: LATIN SMALL LETTER U WITH HORN - 0x10020a0: 0x20A0, // XK_EcuSign: EURO-CURRENCY SIGN - 0x10020a1: 0x20A1, // XK_ColonSign: COLON SIGN - 0x10020a2: 0x20A2, // XK_CruzeiroSign: CRUZEIRO SIGN - 0x10020a3: 0x20A3, // XK_FFrancSign: FRENCH FRANC SIGN - 0x10020a4: 0x20A4, // XK_LiraSign: LIRA SIGN - 0x10020a5: 0x20A5, // XK_MillSign: MILL SIGN - 0x10020a6: 0x20A6, // XK_NairaSign: NAIRA SIGN - 0x10020a7: 0x20A7, // XK_PesetaSign: PESETA SIGN - 0x10020a8: 0x20A8, // XK_RupeeSign: RUPEE SIGN - 0x10020a9: 0x20A9, // XK_WonSign: WON SIGN - 0x10020aa: 0x20AA, // XK_NewSheqelSign: NEW SHEQEL SIGN - 0x10020ab: 0x20AB, // XK_DongSign: DONG SIGN - 0x20ac: 0x20AC, // XK_EuroSign: EURO SIGN - 0x1002070: 0x2070, // XK_zerosuperior: SUPERSCRIPT ZERO - 0x1002074: 0x2074, // XK_foursuperior: SUPERSCRIPT FOUR - 0x1002075: 0x2075, // XK_fivesuperior: SUPERSCRIPT FIVE - 0x1002076: 0x2076, // XK_sixsuperior: SUPERSCRIPT SIX - 0x1002077: 0x2077, // XK_sevensuperior: SUPERSCRIPT SEVEN - 0x1002078: 0x2078, // XK_eightsuperior: SUPERSCRIPT EIGHT - 0x1002079: 0x2079, // XK_ninesuperior: SUPERSCRIPT NINE - 0x1002080: 0x2080, // XK_zerosubscript: SUBSCRIPT ZERO - 0x1002081: 0x2081, // XK_onesubscript: SUBSCRIPT ONE - 0x1002082: 0x2082, // XK_twosubscript: SUBSCRIPT TWO - 0x1002083: 0x2083, // XK_threesubscript: SUBSCRIPT THREE - 0x1002084: 0x2084, // XK_foursubscript: SUBSCRIPT FOUR - 0x1002085: 0x2085, // XK_fivesubscript: SUBSCRIPT FIVE - 0x1002086: 0x2086, // XK_sixsubscript: SUBSCRIPT SIX - 0x1002087: 0x2087, // XK_sevensubscript: SUBSCRIPT SEVEN - 0x1002088: 0x2088, // XK_eightsubscript: SUBSCRIPT EIGHT - 0x1002089: 0x2089, // XK_ninesubscript: SUBSCRIPT NINE - 0x1002202: 0x2202, // XK_partdifferential: PARTIAL DIFFERENTIAL - 0x1002205: 0x2205, // XK_emptyset: NULL SET - 0x1002208: 0x2208, // XK_elementof: ELEMENT OF - 0x1002209: 0x2209, // XK_notelementof: NOT AN ELEMENT OF - 0x100220B: 0x220B, // XK_containsas: CONTAINS AS MEMBER - 0x100221A: 0x221A, // XK_squareroot: SQUARE ROOT - 0x100221B: 0x221B, // XK_cuberoot: CUBE ROOT - 0x100221C: 0x221C, // XK_fourthroot: FOURTH ROOT - 0x100222C: 0x222C, // XK_dintegral: DOUBLE INTEGRAL - 0x100222D: 0x222D, // XK_tintegral: TRIPLE INTEGRAL - 0x1002235: 0x2235, // XK_because: BECAUSE - 0x1002248: 0x2245, // XK_approxeq: ALMOST EQUAL TO - 0x1002247: 0x2247, // XK_notapproxeq: NOT ALMOST EQUAL TO - 0x1002262: 0x2262, // XK_notidentical: NOT IDENTICAL TO - 0x1002263: 0x2263, // XK_stricteq: STRICTLY EQUIVALENT TO - 0x1002800: 0x2800, // XK_braille_blank: BRAILLE PATTERN BLANK - 0x1002801: 0x2801, // XK_braille_dots_1: BRAILLE PATTERN DOTS-1 - 0x1002802: 0x2802, // XK_braille_dots_2: BRAILLE PATTERN DOTS-2 - 0x1002803: 0x2803, // XK_braille_dots_12: BRAILLE PATTERN DOTS-12 - 0x1002804: 0x2804, // XK_braille_dots_3: BRAILLE PATTERN DOTS-3 - 0x1002805: 0x2805, // XK_braille_dots_13: BRAILLE PATTERN DOTS-13 - 0x1002806: 0x2806, // XK_braille_dots_23: BRAILLE PATTERN DOTS-23 - 0x1002807: 0x2807, // XK_braille_dots_123: BRAILLE PATTERN DOTS-123 - 0x1002808: 0x2808, // XK_braille_dots_4: BRAILLE PATTERN DOTS-4 - 0x1002809: 0x2809, // XK_braille_dots_14: BRAILLE PATTERN DOTS-14 - 0x100280a: 0x280a, // XK_braille_dots_24: BRAILLE PATTERN DOTS-24 - 0x100280b: 0x280b, // XK_braille_dots_124: BRAILLE PATTERN DOTS-124 - 0x100280c: 0x280c, // XK_braille_dots_34: BRAILLE PATTERN DOTS-34 - 0x100280d: 0x280d, // XK_braille_dots_134: BRAILLE PATTERN DOTS-134 - 0x100280e: 0x280e, // XK_braille_dots_234: BRAILLE PATTERN DOTS-234 - 0x100280f: 0x280f, // XK_braille_dots_1234: BRAILLE PATTERN DOTS-1234 - 0x1002810: 0x2810, // XK_braille_dots_5: BRAILLE PATTERN DOTS-5 - 0x1002811: 0x2811, // XK_braille_dots_15: BRAILLE PATTERN DOTS-15 - 0x1002812: 0x2812, // XK_braille_dots_25: BRAILLE PATTERN DOTS-25 - 0x1002813: 0x2813, // XK_braille_dots_125: BRAILLE PATTERN DOTS-125 - 0x1002814: 0x2814, // XK_braille_dots_35: BRAILLE PATTERN DOTS-35 - 0x1002815: 0x2815, // XK_braille_dots_135: BRAILLE PATTERN DOTS-135 - 0x1002816: 0x2816, // XK_braille_dots_235: BRAILLE PATTERN DOTS-235 - 0x1002817: 0x2817, // XK_braille_dots_1235: BRAILLE PATTERN DOTS-1235 - 0x1002818: 0x2818, // XK_braille_dots_45: BRAILLE PATTERN DOTS-45 - 0x1002819: 0x2819, // XK_braille_dots_145: BRAILLE PATTERN DOTS-145 - 0x100281a: 0x281a, // XK_braille_dots_245: BRAILLE PATTERN DOTS-245 - 0x100281b: 0x281b, // XK_braille_dots_1245: BRAILLE PATTERN DOTS-1245 - 0x100281c: 0x281c, // XK_braille_dots_345: BRAILLE PATTERN DOTS-345 - 0x100281d: 0x281d, // XK_braille_dots_1345: BRAILLE PATTERN DOTS-1345 - 0x100281e: 0x281e, // XK_braille_dots_2345: BRAILLE PATTERN DOTS-2345 - 0x100281f: 0x281f, // XK_braille_dots_12345: BRAILLE PATTERN DOTS-12345 - 0x1002820: 0x2820, // XK_braille_dots_6: BRAILLE PATTERN DOTS-6 - 0x1002821: 0x2821, // XK_braille_dots_16: BRAILLE PATTERN DOTS-16 - 0x1002822: 0x2822, // XK_braille_dots_26: BRAILLE PATTERN DOTS-26 - 0x1002823: 0x2823, // XK_braille_dots_126: BRAILLE PATTERN DOTS-126 - 0x1002824: 0x2824, // XK_braille_dots_36: BRAILLE PATTERN DOTS-36 - 0x1002825: 0x2825, // XK_braille_dots_136: BRAILLE PATTERN DOTS-136 - 0x1002826: 0x2826, // XK_braille_dots_236: BRAILLE PATTERN DOTS-236 - 0x1002827: 0x2827, // XK_braille_dots_1236: BRAILLE PATTERN DOTS-1236 - 0x1002828: 0x2828, // XK_braille_dots_46: BRAILLE PATTERN DOTS-46 - 0x1002829: 0x2829, // XK_braille_dots_146: BRAILLE PATTERN DOTS-146 - 0x100282a: 0x282a, // XK_braille_dots_246: BRAILLE PATTERN DOTS-246 - 0x100282b: 0x282b, // XK_braille_dots_1246: BRAILLE PATTERN DOTS-1246 - 0x100282c: 0x282c, // XK_braille_dots_346: BRAILLE PATTERN DOTS-346 - 0x100282d: 0x282d, // XK_braille_dots_1346: BRAILLE PATTERN DOTS-1346 - 0x100282e: 0x282e, // XK_braille_dots_2346: BRAILLE PATTERN DOTS-2346 - 0x100282f: 0x282f, // XK_braille_dots_12346: BRAILLE PATTERN DOTS-12346 - 0x1002830: 0x2830, // XK_braille_dots_56: BRAILLE PATTERN DOTS-56 - 0x1002831: 0x2831, // XK_braille_dots_156: BRAILLE PATTERN DOTS-156 - 0x1002832: 0x2832, // XK_braille_dots_256: BRAILLE PATTERN DOTS-256 - 0x1002833: 0x2833, // XK_braille_dots_1256: BRAILLE PATTERN DOTS-1256 - 0x1002834: 0x2834, // XK_braille_dots_356: BRAILLE PATTERN DOTS-356 - 0x1002835: 0x2835, // XK_braille_dots_1356: BRAILLE PATTERN DOTS-1356 - 0x1002836: 0x2836, // XK_braille_dots_2356: BRAILLE PATTERN DOTS-2356 - 0x1002837: 0x2837, // XK_braille_dots_12356: BRAILLE PATTERN DOTS-12356 - 0x1002838: 0x2838, // XK_braille_dots_456: BRAILLE PATTERN DOTS-456 - 0x1002839: 0x2839, // XK_braille_dots_1456: BRAILLE PATTERN DOTS-1456 - 0x100283a: 0x283a, // XK_braille_dots_2456: BRAILLE PATTERN DOTS-2456 - 0x100283b: 0x283b, // XK_braille_dots_12456: BRAILLE PATTERN DOTS-12456 - 0x100283c: 0x283c, // XK_braille_dots_3456: BRAILLE PATTERN DOTS-3456 - 0x100283d: 0x283d, // XK_braille_dots_13456: BRAILLE PATTERN DOTS-13456 - 0x100283e: 0x283e, // XK_braille_dots_23456: BRAILLE PATTERN DOTS-23456 - 0x100283f: 0x283f, // XK_braille_dots_123456: BRAILLE PATTERN DOTS-123456 - 0x1002840: 0x2840, // XK_braille_dots_7: BRAILLE PATTERN DOTS-7 - 0x1002841: 0x2841, // XK_braille_dots_17: BRAILLE PATTERN DOTS-17 - 0x1002842: 0x2842, // XK_braille_dots_27: BRAILLE PATTERN DOTS-27 - 0x1002843: 0x2843, // XK_braille_dots_127: BRAILLE PATTERN DOTS-127 - 0x1002844: 0x2844, // XK_braille_dots_37: BRAILLE PATTERN DOTS-37 - 0x1002845: 0x2845, // XK_braille_dots_137: BRAILLE PATTERN DOTS-137 - 0x1002846: 0x2846, // XK_braille_dots_237: BRAILLE PATTERN DOTS-237 - 0x1002847: 0x2847, // XK_braille_dots_1237: BRAILLE PATTERN DOTS-1237 - 0x1002848: 0x2848, // XK_braille_dots_47: BRAILLE PATTERN DOTS-47 - 0x1002849: 0x2849, // XK_braille_dots_147: BRAILLE PATTERN DOTS-147 - 0x100284a: 0x284a, // XK_braille_dots_247: BRAILLE PATTERN DOTS-247 - 0x100284b: 0x284b, // XK_braille_dots_1247: BRAILLE PATTERN DOTS-1247 - 0x100284c: 0x284c, // XK_braille_dots_347: BRAILLE PATTERN DOTS-347 - 0x100284d: 0x284d, // XK_braille_dots_1347: BRAILLE PATTERN DOTS-1347 - 0x100284e: 0x284e, // XK_braille_dots_2347: BRAILLE PATTERN DOTS-2347 - 0x100284f: 0x284f, // XK_braille_dots_12347: BRAILLE PATTERN DOTS-12347 - 0x1002850: 0x2850, // XK_braille_dots_57: BRAILLE PATTERN DOTS-57 - 0x1002851: 0x2851, // XK_braille_dots_157: BRAILLE PATTERN DOTS-157 - 0x1002852: 0x2852, // XK_braille_dots_257: BRAILLE PATTERN DOTS-257 - 0x1002853: 0x2853, // XK_braille_dots_1257: BRAILLE PATTERN DOTS-1257 - 0x1002854: 0x2854, // XK_braille_dots_357: BRAILLE PATTERN DOTS-357 - 0x1002855: 0x2855, // XK_braille_dots_1357: BRAILLE PATTERN DOTS-1357 - 0x1002856: 0x2856, // XK_braille_dots_2357: BRAILLE PATTERN DOTS-2357 - 0x1002857: 0x2857, // XK_braille_dots_12357: BRAILLE PATTERN DOTS-12357 - 0x1002858: 0x2858, // XK_braille_dots_457: BRAILLE PATTERN DOTS-457 - 0x1002859: 0x2859, // XK_braille_dots_1457: BRAILLE PATTERN DOTS-1457 - 0x100285a: 0x285a, // XK_braille_dots_2457: BRAILLE PATTERN DOTS-2457 - 0x100285b: 0x285b, // XK_braille_dots_12457: BRAILLE PATTERN DOTS-12457 - 0x100285c: 0x285c, // XK_braille_dots_3457: BRAILLE PATTERN DOTS-3457 - 0x100285d: 0x285d, // XK_braille_dots_13457: BRAILLE PATTERN DOTS-13457 - 0x100285e: 0x285e, // XK_braille_dots_23457: BRAILLE PATTERN DOTS-23457 - 0x100285f: 0x285f, // XK_braille_dots_123457: BRAILLE PATTERN DOTS-123457 - 0x1002860: 0x2860, // XK_braille_dots_67: BRAILLE PATTERN DOTS-67 - 0x1002861: 0x2861, // XK_braille_dots_167: BRAILLE PATTERN DOTS-167 - 0x1002862: 0x2862, // XK_braille_dots_267: BRAILLE PATTERN DOTS-267 - 0x1002863: 0x2863, // XK_braille_dots_1267: BRAILLE PATTERN DOTS-1267 - 0x1002864: 0x2864, // XK_braille_dots_367: BRAILLE PATTERN DOTS-367 - 0x1002865: 0x2865, // XK_braille_dots_1367: BRAILLE PATTERN DOTS-1367 - 0x1002866: 0x2866, // XK_braille_dots_2367: BRAILLE PATTERN DOTS-2367 - 0x1002867: 0x2867, // XK_braille_dots_12367: BRAILLE PATTERN DOTS-12367 - 0x1002868: 0x2868, // XK_braille_dots_467: BRAILLE PATTERN DOTS-467 - 0x1002869: 0x2869, // XK_braille_dots_1467: BRAILLE PATTERN DOTS-1467 - 0x100286a: 0x286a, // XK_braille_dots_2467: BRAILLE PATTERN DOTS-2467 - 0x100286b: 0x286b, // XK_braille_dots_12467: BRAILLE PATTERN DOTS-12467 - 0x100286c: 0x286c, // XK_braille_dots_3467: BRAILLE PATTERN DOTS-3467 - 0x100286d: 0x286d, // XK_braille_dots_13467: BRAILLE PATTERN DOTS-13467 - 0x100286e: 0x286e, // XK_braille_dots_23467: BRAILLE PATTERN DOTS-23467 - 0x100286f: 0x286f, // XK_braille_dots_123467: BRAILLE PATTERN DOTS-123467 - 0x1002870: 0x2870, // XK_braille_dots_567: BRAILLE PATTERN DOTS-567 - 0x1002871: 0x2871, // XK_braille_dots_1567: BRAILLE PATTERN DOTS-1567 - 0x1002872: 0x2872, // XK_braille_dots_2567: BRAILLE PATTERN DOTS-2567 - 0x1002873: 0x2873, // XK_braille_dots_12567: BRAILLE PATTERN DOTS-12567 - 0x1002874: 0x2874, // XK_braille_dots_3567: BRAILLE PATTERN DOTS-3567 - 0x1002875: 0x2875, // XK_braille_dots_13567: BRAILLE PATTERN DOTS-13567 - 0x1002876: 0x2876, // XK_braille_dots_23567: BRAILLE PATTERN DOTS-23567 - 0x1002877: 0x2877, // XK_braille_dots_123567: BRAILLE PATTERN DOTS-123567 - 0x1002878: 0x2878, // XK_braille_dots_4567: BRAILLE PATTERN DOTS-4567 - 0x1002879: 0x2879, // XK_braille_dots_14567: BRAILLE PATTERN DOTS-14567 - 0x100287a: 0x287a, // XK_braille_dots_24567: BRAILLE PATTERN DOTS-24567 - 0x100287b: 0x287b, // XK_braille_dots_124567: BRAILLE PATTERN DOTS-124567 - 0x100287c: 0x287c, // XK_braille_dots_34567: BRAILLE PATTERN DOTS-34567 - 0x100287d: 0x287d, // XK_braille_dots_134567: BRAILLE PATTERN DOTS-134567 - 0x100287e: 0x287e, // XK_braille_dots_234567: BRAILLE PATTERN DOTS-234567 - 0x100287f: 0x287f, // XK_braille_dots_1234567: BRAILLE PATTERN DOTS-1234567 - 0x1002880: 0x2880, // XK_braille_dots_8: BRAILLE PATTERN DOTS-8 - 0x1002881: 0x2881, // XK_braille_dots_18: BRAILLE PATTERN DOTS-18 - 0x1002882: 0x2882, // XK_braille_dots_28: BRAILLE PATTERN DOTS-28 - 0x1002883: 0x2883, // XK_braille_dots_128: BRAILLE PATTERN DOTS-128 - 0x1002884: 0x2884, // XK_braille_dots_38: BRAILLE PATTERN DOTS-38 - 0x1002885: 0x2885, // XK_braille_dots_138: BRAILLE PATTERN DOTS-138 - 0x1002886: 0x2886, // XK_braille_dots_238: BRAILLE PATTERN DOTS-238 - 0x1002887: 0x2887, // XK_braille_dots_1238: BRAILLE PATTERN DOTS-1238 - 0x1002888: 0x2888, // XK_braille_dots_48: BRAILLE PATTERN DOTS-48 - 0x1002889: 0x2889, // XK_braille_dots_148: BRAILLE PATTERN DOTS-148 - 0x100288a: 0x288a, // XK_braille_dots_248: BRAILLE PATTERN DOTS-248 - 0x100288b: 0x288b, // XK_braille_dots_1248: BRAILLE PATTERN DOTS-1248 - 0x100288c: 0x288c, // XK_braille_dots_348: BRAILLE PATTERN DOTS-348 - 0x100288d: 0x288d, // XK_braille_dots_1348: BRAILLE PATTERN DOTS-1348 - 0x100288e: 0x288e, // XK_braille_dots_2348: BRAILLE PATTERN DOTS-2348 - 0x100288f: 0x288f, // XK_braille_dots_12348: BRAILLE PATTERN DOTS-12348 - 0x1002890: 0x2890, // XK_braille_dots_58: BRAILLE PATTERN DOTS-58 - 0x1002891: 0x2891, // XK_braille_dots_158: BRAILLE PATTERN DOTS-158 - 0x1002892: 0x2892, // XK_braille_dots_258: BRAILLE PATTERN DOTS-258 - 0x1002893: 0x2893, // XK_braille_dots_1258: BRAILLE PATTERN DOTS-1258 - 0x1002894: 0x2894, // XK_braille_dots_358: BRAILLE PATTERN DOTS-358 - 0x1002895: 0x2895, // XK_braille_dots_1358: BRAILLE PATTERN DOTS-1358 - 0x1002896: 0x2896, // XK_braille_dots_2358: BRAILLE PATTERN DOTS-2358 - 0x1002897: 0x2897, // XK_braille_dots_12358: BRAILLE PATTERN DOTS-12358 - 0x1002898: 0x2898, // XK_braille_dots_458: BRAILLE PATTERN DOTS-458 - 0x1002899: 0x2899, // XK_braille_dots_1458: BRAILLE PATTERN DOTS-1458 - 0x100289a: 0x289a, // XK_braille_dots_2458: BRAILLE PATTERN DOTS-2458 - 0x100289b: 0x289b, // XK_braille_dots_12458: BRAILLE PATTERN DOTS-12458 - 0x100289c: 0x289c, // XK_braille_dots_3458: BRAILLE PATTERN DOTS-3458 - 0x100289d: 0x289d, // XK_braille_dots_13458: BRAILLE PATTERN DOTS-13458 - 0x100289e: 0x289e, // XK_braille_dots_23458: BRAILLE PATTERN DOTS-23458 - 0x100289f: 0x289f, // XK_braille_dots_123458: BRAILLE PATTERN DOTS-123458 - 0x10028a0: 0x28a0, // XK_braille_dots_68: BRAILLE PATTERN DOTS-68 - 0x10028a1: 0x28a1, // XK_braille_dots_168: BRAILLE PATTERN DOTS-168 - 0x10028a2: 0x28a2, // XK_braille_dots_268: BRAILLE PATTERN DOTS-268 - 0x10028a3: 0x28a3, // XK_braille_dots_1268: BRAILLE PATTERN DOTS-1268 - 0x10028a4: 0x28a4, // XK_braille_dots_368: BRAILLE PATTERN DOTS-368 - 0x10028a5: 0x28a5, // XK_braille_dots_1368: BRAILLE PATTERN DOTS-1368 - 0x10028a6: 0x28a6, // XK_braille_dots_2368: BRAILLE PATTERN DOTS-2368 - 0x10028a7: 0x28a7, // XK_braille_dots_12368: BRAILLE PATTERN DOTS-12368 - 0x10028a8: 0x28a8, // XK_braille_dots_468: BRAILLE PATTERN DOTS-468 - 0x10028a9: 0x28a9, // XK_braille_dots_1468: BRAILLE PATTERN DOTS-1468 - 0x10028aa: 0x28aa, // XK_braille_dots_2468: BRAILLE PATTERN DOTS-2468 - 0x10028ab: 0x28ab, // XK_braille_dots_12468: BRAILLE PATTERN DOTS-12468 - 0x10028ac: 0x28ac, // XK_braille_dots_3468: BRAILLE PATTERN DOTS-3468 - 0x10028ad: 0x28ad, // XK_braille_dots_13468: BRAILLE PATTERN DOTS-13468 - 0x10028ae: 0x28ae, // XK_braille_dots_23468: BRAILLE PATTERN DOTS-23468 - 0x10028af: 0x28af, // XK_braille_dots_123468: BRAILLE PATTERN DOTS-123468 - 0x10028b0: 0x28b0, // XK_braille_dots_568: BRAILLE PATTERN DOTS-568 - 0x10028b1: 0x28b1, // XK_braille_dots_1568: BRAILLE PATTERN DOTS-1568 - 0x10028b2: 0x28b2, // XK_braille_dots_2568: BRAILLE PATTERN DOTS-2568 - 0x10028b3: 0x28b3, // XK_braille_dots_12568: BRAILLE PATTERN DOTS-12568 - 0x10028b4: 0x28b4, // XK_braille_dots_3568: BRAILLE PATTERN DOTS-3568 - 0x10028b5: 0x28b5, // XK_braille_dots_13568: BRAILLE PATTERN DOTS-13568 - 0x10028b6: 0x28b6, // XK_braille_dots_23568: BRAILLE PATTERN DOTS-23568 - 0x10028b7: 0x28b7, // XK_braille_dots_123568: BRAILLE PATTERN DOTS-123568 - 0x10028b8: 0x28b8, // XK_braille_dots_4568: BRAILLE PATTERN DOTS-4568 - 0x10028b9: 0x28b9, // XK_braille_dots_14568: BRAILLE PATTERN DOTS-14568 - 0x10028ba: 0x28ba, // XK_braille_dots_24568: BRAILLE PATTERN DOTS-24568 - 0x10028bb: 0x28bb, // XK_braille_dots_124568: BRAILLE PATTERN DOTS-124568 - 0x10028bc: 0x28bc, // XK_braille_dots_34568: BRAILLE PATTERN DOTS-34568 - 0x10028bd: 0x28bd, // XK_braille_dots_134568: BRAILLE PATTERN DOTS-134568 - 0x10028be: 0x28be, // XK_braille_dots_234568: BRAILLE PATTERN DOTS-234568 - 0x10028bf: 0x28bf, // XK_braille_dots_1234568: BRAILLE PATTERN DOTS-1234568 - 0x10028c0: 0x28c0, // XK_braille_dots_78: BRAILLE PATTERN DOTS-78 - 0x10028c1: 0x28c1, // XK_braille_dots_178: BRAILLE PATTERN DOTS-178 - 0x10028c2: 0x28c2, // XK_braille_dots_278: BRAILLE PATTERN DOTS-278 - 0x10028c3: 0x28c3, // XK_braille_dots_1278: BRAILLE PATTERN DOTS-1278 - 0x10028c4: 0x28c4, // XK_braille_dots_378: BRAILLE PATTERN DOTS-378 - 0x10028c5: 0x28c5, // XK_braille_dots_1378: BRAILLE PATTERN DOTS-1378 - 0x10028c6: 0x28c6, // XK_braille_dots_2378: BRAILLE PATTERN DOTS-2378 - 0x10028c7: 0x28c7, // XK_braille_dots_12378: BRAILLE PATTERN DOTS-12378 - 0x10028c8: 0x28c8, // XK_braille_dots_478: BRAILLE PATTERN DOTS-478 - 0x10028c9: 0x28c9, // XK_braille_dots_1478: BRAILLE PATTERN DOTS-1478 - 0x10028ca: 0x28ca, // XK_braille_dots_2478: BRAILLE PATTERN DOTS-2478 - 0x10028cb: 0x28cb, // XK_braille_dots_12478: BRAILLE PATTERN DOTS-12478 - 0x10028cc: 0x28cc, // XK_braille_dots_3478: BRAILLE PATTERN DOTS-3478 - 0x10028cd: 0x28cd, // XK_braille_dots_13478: BRAILLE PATTERN DOTS-13478 - 0x10028ce: 0x28ce, // XK_braille_dots_23478: BRAILLE PATTERN DOTS-23478 - 0x10028cf: 0x28cf, // XK_braille_dots_123478: BRAILLE PATTERN DOTS-123478 - 0x10028d0: 0x28d0, // XK_braille_dots_578: BRAILLE PATTERN DOTS-578 - 0x10028d1: 0x28d1, // XK_braille_dots_1578: BRAILLE PATTERN DOTS-1578 - 0x10028d2: 0x28d2, // XK_braille_dots_2578: BRAILLE PATTERN DOTS-2578 - 0x10028d3: 0x28d3, // XK_braille_dots_12578: BRAILLE PATTERN DOTS-12578 - 0x10028d4: 0x28d4, // XK_braille_dots_3578: BRAILLE PATTERN DOTS-3578 - 0x10028d5: 0x28d5, // XK_braille_dots_13578: BRAILLE PATTERN DOTS-13578 - 0x10028d6: 0x28d6, // XK_braille_dots_23578: BRAILLE PATTERN DOTS-23578 - 0x10028d7: 0x28d7, // XK_braille_dots_123578: BRAILLE PATTERN DOTS-123578 - 0x10028d8: 0x28d8, // XK_braille_dots_4578: BRAILLE PATTERN DOTS-4578 - 0x10028d9: 0x28d9, // XK_braille_dots_14578: BRAILLE PATTERN DOTS-14578 - 0x10028da: 0x28da, // XK_braille_dots_24578: BRAILLE PATTERN DOTS-24578 - 0x10028db: 0x28db, // XK_braille_dots_124578: BRAILLE PATTERN DOTS-124578 - 0x10028dc: 0x28dc, // XK_braille_dots_34578: BRAILLE PATTERN DOTS-34578 - 0x10028dd: 0x28dd, // XK_braille_dots_134578: BRAILLE PATTERN DOTS-134578 - 0x10028de: 0x28de, // XK_braille_dots_234578: BRAILLE PATTERN DOTS-234578 - 0x10028df: 0x28df, // XK_braille_dots_1234578: BRAILLE PATTERN DOTS-1234578 - 0x10028e0: 0x28e0, // XK_braille_dots_678: BRAILLE PATTERN DOTS-678 - 0x10028e1: 0x28e1, // XK_braille_dots_1678: BRAILLE PATTERN DOTS-1678 - 0x10028e2: 0x28e2, // XK_braille_dots_2678: BRAILLE PATTERN DOTS-2678 - 0x10028e3: 0x28e3, // XK_braille_dots_12678: BRAILLE PATTERN DOTS-12678 - 0x10028e4: 0x28e4, // XK_braille_dots_3678: BRAILLE PATTERN DOTS-3678 - 0x10028e5: 0x28e5, // XK_braille_dots_13678: BRAILLE PATTERN DOTS-13678 - 0x10028e6: 0x28e6, // XK_braille_dots_23678: BRAILLE PATTERN DOTS-23678 - 0x10028e7: 0x28e7, // XK_braille_dots_123678: BRAILLE PATTERN DOTS-123678 - 0x10028e8: 0x28e8, // XK_braille_dots_4678: BRAILLE PATTERN DOTS-4678 - 0x10028e9: 0x28e9, // XK_braille_dots_14678: BRAILLE PATTERN DOTS-14678 - 0x10028ea: 0x28ea, // XK_braille_dots_24678: BRAILLE PATTERN DOTS-24678 - 0x10028eb: 0x28eb, // XK_braille_dots_124678: BRAILLE PATTERN DOTS-124678 - 0x10028ec: 0x28ec, // XK_braille_dots_34678: BRAILLE PATTERN DOTS-34678 - 0x10028ed: 0x28ed, // XK_braille_dots_134678: BRAILLE PATTERN DOTS-134678 - 0x10028ee: 0x28ee, // XK_braille_dots_234678: BRAILLE PATTERN DOTS-234678 - 0x10028ef: 0x28ef, // XK_braille_dots_1234678: BRAILLE PATTERN DOTS-1234678 - 0x10028f0: 0x28f0, // XK_braille_dots_5678: BRAILLE PATTERN DOTS-5678 - 0x10028f1: 0x28f1, // XK_braille_dots_15678: BRAILLE PATTERN DOTS-15678 - 0x10028f2: 0x28f2, // XK_braille_dots_25678: BRAILLE PATTERN DOTS-25678 - 0x10028f3: 0x28f3, // XK_braille_dots_125678: BRAILLE PATTERN DOTS-125678 - 0x10028f4: 0x28f4, // XK_braille_dots_35678: BRAILLE PATTERN DOTS-35678 - 0x10028f5: 0x28f5, // XK_braille_dots_135678: BRAILLE PATTERN DOTS-135678 - 0x10028f6: 0x28f6, // XK_braille_dots_235678: BRAILLE PATTERN DOTS-235678 - 0x10028f7: 0x28f7, // XK_braille_dots_1235678: BRAILLE PATTERN DOTS-1235678 - 0x10028f8: 0x28f8, // XK_braille_dots_45678: BRAILLE PATTERN DOTS-45678 - 0x10028f9: 0x28f9, // XK_braille_dots_145678: BRAILLE PATTERN DOTS-145678 - 0x10028fa: 0x28fa, // XK_braille_dots_245678: BRAILLE PATTERN DOTS-245678 - 0x10028fb: 0x28fb, // XK_braille_dots_1245678: BRAILLE PATTERN DOTS-1245678 - 0x10028fc: 0x28fc, // XK_braille_dots_345678: BRAILLE PATTERN DOTS-345678 - 0x10028fd: 0x28fd, // XK_braille_dots_1345678: BRAILLE PATTERN DOTS-1345678 - 0x10028fe: 0x28fe, // XK_braille_dots_2345678: BRAILLE PATTERN DOTS-2345678 - 0x10028ff: 0x28ff, // XK_braille_dots_12345678: BRAILLE PATTERN DOTS-12345678 - 0x1000d82: 0x0D82, // XK_Sinh_ng: SINHALA ANUSVARAYA - 0x1000d83: 0x0D83, // XK_Sinh_h2: SINHALA VISARGAYA - 0x1000d85: 0x0D85, // XK_Sinh_a: SINHALA AYANNA - 0x1000d86: 0x0D86, // XK_Sinh_aa: SINHALA AAYANNA - 0x1000d87: 0x0D87, // XK_Sinh_ae: SINHALA AEYANNA - 0x1000d88: 0x0D88, // XK_Sinh_aee: SINHALA AEEYANNA - 0x1000d89: 0x0D89, // XK_Sinh_i: SINHALA IYANNA - 0x1000d8a: 0x0D8A, // XK_Sinh_ii: SINHALA IIYANNA - 0x1000d8b: 0x0D8B, // XK_Sinh_u: SINHALA UYANNA - 0x1000d8c: 0x0D8C, // XK_Sinh_uu: SINHALA UUYANNA - 0x1000d8d: 0x0D8D, // XK_Sinh_ri: SINHALA IRUYANNA - 0x1000d8e: 0x0D8E, // XK_Sinh_rii: SINHALA IRUUYANNA - 0x1000d8f: 0x0D8F, // XK_Sinh_lu: SINHALA ILUYANNA - 0x1000d90: 0x0D90, // XK_Sinh_luu: SINHALA ILUUYANNA - 0x1000d91: 0x0D91, // XK_Sinh_e: SINHALA EYANNA - 0x1000d92: 0x0D92, // XK_Sinh_ee: SINHALA EEYANNA - 0x1000d93: 0x0D93, // XK_Sinh_ai: SINHALA AIYANNA - 0x1000d94: 0x0D94, // XK_Sinh_o: SINHALA OYANNA - 0x1000d95: 0x0D95, // XK_Sinh_oo: SINHALA OOYANNA - 0x1000d96: 0x0D96, // XK_Sinh_au: SINHALA AUYANNA - 0x1000d9a: 0x0D9A, // XK_Sinh_ka: SINHALA KAYANNA - 0x1000d9b: 0x0D9B, // XK_Sinh_kha: SINHALA MAHA. KAYANNA - 0x1000d9c: 0x0D9C, // XK_Sinh_ga: SINHALA GAYANNA - 0x1000d9d: 0x0D9D, // XK_Sinh_gha: SINHALA MAHA. GAYANNA - 0x1000d9e: 0x0D9E, // XK_Sinh_ng2: SINHALA KANTAJA NAASIKYAYA - 0x1000d9f: 0x0D9F, // XK_Sinh_nga: SINHALA SANYAKA GAYANNA - 0x1000da0: 0x0DA0, // XK_Sinh_ca: SINHALA CAYANNA - 0x1000da1: 0x0DA1, // XK_Sinh_cha: SINHALA MAHA. CAYANNA - 0x1000da2: 0x0DA2, // XK_Sinh_ja: SINHALA JAYANNA - 0x1000da3: 0x0DA3, // XK_Sinh_jha: SINHALA MAHA. JAYANNA - 0x1000da4: 0x0DA4, // XK_Sinh_nya: SINHALA TAALUJA NAASIKYAYA - 0x1000da5: 0x0DA5, // XK_Sinh_jnya: SINHALA TAALUJA SANYOOGA NAASIKYAYA - 0x1000da6: 0x0DA6, // XK_Sinh_nja: SINHALA SANYAKA JAYANNA - 0x1000da7: 0x0DA7, // XK_Sinh_tta: SINHALA TTAYANNA - 0x1000da8: 0x0DA8, // XK_Sinh_ttha: SINHALA MAHA. TTAYANNA - 0x1000da9: 0x0DA9, // XK_Sinh_dda: SINHALA DDAYANNA - 0x1000daa: 0x0DAA, // XK_Sinh_ddha: SINHALA MAHA. DDAYANNA - 0x1000dab: 0x0DAB, // XK_Sinh_nna: SINHALA MUURDHAJA NAYANNA - 0x1000dac: 0x0DAC, // XK_Sinh_ndda: SINHALA SANYAKA DDAYANNA - 0x1000dad: 0x0DAD, // XK_Sinh_tha: SINHALA TAYANNA - 0x1000dae: 0x0DAE, // XK_Sinh_thha: SINHALA MAHA. TAYANNA - 0x1000daf: 0x0DAF, // XK_Sinh_dha: SINHALA DAYANNA - 0x1000db0: 0x0DB0, // XK_Sinh_dhha: SINHALA MAHA. DAYANNA - 0x1000db1: 0x0DB1, // XK_Sinh_na: SINHALA DANTAJA NAYANNA - 0x1000db3: 0x0DB3, // XK_Sinh_ndha: SINHALA SANYAKA DAYANNA - 0x1000db4: 0x0DB4, // XK_Sinh_pa: SINHALA PAYANNA - 0x1000db5: 0x0DB5, // XK_Sinh_pha: SINHALA MAHA. PAYANNA - 0x1000db6: 0x0DB6, // XK_Sinh_ba: SINHALA BAYANNA - 0x1000db7: 0x0DB7, // XK_Sinh_bha: SINHALA MAHA. BAYANNA - 0x1000db8: 0x0DB8, // XK_Sinh_ma: SINHALA MAYANNA - 0x1000db9: 0x0DB9, // XK_Sinh_mba: SINHALA AMBA BAYANNA - 0x1000dba: 0x0DBA, // XK_Sinh_ya: SINHALA YAYANNA - 0x1000dbb: 0x0DBB, // XK_Sinh_ra: SINHALA RAYANNA - 0x1000dbd: 0x0DBD, // XK_Sinh_la: SINHALA DANTAJA LAYANNA - 0x1000dc0: 0x0DC0, // XK_Sinh_va: SINHALA VAYANNA - 0x1000dc1: 0x0DC1, // XK_Sinh_sha: SINHALA TAALUJA SAYANNA - 0x1000dc2: 0x0DC2, // XK_Sinh_ssha: SINHALA MUURDHAJA SAYANNA - 0x1000dc3: 0x0DC3, // XK_Sinh_sa: SINHALA DANTAJA SAYANNA - 0x1000dc4: 0x0DC4, // XK_Sinh_ha: SINHALA HAYANNA - 0x1000dc5: 0x0DC5, // XK_Sinh_lla: SINHALA MUURDHAJA LAYANNA - 0x1000dc6: 0x0DC6, // XK_Sinh_fa: SINHALA FAYANNA - 0x1000dca: 0x0DCA, // XK_Sinh_al: SINHALA AL-LAKUNA - 0x1000dcf: 0x0DCF, // XK_Sinh_aa2: SINHALA AELA-PILLA - 0x1000dd0: 0x0DD0, // XK_Sinh_ae2: SINHALA AEDA-PILLA - 0x1000dd1: 0x0DD1, // XK_Sinh_aee2: SINHALA DIGA AEDA-PILLA - 0x1000dd2: 0x0DD2, // XK_Sinh_i2: SINHALA IS-PILLA - 0x1000dd3: 0x0DD3, // XK_Sinh_ii2: SINHALA DIGA IS-PILLA - 0x1000dd4: 0x0DD4, // XK_Sinh_u2: SINHALA PAA-PILLA - 0x1000dd6: 0x0DD6, // XK_Sinh_uu2: SINHALA DIGA PAA-PILLA - 0x1000dd8: 0x0DD8, // XK_Sinh_ru2: SINHALA GAETTA-PILLA - 0x1000dd9: 0x0DD9, // XK_Sinh_e2: SINHALA KOMBUVA - 0x1000dda: 0x0DDA, // XK_Sinh_ee2: SINHALA DIGA KOMBUVA - 0x1000ddb: 0x0DDB, // XK_Sinh_ai2: SINHALA KOMBU DEKA - 0x1000dde: 0x0DDE, // XK_Sinh_au2: SINHALA KOMBUVA HAA GAYANUKITTA - 0x1000ddf: 0x0DDF, // XK_Sinh_lu2: SINHALA GAYANUKITTA - 0x1000df2: 0x0DF2, // XK_Sinh_ruu2: SINHALA DIGA GAETTA-PILLA - 0x1000df3: 0x0DF3, // XK_Sinh_luu2: SINHALA DIGA GAYANUKITTA - 0x1000df4: 0x0DF4, // XK_Sinh_kunddaliya: SINHALA KUNDDALIYA -} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/x11key/x11key.go b/vendor/golang.org/x/exp/shiny/driver/internal/x11key/x11key.go deleted file mode 100644 index 546d463..0000000 --- a/vendor/golang.org/x/exp/shiny/driver/internal/x11key/x11key.go +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go - -// x11key contains X11 numeric codes for the keyboard and mouse. -package x11key // import "golang.org/x/exp/shiny/driver/internal/x11key" - -import ( - "unicode" - - "golang.org/x/mobile/event/key" -) - -// These constants come from /usr/include/X11/X.h -const ( - ShiftMask = 1 << 0 - LockMask = 1 << 1 - ControlMask = 1 << 2 - Mod1Mask = 1 << 3 - Mod2Mask = 1 << 4 - Mod3Mask = 1 << 5 - Mod4Mask = 1 << 6 - Mod5Mask = 1 << 7 - Button1Mask = 1 << 8 - Button2Mask = 1 << 9 - Button3Mask = 1 << 10 - Button4Mask = 1 << 11 - Button5Mask = 1 << 12 -) - -type KeysymTable struct { - Table [256][6]uint32 - - NumLockMod, ModeSwitchMod, ISOLevel3ShiftMod uint16 -} - -func (t *KeysymTable) Lookup(detail uint8, state uint16) (rune, key.Code) { - te := t.Table[detail][0:2] - if state&t.ModeSwitchMod != 0 { - te = t.Table[detail][2:4] - } - if state&t.ISOLevel3ShiftMod != 0 { - te = t.Table[detail][4:6] - } - - // The key event's rune depends on whether the shift key is down. - unshifted := rune(te[0]) - r := unshifted - if state&t.NumLockMod != 0 && isKeypad(te[1]) { - if state&ShiftMask == 0 { - r = rune(te[1]) - } - } else if state&ShiftMask != 0 { - r = rune(te[1]) - // In X11, a zero keysym when shift is down means to use what the - // keysym is when shift is up. - if r == 0 { - r = unshifted - } - } - - // The key event's code is independent of whether the shift key is down. - var c key.Code - if 0 <= unshifted && unshifted < 0x80 { - c = asciiKeycodes[unshifted] - if state&LockMask != 0 { - r = unicode.ToUpper(r) - } - } else if kk, isKeypad := keypadKeysyms[r]; isKeypad { - r, c = kk.rune, kk.code - } else if nuk := nonUnicodeKeycodes[unshifted]; nuk != key.CodeUnknown { - r, c = -1, nuk - } else { - r = keysymCodePoints[r] - if state&LockMask != 0 { - r = unicode.ToUpper(r) - } - } - - return r, c -} - -func isKeypad(keysym uint32) bool { - return keysym >= 0xff80 && keysym <= 0xffbd -} - -func KeyModifiers(state uint16) (m key.Modifiers) { - if state&ShiftMask != 0 { - m |= key.ModShift - } - if state&ControlMask != 0 { - m |= key.ModControl - } - if state&Mod1Mask != 0 { - m |= key.ModAlt - } - if state&Mod4Mask != 0 { - m |= key.ModMeta - } - return m -} - -// These constants come from /usr/include/X11/{keysymdef,XF86keysym}.h -const ( - xkISOLeftTab = 0xfe20 - xkBackSpace = 0xff08 - xkTab = 0xff09 - xkReturn = 0xff0d - xkEscape = 0xff1b - xkMultiKey = 0xff20 - xkHome = 0xff50 - xkLeft = 0xff51 - xkUp = 0xff52 - xkRight = 0xff53 - xkDown = 0xff54 - xkPageUp = 0xff55 - xkPageDown = 0xff56 - xkEnd = 0xff57 - xkInsert = 0xff63 - xkMenu = 0xff67 - xkHelp = 0xff6a - - xkNumLock = 0xff7f - xkKeypadEnter = 0xff8d - xkKeypadHome = 0xff95 - xkKeypadLeft = 0xff96 - xkKeypadUp = 0xff97 - xkKeypadRight = 0xff98 - xkKeypadDown = 0xff99 - xkKeypadPageUp = 0xff9a - xkKeypadPageDown = 0xff9b - xkKeypadEnd = 0xff9c - xkKeypadInsert = 0xff9e - xkKeypadDelete = 0xff9f - xkKeypadEqual = 0xffbd - xkKeypadMultiply = 0xffaa - xkKeypadAdd = 0xffab - xkKeypadSubtract = 0xffad - xkKeypadDecimal = 0xffae - xkKeypadDivide = 0xffaf - xkKeypad0 = 0xffb0 - xkKeypad1 = 0xffb1 - xkKeypad2 = 0xffb2 - xkKeypad3 = 0xffb3 - xkKeypad4 = 0xffb4 - xkKeypad5 = 0xffb5 - xkKeypad6 = 0xffb6 - xkKeypad7 = 0xffb7 - xkKeypad8 = 0xffb8 - xkKeypad9 = 0xffb9 - - xkF1 = 0xffbe - xkF2 = 0xffbf - xkF3 = 0xffc0 - xkF4 = 0xffc1 - xkF5 = 0xffc2 - xkF6 = 0xffc3 - xkF7 = 0xffc4 - xkF8 = 0xffc5 - xkF9 = 0xffc6 - xkF10 = 0xffc7 - xkF11 = 0xffc8 - xkF12 = 0xffc9 - xkShiftL = 0xffe1 - xkShiftR = 0xffe2 - xkControlL = 0xffe3 - xkControlR = 0xffe4 - xkCapsLock = 0xffe5 - xkAltL = 0xffe9 - xkAltR = 0xffea - xkSuperL = 0xffeb - xkSuperR = 0xffec - xkDelete = 0xffff - - xf86xkAudioLowerVolume = 0x1008ff11 - xf86xkAudioMute = 0x1008ff12 - xf86xkAudioRaiseVolume = 0x1008ff13 -) - -// nonUnicodeKeycodes maps from those xproto.Keysym values (converted to runes) -// that do not correspond to a Unicode code point, such as "Page Up", "F1" or -// "Left Shift", to key.Code values. -var nonUnicodeKeycodes = map[rune]key.Code{ - xkISOLeftTab: key.CodeTab, - xkBackSpace: key.CodeDeleteBackspace, - xkTab: key.CodeTab, - xkReturn: key.CodeReturnEnter, - xkEscape: key.CodeEscape, - xkHome: key.CodeHome, - xkLeft: key.CodeLeftArrow, - xkUp: key.CodeUpArrow, - xkRight: key.CodeRightArrow, - xkDown: key.CodeDownArrow, - xkPageUp: key.CodePageUp, - xkPageDown: key.CodePageDown, - xkEnd: key.CodeEnd, - xkInsert: key.CodeInsert, - xkMenu: key.CodeRightGUI, // TODO: CodeRightGUI or CodeMenu?? - xkHelp: key.CodeHelp, - xkNumLock: key.CodeKeypadNumLock, - xkMultiKey: key.CodeCompose, - - xkKeypadEnter: key.CodeKeypadEnter, - xkKeypadHome: key.CodeHome, - xkKeypadLeft: key.CodeLeftArrow, - xkKeypadUp: key.CodeUpArrow, - xkKeypadRight: key.CodeRightArrow, - xkKeypadDown: key.CodeDownArrow, - xkKeypadPageUp: key.CodePageUp, - xkKeypadPageDown: key.CodePageDown, - xkKeypadEnd: key.CodeEnd, - xkKeypadInsert: key.CodeInsert, - xkKeypadDelete: key.CodeDeleteForward, - - xkF1: key.CodeF1, - xkF2: key.CodeF2, - xkF3: key.CodeF3, - xkF4: key.CodeF4, - xkF5: key.CodeF5, - xkF6: key.CodeF6, - xkF7: key.CodeF7, - xkF8: key.CodeF8, - xkF9: key.CodeF9, - xkF10: key.CodeF10, - xkF11: key.CodeF11, - xkF12: key.CodeF12, - - xkShiftL: key.CodeLeftShift, - xkShiftR: key.CodeRightShift, - xkControlL: key.CodeLeftControl, - xkControlR: key.CodeRightControl, - xkCapsLock: key.CodeCapsLock, - xkAltL: key.CodeLeftAlt, - xkAltR: key.CodeRightAlt, - xkSuperL: key.CodeLeftGUI, - xkSuperR: key.CodeRightGUI, - - xkDelete: key.CodeDeleteForward, - - xf86xkAudioRaiseVolume: key.CodeVolumeUp, - xf86xkAudioLowerVolume: key.CodeVolumeDown, - xf86xkAudioMute: key.CodeMute, -} - -// asciiKeycodes maps lower-case ASCII runes to key.Code values. -var asciiKeycodes = [0x80]key.Code{ - 'a': key.CodeA, - 'b': key.CodeB, - 'c': key.CodeC, - 'd': key.CodeD, - 'e': key.CodeE, - 'f': key.CodeF, - 'g': key.CodeG, - 'h': key.CodeH, - 'i': key.CodeI, - 'j': key.CodeJ, - 'k': key.CodeK, - 'l': key.CodeL, - 'm': key.CodeM, - 'n': key.CodeN, - 'o': key.CodeO, - 'p': key.CodeP, - 'q': key.CodeQ, - 'r': key.CodeR, - 's': key.CodeS, - 't': key.CodeT, - 'u': key.CodeU, - 'v': key.CodeV, - 'w': key.CodeW, - 'x': key.CodeX, - 'y': key.CodeY, - 'z': key.CodeZ, - - '1': key.Code1, - '2': key.Code2, - '3': key.Code3, - '4': key.Code4, - '5': key.Code5, - '6': key.Code6, - '7': key.Code7, - '8': key.Code8, - '9': key.Code9, - '0': key.Code0, - - ' ': key.CodeSpacebar, - '-': key.CodeHyphenMinus, - '=': key.CodeEqualSign, - '[': key.CodeLeftSquareBracket, - ']': key.CodeRightSquareBracket, - '\\': key.CodeBackslash, - ';': key.CodeSemicolon, - '\'': key.CodeApostrophe, - '`': key.CodeGraveAccent, - ',': key.CodeComma, - '.': key.CodeFullStop, - '/': key.CodeSlash, -} - -type keypadKeysym struct { - rune rune - code key.Code -} - -var keypadKeysyms = map[rune]keypadKeysym{ - xkKeypadEqual: {'=', key.CodeKeypadEqualSign}, - xkKeypadMultiply: {'*', key.CodeKeypadAsterisk}, - xkKeypadAdd: {'+', key.CodeKeypadPlusSign}, - xkKeypadSubtract: {'-', key.CodeKeypadHyphenMinus}, - xkKeypadDecimal: {'.', key.CodeKeypadFullStop}, - xkKeypadDivide: {'/', key.CodeKeypadSlash}, - xkKeypad0: {'0', key.CodeKeypad0}, - xkKeypad1: {'1', key.CodeKeypad1}, - xkKeypad2: {'2', key.CodeKeypad2}, - xkKeypad3: {'3', key.CodeKeypad3}, - xkKeypad4: {'4', key.CodeKeypad4}, - xkKeypad5: {'5', key.CodeKeypad5}, - xkKeypad6: {'6', key.CodeKeypad6}, - xkKeypad7: {'7', key.CodeKeypad7}, - xkKeypad8: {'8', key.CodeKeypad8}, - xkKeypad9: {'9', key.CodeKeypad9}, -} diff --git a/vendor/golang.org/x/exp/shiny/screen/screen.go b/vendor/golang.org/x/exp/shiny/screen/screen.go deleted file mode 100644 index 5d89fe8..0000000 --- a/vendor/golang.org/x/exp/shiny/screen/screen.go +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package screen provides interfaces for portable two-dimensional graphics and -// input events. -// -// Screens are not created directly. Instead, driver packages provide access to -// the screen through a Main function that is designed to be called by the -// program's main function. The golang.org/x/exp/shiny/driver package provides -// the default driver for the system, such as the X11 driver for desktop Linux, -// but other drivers, such as the OpenGL driver, can be explicitly invoked by -// calling that driver's Main function. To use the default driver: -// -// package main -// -// import ( -// "golang.org/x/exp/shiny/driver" -// "golang.org/x/exp/shiny/screen" -// "golang.org/x/mobile/event/lifecycle" -// ) -// -// func main() { -// driver.Main(func(s screen.Screen) { -// w, err := s.NewWindow(nil) -// if err != nil { -// handleError(err) -// return -// } -// defer w.Release() -// -// for { -// switch e := w.NextEvent().(type) { -// case lifecycle.Event: -// if e.To == lifecycle.StageDead { -// return -// } -// etc -// case etc: -// etc -// } -// } -// }) -// } -// -// Complete examples can be found in the shiny/example directory. -// -// Each driver package provides Screen, Buffer, Texture and Window -// implementations that work together. Such types are interface types because -// this package is driver-independent, but those interfaces aren't expected to -// be implemented outside of drivers. For example, a driver's Window -// implementation will generally work only with that driver's Buffer -// implementation, and will not work with an arbitrary type that happens to -// implement the Buffer methods. -package screen // import "golang.org/x/exp/shiny/screen" - -import ( - "image" - "image/color" - "image/draw" - "unicode/utf8" - - "golang.org/x/image/math/f64" -) - -// TODO: specify image format (Alpha or Gray, not just RGBA) for NewBuffer -// and/or NewTexture? - -// Screen creates Buffers, Textures and Windows. -type Screen interface { - // NewBuffer returns a new Buffer for this screen. - NewBuffer(size image.Point) (Buffer, error) - - // NewTexture returns a new Texture for this screen. - NewTexture(size image.Point) (Texture, error) - - // NewWindow returns a new Window for this screen. - // - // A nil opts is valid and means to use the default option values. - NewWindow(opts *NewWindowOptions) (Window, error) -} - -// TODO: rename Buffer to Image, to be less confusing with a Window's back and -// front buffers. - -// Buffer is an in-memory pixel buffer. Its pixels can be modified by any Go -// code that takes an *image.RGBA, such as the standard library's image/draw -// package. A Buffer is essentially an *image.RGBA, but not all *image.RGBA -// values (including those returned by image.NewRGBA) are valid Buffers, as a -// driver may assume that the memory backing a Buffer's pixels are specially -// allocated. -// -// To see a Buffer's contents on a screen, upload it to a Texture (and then -// draw the Texture on a Window) or upload it directly to a Window. -// -// When specifying a sub-Buffer via Upload, a Buffer's top-left pixel is always -// (0, 0) in its own coordinate space. -type Buffer interface { - // Release releases the Buffer's resources, after all pending uploads and - // draws resolve. - // - // The behavior of the Buffer after Release, whether calling its methods or - // passing it as an argument, is undefined. - Release() - - // Size returns the size of the Buffer's image. - Size() image.Point - - // Bounds returns the bounds of the Buffer's image. It is equal to - // image.Rectangle{Max: b.Size()}. - Bounds() image.Rectangle - - // RGBA returns the pixel buffer as an *image.RGBA. - // - // Its contents should not be accessed while the Buffer is uploading. - // - // The contents of the returned *image.RGBA's Pix field (of type []byte) - // can be modified at other times, but that Pix slice itself (i.e. its - // underlying pointer, length and capacity) should not be modified at any - // time. - // - // The following is valid: - // m := buffer.RGBA() - // if len(m.Pix) >= 4 { - // m.Pix[0] = 0xff - // m.Pix[1] = 0x00 - // m.Pix[2] = 0x00 - // m.Pix[3] = 0xff - // } - // or, equivalently: - // m := buffer.RGBA() - // m.SetRGBA(m.Rect.Min.X, m.Rect.Min.Y, color.RGBA{0xff, 0x00, 0x00, 0xff}) - // and using the standard library's image/draw package is also valid: - // dst := buffer.RGBA() - // draw.Draw(dst, dst.Bounds(), etc) - // but the following is invalid: - // m := buffer.RGBA() - // m.Pix = anotherByteSlice - // and so is this: - // *buffer.RGBA() = anotherImageRGBA - RGBA() *image.RGBA -} - -// Texture is a pixel buffer, but not one that is directly accessible as a -// []byte. Conceptually, it could live on a GPU, in another process or even be -// across a network, instead of on a CPU in this process. -// -// Buffers can be uploaded to Textures, and Textures can be drawn on Windows. -// -// When specifying a sub-Texture via Draw, a Texture's top-left pixel is always -// (0, 0) in its own coordinate space. -type Texture interface { - // Release releases the Texture's resources, after all pending uploads and - // draws resolve. - // - // The behavior of the Texture after Release, whether calling its methods - // or passing it as an argument, is undefined. - Release() - - // Size returns the size of the Texture's image. - Size() image.Point - - // Bounds returns the bounds of the Texture's image. It is equal to - // image.Rectangle{Max: t.Size()}. - Bounds() image.Rectangle - - Uploader - - // TODO: also implement Drawer? If so, merge the Uploader and Drawer - // interfaces?? -} - -// EventDeque is an infinitely buffered double-ended queue of events. -type EventDeque interface { - // Send adds an event to the end of the deque. They are returned by - // NextEvent in FIFO order. - Send(event interface{}) - - // SendFirst adds an event to the start of the deque. They are returned by - // NextEvent in LIFO order, and have priority over events sent via Send. - SendFirst(event interface{}) - - // NextEvent returns the next event in the deque. It blocks until such an - // event has been sent. - // - // Typical event types include: - // - lifecycle.Event - // - size.Event - // - paint.Event - // - key.Event - // - mouse.Event - // - touch.Event - // from the golang.org/x/mobile/event/... packages. Other packages may send - // events, of those types above or of other types, via Send or SendFirst. - NextEvent() interface{} - - // TODO: LatestLifecycleEvent? Is that still worth it if the - // lifecycle.Event struct type loses its DrawContext field? - - // TODO: LatestSizeEvent? -} - -// Window is a top-level, double-buffered GUI window. -type Window interface { - // Release closes the window. - // - // The behavior of the Window after Release, whether calling its methods or - // passing it as an argument, is undefined. - Release() - - EventDeque - - Uploader - - Drawer - - // Publish flushes any pending Upload and Draw calls to the window, and - // swaps the back buffer to the front. - Publish() PublishResult -} - -// PublishResult is the result of an Window.Publish call. -type PublishResult struct { - // BackBufferPreserved is whether the contents of the back buffer was - // preserved. If false, the contents are undefined. - BackBufferPreserved bool -} - -// NewWindowOptions are optional arguments to NewWindow. -type NewWindowOptions struct { - // Width and Height specify the dimensions of the new window. If Width - // or Height are zero, a driver-dependent default will be used for each - // zero value dimension. - Width, Height int - - // Title specifies the window title. - Title string - - // TODO: fullscreen, icon, cursorHidden? -} - -// GetTitle returns a sanitized form of o.Title. In particular, its length will -// not exceed 4096, and it may be further truncated so that it is valid UTF-8 -// and will not contain the NUL byte. -// -// o may be nil, in which case "" is returned. -func (o *NewWindowOptions) GetTitle() string { - if o == nil { - return "" - } - return sanitizeUTF8(o.Title, 4096) -} - -func sanitizeUTF8(s string, n int) string { - if n < len(s) { - s = s[:n] - } - i := 0 - for i < len(s) { - r, n := utf8.DecodeRuneInString(s[i:]) - if r == 0 || (r == utf8.RuneError && n == 1) { - break - } - i += n - } - return s[:i] -} - -// Uploader is something you can upload a Buffer to. -type Uploader interface { - // Upload uploads the sub-Buffer defined by src and sr to the destination - // (the method receiver), such that sr.Min in src-space aligns with dp in - // dst-space. The destination's contents are overwritten; the draw operator - // is implicitly draw.Src. - // - // It is valid to upload a Buffer while another upload of the same Buffer - // is in progress, but a Buffer's image.RGBA pixel contents should not be - // accessed while it is uploading. A Buffer is re-usable, in that its pixel - // contents can be further modified, once all outstanding calls to Upload - // have returned. - // - // TODO: make it optional that a Buffer's contents is preserved after - // Upload? Undoing a swizzle is a non-trivial amount of work, and can be - // redundant if the next paint cycle starts by clearing the buffer. - // - // When uploading to a Window, there will not be any visible effect until - // Publish is called. - Upload(dp image.Point, src Buffer, sr image.Rectangle) - - // Fill fills that part of the destination (the method receiver) defined by - // dr with the given color. - // - // When filling a Window, there will not be any visible effect until - // Publish is called. - Fill(dr image.Rectangle, src color.Color, op draw.Op) -} - -// TODO: have a Downloader interface? Not every graphical app needs to be -// interactive or involve a window. You could use the GPU for hardware- -// accelerated image manipulation: upload a buffer, do some texture ops, then -// download the result. - -// Drawer is something you can draw Textures on. -// -// Draw is the most general purpose of this interface's methods. It supports -// arbitrary affine transformations, such as translations, scales and -// rotations. -// -// Copy and Scale are more specific versions of Draw. The affected dst pixels -// are an axis-aligned rectangle, quantized to the pixel grid. Copy copies -// pixels in a 1:1 manner, Scale is more general. They have simpler parameters -// than Draw, using ints instead of float64s. -// -// When drawing on a Window, there will not be any visible effect until Publish -// is called. -type Drawer interface { - // Draw draws the sub-Texture defined by src and sr to the destination (the - // method receiver). src2dst defines how to transform src coordinates to - // dst coordinates. For example, if src2dst is the matrix - // - // m00 m01 m02 - // m10 m11 m12 - // - // then the src-space point (sx, sy) maps to the dst-space point - // (m00*sx + m01*sy + m02, m10*sx + m11*sy + m12). - Draw(src2dst f64.Aff3, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) - - // DrawUniform is like Draw except that the src is a uniform color instead - // of a Texture. - DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *DrawOptions) - - // Copy copies the sub-Texture defined by src and sr to the destination - // (the method receiver), such that sr.Min in src-space aligns with dp in - // dst-space. - Copy(dp image.Point, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) - - // Scale scales the sub-Texture defined by src and sr to the destination - // (the method receiver), such that sr in src-space is mapped to dr in - // dst-space. - Scale(dr image.Rectangle, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) -} - -// These draw.Op constants are provided so that users of this package don't -// have to explicitly import "image/draw". -const ( - Over = draw.Over - Src = draw.Src -) - -// DrawOptions are optional arguments to Draw. -type DrawOptions struct { - // TODO: transparency in [0x0000, 0xffff]? - // TODO: scaler (nearest neighbor vs linear)? -} diff --git a/vendor/golang.org/x/image/LICENSE b/vendor/golang.org/x/image/LICENSE deleted file mode 100644 index 6a66aea..0000000 --- a/vendor/golang.org/x/image/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/image/PATENTS b/vendor/golang.org/x/image/PATENTS deleted file mode 100644 index 7330990..0000000 --- a/vendor/golang.org/x/image/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/image/math/f64/f64.go b/vendor/golang.org/x/image/math/f64/f64.go deleted file mode 100644 index a1f7fc0..0000000 --- a/vendor/golang.org/x/image/math/f64/f64.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package f64 implements float64 vector and matrix types. -package f64 // import "golang.org/x/image/math/f64" - -// Vec2 is a 2-element vector. -type Vec2 [2]float64 - -// Vec3 is a 3-element vector. -type Vec3 [3]float64 - -// Vec4 is a 4-element vector. -type Vec4 [4]float64 - -// Mat3 is a 3x3 matrix in row major order. -// -// m[3*r + c] is the element in the r'th row and c'th column. -type Mat3 [9]float64 - -// Mat4 is a 4x4 matrix in row major order. -// -// m[4*r + c] is the element in the r'th row and c'th column. -type Mat4 [16]float64 - -// Aff3 is a 3x3 affine transformation matrix in row major order, where the -// bottom row is implicitly [0 0 1]. -// -// m[3*r + c] is the element in the r'th row and c'th column. -type Aff3 [6]float64 - -// Aff4 is a 4x4 affine transformation matrix in row major order, where the -// bottom row is implicitly [0 0 0 1]. -// -// m[4*r + c] is the element in the r'th row and c'th column. -type Aff4 [12]float64 diff --git a/vendor/golang.org/x/mobile/LICENSE b/vendor/golang.org/x/mobile/LICENSE deleted file mode 100644 index 6a66aea..0000000 --- a/vendor/golang.org/x/mobile/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/mobile/PATENTS b/vendor/golang.org/x/mobile/PATENTS deleted file mode 100644 index 7330990..0000000 --- a/vendor/golang.org/x/mobile/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/mobile/app/GoNativeActivity.java b/vendor/golang.org/x/mobile/app/GoNativeActivity.java deleted file mode 100644 index e829c8c..0000000 --- a/vendor/golang.org/x/mobile/app/GoNativeActivity.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.golang.app; - -import android.app.Activity; -import android.app.NativeActivity; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.util.Log; -import android.view.KeyCharacterMap; - -public class GoNativeActivity extends NativeActivity { - private static GoNativeActivity goNativeActivity; - - public GoNativeActivity() { - super(); - goNativeActivity = this; - } - - String getTmpdir() { - return getCacheDir().getAbsolutePath(); - } - - static int getRune(int deviceId, int keyCode, int metaState) { - try { - int rune = KeyCharacterMap.load(deviceId).get(keyCode, metaState); - if (rune == 0) { - return -1; - } - return rune; - } catch (KeyCharacterMap.UnavailableException e) { - return -1; - } catch (Exception e) { - Log.e("Go", "exception reading KeyCharacterMap", e); - return -1; - } - } - - private void load() { - // Interestingly, NativeActivity uses a different method - // to find native code to execute, avoiding - // System.loadLibrary. The result is Java methods - // implemented in C with JNIEXPORT (and JNI_OnLoad) are not - // available unless an explicit call to System.loadLibrary - // is done. So we do it here, borrowing the name of the - // library from the same AndroidManifest.xml metadata used - // by NativeActivity. - try { - ActivityInfo ai = getPackageManager().getActivityInfo( - getIntent().getComponent(), PackageManager.GET_META_DATA); - if (ai.metaData == null) { - Log.e("Go", "loadLibrary: no manifest metadata found"); - return; - } - String libName = ai.metaData.getString("android.app.lib_name"); - System.loadLibrary(libName); - } catch (Exception e) { - Log.e("Go", "loadLibrary failed", e); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - load(); - super.onCreate(savedInstanceState); - } -} diff --git a/vendor/golang.org/x/mobile/app/android.c b/vendor/golang.org/x/mobile/app/android.c deleted file mode 100644 index 305d586..0000000 --- a/vendor/golang.org/x/mobile/app/android.c +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build android -// +build android - -#include -#include -#include -#include -#include -#include -#include "_cgo_export.h" - -#define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "Go", __VA_ARGS__) -#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__) - -static jclass current_class; - -static jclass find_class(JNIEnv *env, const char *class_name) { - jclass clazz = (*env)->FindClass(env, class_name); - if (clazz == NULL) { - (*env)->ExceptionClear(env); - LOG_FATAL("cannot find %s", class_name); - return NULL; - } - return clazz; -} - -static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) { - jmethodID m = (*env)->GetMethodID(env, clazz, name, sig); - if (m == 0) { - (*env)->ExceptionClear(env); - LOG_FATAL("cannot find method %s %s", name, sig); - return 0; - } - return m; -} - -static jmethodID find_static_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) { - jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig); - if (m == 0) { - (*env)->ExceptionClear(env); - LOG_FATAL("cannot find method %s %s", name, sig); - return 0; - } - return m; -} - -static jmethodID key_rune_method; - -jint JNI_OnLoad(JavaVM* vm, void* reserved) { - JNIEnv* env; - if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { - return -1; - } - - return JNI_VERSION_1_6; -} - -static int main_running = 0; - -// Entry point from our subclassed NativeActivity. -// -// By here, the Go runtime has been initialized (as we are running in -// -buildmode=c-shared) but the first time it is called, Go's main.main -// hasn't been called yet. -// -// The Activity may be created and destroyed multiple times throughout -// the life of a single process. Each time, onCreate is called. -void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) { - if (!main_running) { - JNIEnv* env = activity->env; - - // Note that activity->clazz is mis-named. - current_class = (*env)->GetObjectClass(env, activity->clazz); - current_class = (*env)->NewGlobalRef(env, current_class); - key_rune_method = find_static_method(env, current_class, "getRune", "(III)I"); - - setCurrentContext(activity->vm, (*env)->NewGlobalRef(env, activity->clazz)); - - // Set TMPDIR. - jmethodID gettmpdir = find_method(env, current_class, "getTmpdir", "()Ljava/lang/String;"); - jstring jpath = (jstring)(*env)->CallObjectMethod(env, activity->clazz, gettmpdir, NULL); - const char* tmpdir = (*env)->GetStringUTFChars(env, jpath, NULL); - if (setenv("TMPDIR", tmpdir, 1) != 0) { - LOG_INFO("setenv(\"TMPDIR\", \"%s\", 1) failed: %d", tmpdir, errno); - } - (*env)->ReleaseStringUTFChars(env, jpath, tmpdir); - - // Call the Go main.main. - uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); - if (!mainPC) { - LOG_FATAL("missing main.main"); - } - callMain(mainPC); - main_running = 1; - } - - // These functions match the methods on Activity, described at - // http://developer.android.com/reference/android/app/Activity.html - // - // Note that onNativeWindowResized is not called on resize. Avoid it. - // https://code.google.com/p/android/issues/detail?id=180645 - activity->callbacks->onStart = onStart; - activity->callbacks->onResume = onResume; - activity->callbacks->onSaveInstanceState = onSaveInstanceState; - activity->callbacks->onPause = onPause; - activity->callbacks->onStop = onStop; - activity->callbacks->onDestroy = onDestroy; - activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; - activity->callbacks->onConfigurationChanged = onConfigurationChanged; - activity->callbacks->onLowMemory = onLowMemory; - - onCreate(activity); -} - -// TODO(crawshaw): Test configuration on more devices. -static const EGLint RGB_888[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_NONE -}; - -EGLDisplay display = NULL; -EGLSurface surface = NULL; - -static char* initEGLDisplay() { - display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (!eglInitialize(display, 0, 0)) { - return "EGL initialize failed"; - } - return NULL; -} - -char* createEGLSurface(ANativeWindow* window) { - char* err; - EGLint numConfigs, format; - EGLConfig config; - EGLContext context; - - if (display == 0) { - if ((err = initEGLDisplay()) != NULL) { - return err; - } - } - - if (!eglChooseConfig(display, RGB_888, &config, 1, &numConfigs)) { - return "EGL choose RGB_888 config failed"; - } - if (numConfigs <= 0) { - return "EGL no config found"; - } - - eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); - if (ANativeWindow_setBuffersGeometry(window, 0, 0, format) != 0) { - return "EGL set buffers geometry failed"; - } - - surface = eglCreateWindowSurface(display, config, window, NULL); - if (surface == EGL_NO_SURFACE) { - return "EGL create surface failed"; - } - - const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); - - if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { - return "eglMakeCurrent failed"; - } - return NULL; -} - -char* destroyEGLSurface() { - if (!eglDestroySurface(display, surface)) { - return "EGL destroy surface failed"; - } - return NULL; -} - -int32_t getKeyRune(JNIEnv* env, AInputEvent* e) { - return (int32_t)(*env)->CallStaticIntMethod( - env, - current_class, - key_rune_method, - AInputEvent_getDeviceId(e), - AKeyEvent_getKeyCode(e), - AKeyEvent_getMetaState(e) - ); -} diff --git a/vendor/golang.org/x/mobile/app/android.go b/vendor/golang.org/x/mobile/app/android.go deleted file mode 100644 index 08a6e05..0000000 --- a/vendor/golang.org/x/mobile/app/android.go +++ /dev/null @@ -1,825 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build android -// +build android - -/* -Android Apps are built with -buildmode=c-shared. They are loaded by a -running Java process. - -Before any entry point is reached, a global constructor initializes the -Go runtime, calling all Go init functions. All cgo calls will block -until this is complete. Next JNI_OnLoad is called. When that is -complete, one of two entry points is called. - -All-Go apps built using NativeActivity enter at ANativeActivity_onCreate. - -Go libraries (for example, those built with gomobile bind) do not use -the app package initialization. -*/ - -package app - -/* -#cgo LDFLAGS: -landroid -llog -lEGL -lGLESv2 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern EGLDisplay display; -extern EGLSurface surface; - - -char* createEGLSurface(ANativeWindow* window); -char* destroyEGLSurface(); -int32_t getKeyRune(JNIEnv* env, AInputEvent* e); -*/ -import "C" -import ( - "fmt" - "log" - "os" - "time" - "unsafe" - - "golang.org/x/mobile/app/internal/callfn" - "golang.org/x/mobile/event/key" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/event/touch" - "golang.org/x/mobile/geom" - "golang.org/x/mobile/internal/mobileinit" -) - -// RunOnJVM runs fn on a new goroutine locked to an OS thread with a JNIEnv. -// -// RunOnJVM blocks until the call to fn is complete. Any Java -// exception or failure to attach to the JVM is returned as an error. -// -// The function fn takes vm, the current JavaVM*, -// env, the current JNIEnv*, and -// ctx, a jobject representing the global android.context.Context. -func RunOnJVM(fn func(vm, jniEnv, ctx uintptr) error) error { - return mobileinit.RunOnJVM(fn) -} - -//export setCurrentContext -func setCurrentContext(vm *C.JavaVM, ctx C.jobject) { - mobileinit.SetCurrentContext(unsafe.Pointer(vm), uintptr(ctx)) -} - -//export callMain -func callMain(mainPC uintptr) { - for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} { - n := C.CString(name) - os.Setenv(name, C.GoString(C.getenv(n))) - C.free(unsafe.Pointer(n)) - } - - // Set timezone. - // - // Note that Android zoneinfo is stored in /system/usr/share/zoneinfo, - // but it is in some kind of packed TZiff file that we do not support - // yet. As a stopgap, we build a fixed zone using the tm_zone name. - var curtime C.time_t - var curtm C.struct_tm - C.time(&curtime) - C.localtime_r(&curtime, &curtm) - tzOffset := int(curtm.tm_gmtoff) - tz := C.GoString(curtm.tm_zone) - time.Local = time.FixedZone(tz, tzOffset) - - go callfn.CallFn(mainPC) -} - -//export onStart -func onStart(activity *C.ANativeActivity) { -} - -//export onResume -func onResume(activity *C.ANativeActivity) { -} - -//export onSaveInstanceState -func onSaveInstanceState(activity *C.ANativeActivity, outSize *C.size_t) unsafe.Pointer { - return nil -} - -//export onPause -func onPause(activity *C.ANativeActivity) { -} - -//export onStop -func onStop(activity *C.ANativeActivity) { -} - -//export onCreate -func onCreate(activity *C.ANativeActivity) { - // Set the initial configuration. - // - // Note we use unbuffered channels to talk to the activity loop, and - // NativeActivity calls these callbacks sequentially, so configuration - // will be set before <-windowRedrawNeeded is processed. - windowConfigChange <- windowConfigRead(activity) -} - -//export onDestroy -func onDestroy(activity *C.ANativeActivity) { -} - -//export onWindowFocusChanged -func onWindowFocusChanged(activity *C.ANativeActivity, hasFocus C.int) { -} - -//export onNativeWindowCreated -func onNativeWindowCreated(activity *C.ANativeActivity, window *C.ANativeWindow) { -} - -//export onNativeWindowRedrawNeeded -func onNativeWindowRedrawNeeded(activity *C.ANativeActivity, window *C.ANativeWindow) { - // Called on orientation change and window resize. - // Send a request for redraw, and block this function - // until a complete draw and buffer swap is completed. - // This is required by the redraw documentation to - // avoid bad draws. - windowRedrawNeeded <- window - <-windowRedrawDone -} - -//export onNativeWindowDestroyed -func onNativeWindowDestroyed(activity *C.ANativeActivity, window *C.ANativeWindow) { - windowDestroyed <- window -} - -//export onInputQueueCreated -func onInputQueueCreated(activity *C.ANativeActivity, q *C.AInputQueue) { - inputQueue <- q - <-inputQueueDone -} - -//export onInputQueueDestroyed -func onInputQueueDestroyed(activity *C.ANativeActivity, q *C.AInputQueue) { - inputQueue <- nil - <-inputQueueDone -} - -//export onContentRectChanged -func onContentRectChanged(activity *C.ANativeActivity, rect *C.ARect) { -} - -type windowConfig struct { - orientation size.Orientation - pixelsPerPt float32 -} - -func windowConfigRead(activity *C.ANativeActivity) windowConfig { - aconfig := C.AConfiguration_new() - C.AConfiguration_fromAssetManager(aconfig, activity.assetManager) - orient := C.AConfiguration_getOrientation(aconfig) - density := C.AConfiguration_getDensity(aconfig) - C.AConfiguration_delete(aconfig) - - // Calculate the screen resolution. This value is approximate. For example, - // a physical resolution of 200 DPI may be quantized to one of the - // ACONFIGURATION_DENSITY_XXX values such as 160 or 240. - // - // A more accurate DPI could possibly be calculated from - // https://developer.android.com/reference/android/util/DisplayMetrics.html#xdpi - // but this does not appear to be accessible via the NDK. In any case, the - // hardware might not even provide a more accurate number, as the system - // does not apparently use the reported value. See golang.org/issue/13366 - // for a discussion. - var dpi int - switch density { - case C.ACONFIGURATION_DENSITY_DEFAULT: - dpi = 160 - case C.ACONFIGURATION_DENSITY_LOW, - C.ACONFIGURATION_DENSITY_MEDIUM, - 213, // C.ACONFIGURATION_DENSITY_TV - C.ACONFIGURATION_DENSITY_HIGH, - 320, // ACONFIGURATION_DENSITY_XHIGH - 480, // ACONFIGURATION_DENSITY_XXHIGH - 640: // ACONFIGURATION_DENSITY_XXXHIGH - dpi = int(density) - case C.ACONFIGURATION_DENSITY_NONE: - log.Print("android device reports no screen density") - dpi = 72 - default: - log.Printf("android device reports unknown density: %d", density) - // All we can do is guess. - if density > 0 { - dpi = int(density) - } else { - dpi = 72 - } - } - - o := size.OrientationUnknown - switch orient { - case C.ACONFIGURATION_ORIENTATION_PORT: - o = size.OrientationPortrait - case C.ACONFIGURATION_ORIENTATION_LAND: - o = size.OrientationLandscape - } - - return windowConfig{ - orientation: o, - pixelsPerPt: float32(dpi) / 72, - } -} - -//export onConfigurationChanged -func onConfigurationChanged(activity *C.ANativeActivity) { - // A rotation event first triggers onConfigurationChanged, then - // calls onNativeWindowRedrawNeeded. We extract the orientation - // here and save it for the redraw event. - windowConfigChange <- windowConfigRead(activity) -} - -//export onLowMemory -func onLowMemory(activity *C.ANativeActivity) { -} - -var ( - inputQueue = make(chan *C.AInputQueue) - inputQueueDone = make(chan struct{}) - windowDestroyed = make(chan *C.ANativeWindow) - windowRedrawNeeded = make(chan *C.ANativeWindow) - windowRedrawDone = make(chan struct{}) - windowConfigChange = make(chan windowConfig) -) - -func init() { - theApp.registerGLViewportFilter() -} - -func main(f func(App)) { - mainUserFn = f - // TODO: merge the runInputQueue and mainUI functions? - go func() { - if err := mobileinit.RunOnJVM(runInputQueue); err != nil { - log.Fatalf("app: %v", err) - } - }() - // Preserve this OS thread for: - // 1. the attached JNI thread - // 2. the GL context - if err := mobileinit.RunOnJVM(mainUI); err != nil { - log.Fatalf("app: %v", err) - } -} - -var mainUserFn func(App) - -func mainUI(vm, jniEnv, ctx uintptr) error { - workAvailable := theApp.worker.WorkAvailable() - - donec := make(chan struct{}) - go func() { - // close the donec channel in a defer statement - // so that we could still be able to return even - // if mainUserFn panics. - defer close(donec) - - mainUserFn(theApp) - }() - - var pixelsPerPt float32 - var orientation size.Orientation - - for { - select { - case <-donec: - return nil - case cfg := <-windowConfigChange: - pixelsPerPt = cfg.pixelsPerPt - orientation = cfg.orientation - case w := <-windowRedrawNeeded: - if C.surface == nil { - if errStr := C.createEGLSurface(w); errStr != nil { - return fmt.Errorf("%s (%s)", C.GoString(errStr), eglGetError()) - } - } - theApp.sendLifecycle(lifecycle.StageFocused) - widthPx := int(C.ANativeWindow_getWidth(w)) - heightPx := int(C.ANativeWindow_getHeight(w)) - theApp.eventsIn <- size.Event{ - WidthPx: widthPx, - HeightPx: heightPx, - WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), - HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), - PixelsPerPt: pixelsPerPt, - Orientation: orientation, - } - theApp.eventsIn <- paint.Event{External: true} - case <-windowDestroyed: - if C.surface != nil { - if errStr := C.destroyEGLSurface(); errStr != nil { - return fmt.Errorf("%s (%s)", C.GoString(errStr), eglGetError()) - } - } - C.surface = nil - theApp.sendLifecycle(lifecycle.StageAlive) - case <-workAvailable: - theApp.worker.DoWork() - case <-theApp.publish: - // TODO: compare a generation number to redrawGen for stale paints? - if C.surface != nil { - // eglSwapBuffers blocks until vsync. - if C.eglSwapBuffers(C.display, C.surface) == C.EGL_FALSE { - log.Printf("app: failed to swap buffers (%s)", eglGetError()) - } - } - select { - case windowRedrawDone <- struct{}{}: - default: - } - theApp.publishResult <- PublishResult{} - } - } -} - -func runInputQueue(vm, jniEnv, ctx uintptr) error { - env := (*C.JNIEnv)(unsafe.Pointer(jniEnv)) // not a Go heap pointer - - // Android loopers select on OS file descriptors, not Go channels, so we - // translate the inputQueue channel to an ALooper_wake call. - l := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS) - pending := make(chan *C.AInputQueue, 1) - go func() { - for q := range inputQueue { - pending <- q - C.ALooper_wake(l) - } - }() - - var q *C.AInputQueue - for { - if C.ALooper_pollAll(-1, nil, nil, nil) == C.ALOOPER_POLL_WAKE { - select { - default: - case p := <-pending: - if q != nil { - processEvents(env, q) - C.AInputQueue_detachLooper(q) - } - q = p - if q != nil { - C.AInputQueue_attachLooper(q, l, 0, nil, nil) - } - inputQueueDone <- struct{}{} - } - } - if q != nil { - processEvents(env, q) - } - } -} - -func processEvents(env *C.JNIEnv, q *C.AInputQueue) { - var e *C.AInputEvent - for C.AInputQueue_getEvent(q, &e) >= 0 { - if C.AInputQueue_preDispatchEvent(q, e) != 0 { - continue - } - processEvent(env, e) - C.AInputQueue_finishEvent(q, e, 0) - } -} - -func processEvent(env *C.JNIEnv, e *C.AInputEvent) { - switch C.AInputEvent_getType(e) { - case C.AINPUT_EVENT_TYPE_KEY: - processKey(env, e) - case C.AINPUT_EVENT_TYPE_MOTION: - // At most one of the events in this batch is an up or down event; get its index and change. - upDownIndex := C.size_t(C.AMotionEvent_getAction(e)&C.AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> C.AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT - upDownType := touch.TypeMove - switch C.AMotionEvent_getAction(e) & C.AMOTION_EVENT_ACTION_MASK { - case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN: - upDownType = touch.TypeBegin - case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP: - upDownType = touch.TypeEnd - } - - for i, n := C.size_t(0), C.AMotionEvent_getPointerCount(e); i < n; i++ { - t := touch.TypeMove - if i == upDownIndex { - t = upDownType - } - theApp.eventsIn <- touch.Event{ - X: float32(C.AMotionEvent_getX(e, i)), - Y: float32(C.AMotionEvent_getY(e, i)), - Sequence: touch.Sequence(C.AMotionEvent_getPointerId(e, i)), - Type: t, - } - } - default: - log.Printf("unknown input event, type=%d", C.AInputEvent_getType(e)) - } -} - -func processKey(env *C.JNIEnv, e *C.AInputEvent) { - deviceID := C.AInputEvent_getDeviceId(e) - if deviceID == 0 { - // Software keyboard input, leaving for scribe/IME. - return - } - - k := key.Event{ - Rune: rune(C.getKeyRune(env, e)), - Code: convAndroidKeyCode(int32(C.AKeyEvent_getKeyCode(e))), - } - switch C.AKeyEvent_getAction(e) { - case C.AKEY_EVENT_ACTION_DOWN: - k.Direction = key.DirPress - case C.AKEY_EVENT_ACTION_UP: - k.Direction = key.DirRelease - default: - k.Direction = key.DirNone - } - // TODO(crawshaw): set Modifiers. - theApp.eventsIn <- k -} - -func eglGetError() string { - switch errNum := C.eglGetError(); errNum { - case C.EGL_SUCCESS: - return "EGL_SUCCESS" - case C.EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED" - case C.EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS" - case C.EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC" - case C.EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE" - case C.EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT" - case C.EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG" - case C.EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE" - case C.EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY" - case C.EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE" - case C.EGL_BAD_MATCH: - return "EGL_BAD_MATCH" - case C.EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER" - case C.EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP" - case C.EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW" - case C.EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST" - default: - return fmt.Sprintf("Unknown EGL err: %d", errNum) - } -} - -func convAndroidKeyCode(aKeyCode int32) key.Code { - // Many Android key codes do not map into USB HID codes. - // For those, key.CodeUnknown is returned. This switch has all - // cases, even the unknown ones, to serve as a documentation - // and search aid. - switch aKeyCode { - case C.AKEYCODE_UNKNOWN: - case C.AKEYCODE_SOFT_LEFT: - case C.AKEYCODE_SOFT_RIGHT: - case C.AKEYCODE_HOME: - return key.CodeHome - case C.AKEYCODE_BACK: - case C.AKEYCODE_CALL: - case C.AKEYCODE_ENDCALL: - case C.AKEYCODE_0: - return key.Code0 - case C.AKEYCODE_1: - return key.Code1 - case C.AKEYCODE_2: - return key.Code2 - case C.AKEYCODE_3: - return key.Code3 - case C.AKEYCODE_4: - return key.Code4 - case C.AKEYCODE_5: - return key.Code5 - case C.AKEYCODE_6: - return key.Code6 - case C.AKEYCODE_7: - return key.Code7 - case C.AKEYCODE_8: - return key.Code8 - case C.AKEYCODE_9: - return key.Code9 - case C.AKEYCODE_STAR: - case C.AKEYCODE_POUND: - case C.AKEYCODE_DPAD_UP: - case C.AKEYCODE_DPAD_DOWN: - case C.AKEYCODE_DPAD_LEFT: - case C.AKEYCODE_DPAD_RIGHT: - case C.AKEYCODE_DPAD_CENTER: - case C.AKEYCODE_VOLUME_UP: - return key.CodeVolumeUp - case C.AKEYCODE_VOLUME_DOWN: - return key.CodeVolumeDown - case C.AKEYCODE_POWER: - case C.AKEYCODE_CAMERA: - case C.AKEYCODE_CLEAR: - case C.AKEYCODE_A: - return key.CodeA - case C.AKEYCODE_B: - return key.CodeB - case C.AKEYCODE_C: - return key.CodeC - case C.AKEYCODE_D: - return key.CodeD - case C.AKEYCODE_E: - return key.CodeE - case C.AKEYCODE_F: - return key.CodeF - case C.AKEYCODE_G: - return key.CodeG - case C.AKEYCODE_H: - return key.CodeH - case C.AKEYCODE_I: - return key.CodeI - case C.AKEYCODE_J: - return key.CodeJ - case C.AKEYCODE_K: - return key.CodeK - case C.AKEYCODE_L: - return key.CodeL - case C.AKEYCODE_M: - return key.CodeM - case C.AKEYCODE_N: - return key.CodeN - case C.AKEYCODE_O: - return key.CodeO - case C.AKEYCODE_P: - return key.CodeP - case C.AKEYCODE_Q: - return key.CodeQ - case C.AKEYCODE_R: - return key.CodeR - case C.AKEYCODE_S: - return key.CodeS - case C.AKEYCODE_T: - return key.CodeT - case C.AKEYCODE_U: - return key.CodeU - case C.AKEYCODE_V: - return key.CodeV - case C.AKEYCODE_W: - return key.CodeW - case C.AKEYCODE_X: - return key.CodeX - case C.AKEYCODE_Y: - return key.CodeY - case C.AKEYCODE_Z: - return key.CodeZ - case C.AKEYCODE_COMMA: - return key.CodeComma - case C.AKEYCODE_PERIOD: - return key.CodeFullStop - case C.AKEYCODE_ALT_LEFT: - return key.CodeLeftAlt - case C.AKEYCODE_ALT_RIGHT: - return key.CodeRightAlt - case C.AKEYCODE_SHIFT_LEFT: - return key.CodeLeftShift - case C.AKEYCODE_SHIFT_RIGHT: - return key.CodeRightShift - case C.AKEYCODE_TAB: - return key.CodeTab - case C.AKEYCODE_SPACE: - return key.CodeSpacebar - case C.AKEYCODE_SYM: - case C.AKEYCODE_EXPLORER: - case C.AKEYCODE_ENVELOPE: - case C.AKEYCODE_ENTER: - return key.CodeReturnEnter - case C.AKEYCODE_DEL: - return key.CodeDeleteBackspace - case C.AKEYCODE_GRAVE: - return key.CodeGraveAccent - case C.AKEYCODE_MINUS: - return key.CodeHyphenMinus - case C.AKEYCODE_EQUALS: - return key.CodeEqualSign - case C.AKEYCODE_LEFT_BRACKET: - return key.CodeLeftSquareBracket - case C.AKEYCODE_RIGHT_BRACKET: - return key.CodeRightSquareBracket - case C.AKEYCODE_BACKSLASH: - return key.CodeBackslash - case C.AKEYCODE_SEMICOLON: - return key.CodeSemicolon - case C.AKEYCODE_APOSTROPHE: - return key.CodeApostrophe - case C.AKEYCODE_SLASH: - return key.CodeSlash - case C.AKEYCODE_AT: - case C.AKEYCODE_NUM: - case C.AKEYCODE_HEADSETHOOK: - case C.AKEYCODE_FOCUS: - case C.AKEYCODE_PLUS: - case C.AKEYCODE_MENU: - case C.AKEYCODE_NOTIFICATION: - case C.AKEYCODE_SEARCH: - case C.AKEYCODE_MEDIA_PLAY_PAUSE: - case C.AKEYCODE_MEDIA_STOP: - case C.AKEYCODE_MEDIA_NEXT: - case C.AKEYCODE_MEDIA_PREVIOUS: - case C.AKEYCODE_MEDIA_REWIND: - case C.AKEYCODE_MEDIA_FAST_FORWARD: - case C.AKEYCODE_MUTE: - case C.AKEYCODE_PAGE_UP: - return key.CodePageUp - case C.AKEYCODE_PAGE_DOWN: - return key.CodePageDown - case C.AKEYCODE_PICTSYMBOLS: - case C.AKEYCODE_SWITCH_CHARSET: - case C.AKEYCODE_BUTTON_A: - case C.AKEYCODE_BUTTON_B: - case C.AKEYCODE_BUTTON_C: - case C.AKEYCODE_BUTTON_X: - case C.AKEYCODE_BUTTON_Y: - case C.AKEYCODE_BUTTON_Z: - case C.AKEYCODE_BUTTON_L1: - case C.AKEYCODE_BUTTON_R1: - case C.AKEYCODE_BUTTON_L2: - case C.AKEYCODE_BUTTON_R2: - case C.AKEYCODE_BUTTON_THUMBL: - case C.AKEYCODE_BUTTON_THUMBR: - case C.AKEYCODE_BUTTON_START: - case C.AKEYCODE_BUTTON_SELECT: - case C.AKEYCODE_BUTTON_MODE: - case C.AKEYCODE_ESCAPE: - return key.CodeEscape - case C.AKEYCODE_FORWARD_DEL: - return key.CodeDeleteForward - case C.AKEYCODE_CTRL_LEFT: - return key.CodeLeftControl - case C.AKEYCODE_CTRL_RIGHT: - return key.CodeRightControl - case C.AKEYCODE_CAPS_LOCK: - return key.CodeCapsLock - case C.AKEYCODE_SCROLL_LOCK: - case C.AKEYCODE_META_LEFT: - return key.CodeLeftGUI - case C.AKEYCODE_META_RIGHT: - return key.CodeRightGUI - case C.AKEYCODE_FUNCTION: - case C.AKEYCODE_SYSRQ: - case C.AKEYCODE_BREAK: - case C.AKEYCODE_MOVE_HOME: - case C.AKEYCODE_MOVE_END: - case C.AKEYCODE_INSERT: - return key.CodeInsert - case C.AKEYCODE_FORWARD: - case C.AKEYCODE_MEDIA_PLAY: - case C.AKEYCODE_MEDIA_PAUSE: - case C.AKEYCODE_MEDIA_CLOSE: - case C.AKEYCODE_MEDIA_EJECT: - case C.AKEYCODE_MEDIA_RECORD: - case C.AKEYCODE_F1: - return key.CodeF1 - case C.AKEYCODE_F2: - return key.CodeF2 - case C.AKEYCODE_F3: - return key.CodeF3 - case C.AKEYCODE_F4: - return key.CodeF4 - case C.AKEYCODE_F5: - return key.CodeF5 - case C.AKEYCODE_F6: - return key.CodeF6 - case C.AKEYCODE_F7: - return key.CodeF7 - case C.AKEYCODE_F8: - return key.CodeF8 - case C.AKEYCODE_F9: - return key.CodeF9 - case C.AKEYCODE_F10: - return key.CodeF10 - case C.AKEYCODE_F11: - return key.CodeF11 - case C.AKEYCODE_F12: - return key.CodeF12 - case C.AKEYCODE_NUM_LOCK: - return key.CodeKeypadNumLock - case C.AKEYCODE_NUMPAD_0: - return key.CodeKeypad0 - case C.AKEYCODE_NUMPAD_1: - return key.CodeKeypad1 - case C.AKEYCODE_NUMPAD_2: - return key.CodeKeypad2 - case C.AKEYCODE_NUMPAD_3: - return key.CodeKeypad3 - case C.AKEYCODE_NUMPAD_4: - return key.CodeKeypad4 - case C.AKEYCODE_NUMPAD_5: - return key.CodeKeypad5 - case C.AKEYCODE_NUMPAD_6: - return key.CodeKeypad6 - case C.AKEYCODE_NUMPAD_7: - return key.CodeKeypad7 - case C.AKEYCODE_NUMPAD_8: - return key.CodeKeypad8 - case C.AKEYCODE_NUMPAD_9: - return key.CodeKeypad9 - case C.AKEYCODE_NUMPAD_DIVIDE: - return key.CodeKeypadSlash - case C.AKEYCODE_NUMPAD_MULTIPLY: - return key.CodeKeypadAsterisk - case C.AKEYCODE_NUMPAD_SUBTRACT: - return key.CodeKeypadHyphenMinus - case C.AKEYCODE_NUMPAD_ADD: - return key.CodeKeypadPlusSign - case C.AKEYCODE_NUMPAD_DOT: - return key.CodeKeypadFullStop - case C.AKEYCODE_NUMPAD_COMMA: - case C.AKEYCODE_NUMPAD_ENTER: - return key.CodeKeypadEnter - case C.AKEYCODE_NUMPAD_EQUALS: - return key.CodeKeypadEqualSign - case C.AKEYCODE_NUMPAD_LEFT_PAREN: - case C.AKEYCODE_NUMPAD_RIGHT_PAREN: - case C.AKEYCODE_VOLUME_MUTE: - return key.CodeMute - case C.AKEYCODE_INFO: - case C.AKEYCODE_CHANNEL_UP: - case C.AKEYCODE_CHANNEL_DOWN: - case C.AKEYCODE_ZOOM_IN: - case C.AKEYCODE_ZOOM_OUT: - case C.AKEYCODE_TV: - case C.AKEYCODE_WINDOW: - case C.AKEYCODE_GUIDE: - case C.AKEYCODE_DVR: - case C.AKEYCODE_BOOKMARK: - case C.AKEYCODE_CAPTIONS: - case C.AKEYCODE_SETTINGS: - case C.AKEYCODE_TV_POWER: - case C.AKEYCODE_TV_INPUT: - case C.AKEYCODE_STB_POWER: - case C.AKEYCODE_STB_INPUT: - case C.AKEYCODE_AVR_POWER: - case C.AKEYCODE_AVR_INPUT: - case C.AKEYCODE_PROG_RED: - case C.AKEYCODE_PROG_GREEN: - case C.AKEYCODE_PROG_YELLOW: - case C.AKEYCODE_PROG_BLUE: - case C.AKEYCODE_APP_SWITCH: - case C.AKEYCODE_BUTTON_1: - case C.AKEYCODE_BUTTON_2: - case C.AKEYCODE_BUTTON_3: - case C.AKEYCODE_BUTTON_4: - case C.AKEYCODE_BUTTON_5: - case C.AKEYCODE_BUTTON_6: - case C.AKEYCODE_BUTTON_7: - case C.AKEYCODE_BUTTON_8: - case C.AKEYCODE_BUTTON_9: - case C.AKEYCODE_BUTTON_10: - case C.AKEYCODE_BUTTON_11: - case C.AKEYCODE_BUTTON_12: - case C.AKEYCODE_BUTTON_13: - case C.AKEYCODE_BUTTON_14: - case C.AKEYCODE_BUTTON_15: - case C.AKEYCODE_BUTTON_16: - case C.AKEYCODE_LANGUAGE_SWITCH: - case C.AKEYCODE_MANNER_MODE: - case C.AKEYCODE_3D_MODE: - case C.AKEYCODE_CONTACTS: - case C.AKEYCODE_CALENDAR: - case C.AKEYCODE_MUSIC: - case C.AKEYCODE_CALCULATOR: - } - /* Defined in an NDK API version beyond what we use today: - C.AKEYCODE_ASSIST - C.AKEYCODE_BRIGHTNESS_DOWN - C.AKEYCODE_BRIGHTNESS_UP - C.AKEYCODE_EISU - C.AKEYCODE_HENKAN - C.AKEYCODE_KANA - C.AKEYCODE_KATAKANA_HIRAGANA - C.AKEYCODE_MEDIA_AUDIO_TRACK - C.AKEYCODE_MUHENKAN - C.AKEYCODE_RO - C.AKEYCODE_YEN - C.AKEYCODE_ZENKAKU_HANKAKU - */ - return key.CodeUnknown -} diff --git a/vendor/golang.org/x/mobile/app/app.go b/vendor/golang.org/x/mobile/app/app.go deleted file mode 100644 index 19efb07..0000000 --- a/vendor/golang.org/x/mobile/app/app.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux || darwin || windows -// +build linux darwin windows - -package app - -import ( - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/gl" - _ "golang.org/x/mobile/internal/mobileinit" -) - -// Main is called by the main.main function to run the mobile application. -// -// It calls f on the App, in a separate goroutine, as some OS-specific -// libraries require being on 'the main thread'. -func Main(f func(App)) { - main(f) -} - -// App is how a GUI mobile application interacts with the OS. -type App interface { - // Events returns the events channel. It carries events from the system to - // the app. The type of such events include: - // - lifecycle.Event - // - mouse.Event - // - paint.Event - // - size.Event - // - touch.Event - // from the golang.org/x/mobile/event/etc packages. Other packages may - // define other event types that are carried on this channel. - Events() <-chan interface{} - - // Send sends an event on the events channel. It does not block. - Send(event interface{}) - - // Publish flushes any pending drawing commands, such as OpenGL calls, and - // swaps the back buffer to the screen. - Publish() PublishResult - - // TODO: replace filters (and the Events channel) with a NextEvent method? - - // Filter calls each registered event filter function in sequence. - Filter(event interface{}) interface{} - - // RegisterFilter registers a event filter function to be called by Filter. The - // function can return a different event, or return nil to consume the event, - // but the function can also return its argument unchanged, where its purpose - // is to trigger a side effect rather than modify the event. - RegisterFilter(f func(interface{}) interface{}) -} - -// PublishResult is the result of an App.Publish call. -type PublishResult struct { - // BackBufferPreserved is whether the contents of the back buffer was - // preserved. If false, the contents are undefined. - BackBufferPreserved bool -} - -var theApp = &app{ - eventsOut: make(chan interface{}), - lifecycleStage: lifecycle.StageDead, - publish: make(chan struct{}), - publishResult: make(chan PublishResult), -} - -func init() { - theApp.eventsIn = pump(theApp.eventsOut) - theApp.glctx, theApp.worker = gl.NewContext() -} - -func (a *app) sendLifecycle(to lifecycle.Stage) { - if a.lifecycleStage == to { - return - } - a.eventsIn <- lifecycle.Event{ - From: a.lifecycleStage, - To: to, - DrawContext: a.glctx, - } - a.lifecycleStage = to -} - -type app struct { - filters []func(interface{}) interface{} - - eventsOut chan interface{} - eventsIn chan interface{} - lifecycleStage lifecycle.Stage - publish chan struct{} - publishResult chan PublishResult - - glctx gl.Context - worker gl.Worker -} - -func (a *app) Events() <-chan interface{} { - return a.eventsOut -} - -func (a *app) Send(event interface{}) { - a.eventsIn <- event -} - -func (a *app) Publish() PublishResult { - // gl.Flush is a lightweight (on modern GL drivers) blocking call - // that ensures all GL functions pending in the gl package have - // been passed onto the GL driver before the app package attempts - // to swap the screen buffer. - // - // This enforces that the final receive (for this paint cycle) on - // gl.WorkAvailable happens before the send on endPaint. - a.glctx.Flush() - a.publish <- struct{}{} - return <-a.publishResult -} - -func (a *app) Filter(event interface{}) interface{} { - for _, f := range a.filters { - event = f(event) - } - return event -} - -func (a *app) RegisterFilter(f func(interface{}) interface{}) { - a.filters = append(a.filters, f) -} - -type stopPumping struct{} - -// pump returns a channel src such that sending on src will eventually send on -// dst, in order, but that src will always be ready to send/receive soon, even -// if dst currently isn't. It is effectively an infinitely buffered channel. -// -// In particular, goroutine A sending on src will not deadlock even if goroutine -// B that's responsible for receiving on dst is currently blocked trying to -// send to A on a separate channel. -// -// Send a stopPumping on the src channel to close the dst channel after all queued -// events are sent on dst. After that, other goroutines can still send to src, -// so that such sends won't block forever, but such events will be ignored. -func pump(dst chan interface{}) (src chan interface{}) { - src = make(chan interface{}) - go func() { - // initialSize is the initial size of the circular buffer. It must be a - // power of 2. - const initialSize = 16 - i, j, buf, mask := 0, 0, make([]interface{}, initialSize), initialSize-1 - - srcActive := true - for { - maybeDst := dst - if i == j { - maybeDst = nil - } - if maybeDst == nil && !srcActive { - // Pump is stopped and empty. - break - } - - select { - case maybeDst <- buf[i&mask]: - buf[i&mask] = nil - i++ - - case e := <-src: - if _, ok := e.(stopPumping); ok { - srcActive = false - continue - } - - if !srcActive { - continue - } - - // Allocate a bigger buffer if necessary. - if i+len(buf) == j { - b := make([]interface{}, 2*len(buf)) - n := copy(b, buf[j&mask:]) - copy(b[n:], buf[:j&mask]) - i, j = 0, len(buf) - buf, mask = b, len(b)-1 - } - - buf[j&mask] = e - j++ - } - } - - close(dst) - // Block forever. - for range src { - } - }() - return src -} - -// TODO: do this for all build targets, not just linux (x11 and Android)? If -// so, should package gl instead of this package call RegisterFilter?? -// -// TODO: does Android need this?? It seems to work without it (Nexus 7, -// KitKat). If only x11 needs this, should we move this to x11.go?? -func (a *app) registerGLViewportFilter() { - a.RegisterFilter(func(e interface{}) interface{} { - if e, ok := e.(size.Event); ok { - a.glctx.Viewport(0, 0, e.WidthPx, e.HeightPx) - } - return e - }) -} diff --git a/vendor/golang.org/x/mobile/app/darwin_desktop.go b/vendor/golang.org/x/mobile/app/darwin_desktop.go deleted file mode 100644 index 3377175..0000000 --- a/vendor/golang.org/x/mobile/app/darwin_desktop.go +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && !ios -// +build darwin,!ios - -package app - -// Simple on-screen app debugging for OS X. Not an officially supported -// development target for apps, as screens with mice are very different -// than screens with touch panels. - -/* -#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION -#cgo LDFLAGS: -framework Cocoa -framework OpenGL -#import // for HIToolbox/Events.h -#import -#include - -void runApp(void); -void stopApp(void); -void makeCurrentContext(GLintptr); -uint64 threadID(); -*/ -import "C" -import ( - "log" - "runtime" - "sync" - - "golang.org/x/mobile/event/key" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/event/touch" - "golang.org/x/mobile/geom" -) - -var initThreadID uint64 - -func init() { - // Lock the goroutine responsible for initialization to an OS thread. - // This means the goroutine running main (and calling runApp below) - // is locked to the OS thread that started the program. This is - // necessary for the correct delivery of Cocoa events to the process. - // - // A discussion on this topic: - // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ - runtime.LockOSThread() - initThreadID = uint64(C.threadID()) -} - -func main(f func(App)) { - if tid := uint64(C.threadID()); tid != initThreadID { - log.Fatalf("app.Main called on thread %d, but app.init ran on %d", tid, initThreadID) - } - - go func() { - f(theApp) - C.stopApp() - }() - - C.runApp() -} - -// loop is the primary drawing loop. -// -// After Cocoa has captured the initial OS thread for processing Cocoa -// events in runApp, it starts loop on another goroutine. It is locked -// to an OS thread for its OpenGL context. -// -// The loop processes GL calls until a publish event appears. -// Then it runs any remaining GL calls and flushes the screen. -// -// As NSOpenGLCPSwapInterval is set to 1, the call to CGLFlushDrawable -// blocks until the screen refresh. -func (a *app) loop(ctx C.GLintptr) { - runtime.LockOSThread() - C.makeCurrentContext(ctx) - - workAvailable := a.worker.WorkAvailable() - - for { - select { - case <-workAvailable: - a.worker.DoWork() - case <-theApp.publish: - loop1: - for { - select { - case <-workAvailable: - a.worker.DoWork() - default: - break loop1 - } - } - C.CGLFlushDrawable(C.CGLGetCurrentContext()) - theApp.publishResult <- PublishResult{} - select { - case drawDone <- struct{}{}: - default: - } - } - } -} - -var drawDone = make(chan struct{}) - -// drawgl is used by Cocoa to occasionally request screen updates. -// -//export drawgl -func drawgl() { - switch theApp.lifecycleStage { - case lifecycle.StageFocused, lifecycle.StageVisible: - theApp.Send(paint.Event{ - External: true, - }) - <-drawDone - } -} - -//export startloop -func startloop(ctx C.GLintptr) { - go theApp.loop(ctx) -} - -var windowHeightPx float32 - -//export setGeom -func setGeom(pixelsPerPt float32, widthPx, heightPx int) { - windowHeightPx = float32(heightPx) - theApp.eventsIn <- size.Event{ - WidthPx: widthPx, - HeightPx: heightPx, - WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), - HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), - PixelsPerPt: pixelsPerPt, - } -} - -var touchEvents struct { - sync.Mutex - pending []touch.Event -} - -func sendTouch(t touch.Type, x, y float32) { - theApp.eventsIn <- touch.Event{ - X: x, - Y: windowHeightPx - y, - Sequence: 0, - Type: t, - } -} - -//export eventMouseDown -func eventMouseDown(x, y float32) { sendTouch(touch.TypeBegin, x, y) } - -//export eventMouseDragged -func eventMouseDragged(x, y float32) { sendTouch(touch.TypeMove, x, y) } - -//export eventMouseEnd -func eventMouseEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) } - -//export lifecycleDead -func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) } - -//export eventKey -func eventKey(runeVal int32, direction uint8, code uint16, flags uint32) { - var modifiers key.Modifiers - for _, mod := range mods { - if flags&mod.flags == mod.flags { - modifiers |= mod.mod - } - } - - theApp.eventsIn <- key.Event{ - Rune: convRune(rune(runeVal)), - Code: convVirtualKeyCode(code), - Modifiers: modifiers, - Direction: key.Direction(direction), - } -} - -//export eventFlags -func eventFlags(flags uint32) { - for _, mod := range mods { - if flags&mod.flags == mod.flags && lastFlags&mod.flags != mod.flags { - eventKey(-1, uint8(key.DirPress), mod.code, flags) - } - if lastFlags&mod.flags == mod.flags && flags&mod.flags != mod.flags { - eventKey(-1, uint8(key.DirRelease), mod.code, flags) - } - } - lastFlags = flags -} - -var lastFlags uint32 - -var mods = [...]struct { - flags uint32 - code uint16 - mod key.Modifiers -}{ - // Left and right variants of modifier keys have their own masks, - // but they are not documented. These were determined empirically. - {1<<17 | 0x102, C.kVK_Shift, key.ModShift}, - {1<<17 | 0x104, C.kVK_RightShift, key.ModShift}, - {1<<18 | 0x101, C.kVK_Control, key.ModControl}, - // TODO key.ControlRight - {1<<19 | 0x120, C.kVK_Option, key.ModAlt}, - {1<<19 | 0x140, C.kVK_RightOption, key.ModAlt}, - {1<<20 | 0x108, C.kVK_Command, key.ModMeta}, - {1<<20 | 0x110, C.kVK_Command, key.ModMeta}, // TODO: missing kVK_RightCommand -} - -//export lifecycleAlive -func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) } - -//export lifecycleVisible -func lifecycleVisible() { - theApp.sendLifecycle(lifecycle.StageVisible) -} - -//export lifecycleFocused -func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) } - -// convRune marks the Carbon/Cocoa private-range unicode rune representing -// a non-unicode key event to -1, used for Rune in the key package. -// -// http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT -func convRune(r rune) rune { - if '\uE000' <= r && r <= '\uF8FF' { - return -1 - } - return r -} - -// convVirtualKeyCode converts a Carbon/Cocoa virtual key code number -// into the standard keycodes used by the key package. -// -// To get a sense of the key map, see the diagram on -// -// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes -func convVirtualKeyCode(vkcode uint16) key.Code { - switch vkcode { - case C.kVK_ANSI_A: - return key.CodeA - case C.kVK_ANSI_B: - return key.CodeB - case C.kVK_ANSI_C: - return key.CodeC - case C.kVK_ANSI_D: - return key.CodeD - case C.kVK_ANSI_E: - return key.CodeE - case C.kVK_ANSI_F: - return key.CodeF - case C.kVK_ANSI_G: - return key.CodeG - case C.kVK_ANSI_H: - return key.CodeH - case C.kVK_ANSI_I: - return key.CodeI - case C.kVK_ANSI_J: - return key.CodeJ - case C.kVK_ANSI_K: - return key.CodeK - case C.kVK_ANSI_L: - return key.CodeL - case C.kVK_ANSI_M: - return key.CodeM - case C.kVK_ANSI_N: - return key.CodeN - case C.kVK_ANSI_O: - return key.CodeO - case C.kVK_ANSI_P: - return key.CodeP - case C.kVK_ANSI_Q: - return key.CodeQ - case C.kVK_ANSI_R: - return key.CodeR - case C.kVK_ANSI_S: - return key.CodeS - case C.kVK_ANSI_T: - return key.CodeT - case C.kVK_ANSI_U: - return key.CodeU - case C.kVK_ANSI_V: - return key.CodeV - case C.kVK_ANSI_W: - return key.CodeW - case C.kVK_ANSI_X: - return key.CodeX - case C.kVK_ANSI_Y: - return key.CodeY - case C.kVK_ANSI_Z: - return key.CodeZ - case C.kVK_ANSI_1: - return key.Code1 - case C.kVK_ANSI_2: - return key.Code2 - case C.kVK_ANSI_3: - return key.Code3 - case C.kVK_ANSI_4: - return key.Code4 - case C.kVK_ANSI_5: - return key.Code5 - case C.kVK_ANSI_6: - return key.Code6 - case C.kVK_ANSI_7: - return key.Code7 - case C.kVK_ANSI_8: - return key.Code8 - case C.kVK_ANSI_9: - return key.Code9 - case C.kVK_ANSI_0: - return key.Code0 - // TODO: move the rest of these codes to constants in key.go - // if we are happy with them. - case C.kVK_Return: - return key.CodeReturnEnter - case C.kVK_Escape: - return key.CodeEscape - case C.kVK_Delete: - return key.CodeDeleteBackspace - case C.kVK_Tab: - return key.CodeTab - case C.kVK_Space: - return key.CodeSpacebar - case C.kVK_ANSI_Minus: - return key.CodeHyphenMinus - case C.kVK_ANSI_Equal: - return key.CodeEqualSign - case C.kVK_ANSI_LeftBracket: - return key.CodeLeftSquareBracket - case C.kVK_ANSI_RightBracket: - return key.CodeRightSquareBracket - case C.kVK_ANSI_Backslash: - return key.CodeBackslash - // 50: Keyboard Non-US "#" and ~ - case C.kVK_ANSI_Semicolon: - return key.CodeSemicolon - case C.kVK_ANSI_Quote: - return key.CodeApostrophe - case C.kVK_ANSI_Grave: - return key.CodeGraveAccent - case C.kVK_ANSI_Comma: - return key.CodeComma - case C.kVK_ANSI_Period: - return key.CodeFullStop - case C.kVK_ANSI_Slash: - return key.CodeSlash - case C.kVK_CapsLock: - return key.CodeCapsLock - case C.kVK_F1: - return key.CodeF1 - case C.kVK_F2: - return key.CodeF2 - case C.kVK_F3: - return key.CodeF3 - case C.kVK_F4: - return key.CodeF4 - case C.kVK_F5: - return key.CodeF5 - case C.kVK_F6: - return key.CodeF6 - case C.kVK_F7: - return key.CodeF7 - case C.kVK_F8: - return key.CodeF8 - case C.kVK_F9: - return key.CodeF9 - case C.kVK_F10: - return key.CodeF10 - case C.kVK_F11: - return key.CodeF11 - case C.kVK_F12: - return key.CodeF12 - // 70: PrintScreen - // 71: Scroll Lock - // 72: Pause - // 73: Insert - case C.kVK_Home: - return key.CodeHome - case C.kVK_PageUp: - return key.CodePageUp - case C.kVK_ForwardDelete: - return key.CodeDeleteForward - case C.kVK_End: - return key.CodeEnd - case C.kVK_PageDown: - return key.CodePageDown - case C.kVK_RightArrow: - return key.CodeRightArrow - case C.kVK_LeftArrow: - return key.CodeLeftArrow - case C.kVK_DownArrow: - return key.CodeDownArrow - case C.kVK_UpArrow: - return key.CodeUpArrow - case C.kVK_ANSI_KeypadClear: - return key.CodeKeypadNumLock - case C.kVK_ANSI_KeypadDivide: - return key.CodeKeypadSlash - case C.kVK_ANSI_KeypadMultiply: - return key.CodeKeypadAsterisk - case C.kVK_ANSI_KeypadMinus: - return key.CodeKeypadHyphenMinus - case C.kVK_ANSI_KeypadPlus: - return key.CodeKeypadPlusSign - case C.kVK_ANSI_KeypadEnter: - return key.CodeKeypadEnter - case C.kVK_ANSI_Keypad1: - return key.CodeKeypad1 - case C.kVK_ANSI_Keypad2: - return key.CodeKeypad2 - case C.kVK_ANSI_Keypad3: - return key.CodeKeypad3 - case C.kVK_ANSI_Keypad4: - return key.CodeKeypad4 - case C.kVK_ANSI_Keypad5: - return key.CodeKeypad5 - case C.kVK_ANSI_Keypad6: - return key.CodeKeypad6 - case C.kVK_ANSI_Keypad7: - return key.CodeKeypad7 - case C.kVK_ANSI_Keypad8: - return key.CodeKeypad8 - case C.kVK_ANSI_Keypad9: - return key.CodeKeypad9 - case C.kVK_ANSI_Keypad0: - return key.CodeKeypad0 - case C.kVK_ANSI_KeypadDecimal: - return key.CodeKeypadFullStop - case C.kVK_ANSI_KeypadEquals: - return key.CodeKeypadEqualSign - case C.kVK_F13: - return key.CodeF13 - case C.kVK_F14: - return key.CodeF14 - case C.kVK_F15: - return key.CodeF15 - case C.kVK_F16: - return key.CodeF16 - case C.kVK_F17: - return key.CodeF17 - case C.kVK_F18: - return key.CodeF18 - case C.kVK_F19: - return key.CodeF19 - case C.kVK_F20: - return key.CodeF20 - // 116: Keyboard Execute - case C.kVK_Help: - return key.CodeHelp - // 118: Keyboard Menu - // 119: Keyboard Select - // 120: Keyboard Stop - // 121: Keyboard Again - // 122: Keyboard Undo - // 123: Keyboard Cut - // 124: Keyboard Copy - // 125: Keyboard Paste - // 126: Keyboard Find - case C.kVK_Mute: - return key.CodeMute - case C.kVK_VolumeUp: - return key.CodeVolumeUp - case C.kVK_VolumeDown: - return key.CodeVolumeDown - // 130: Keyboard Locking Caps Lock - // 131: Keyboard Locking Num Lock - // 132: Keyboard Locking Scroll Lock - // 133: Keyboard Comma - // 134: Keyboard Equal Sign - // ...: Bunch of stuff - case C.kVK_Control: - return key.CodeLeftControl - case C.kVK_Shift: - return key.CodeLeftShift - case C.kVK_Option: - return key.CodeLeftAlt - case C.kVK_Command: - return key.CodeLeftGUI - case C.kVK_RightControl: - return key.CodeRightControl - case C.kVK_RightShift: - return key.CodeRightShift - case C.kVK_RightOption: - return key.CodeRightAlt - // TODO key.CodeRightGUI - default: - return key.CodeUnknown - } -} diff --git a/vendor/golang.org/x/mobile/app/darwin_desktop.m b/vendor/golang.org/x/mobile/app/darwin_desktop.m deleted file mode 100644 index 071124f..0000000 --- a/vendor/golang.org/x/mobile/app/darwin_desktop.m +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && !ios -// +build darwin -// +build !ios - -#include "_cgo_export.h" -#include -#include - -#import -#import -#import - -void makeCurrentContext(GLintptr context) { - NSOpenGLContext* ctx = (NSOpenGLContext*)context; - [ctx makeCurrentContext]; -} - -uint64 threadID() { - uint64 id; - if (pthread_threadid_np(pthread_self(), &id)) { - abort(); - } - return id; -} - -@interface MobileGLView : NSOpenGLView -{ -} -@end - -@implementation MobileGLView -- (void)prepareOpenGL { - [super prepareOpenGL]; - [self setWantsBestResolutionOpenGLSurface:YES]; - GLint swapInt = 1; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; -#pragma clang diagnostic pop - - // Using attribute arrays in OpenGL 3.3 requires the use of a VBA. - // But VBAs don't exist in ES 2. So we bind a default one. - GLuint vba; - glGenVertexArrays(1, &vba); - glBindVertexArray(vba); - - startloop((GLintptr)[self openGLContext]); -} - -- (void)reshape { - [super reshape]; - - // Calculate screen PPI. - // - // Note that the backingScaleFactor converts from logical - // pixels to actual pixels, but both of these units vary - // independently from real world size. E.g. - // - // 13" Retina Macbook Pro, 2560x1600, 227ppi, backingScaleFactor=2, scale=3.15 - // 15" Retina Macbook Pro, 2880x1800, 220ppi, backingScaleFactor=2, scale=3.06 - // 27" iMac, 2560x1440, 109ppi, backingScaleFactor=1, scale=1.51 - // 27" Retina iMac, 5120x2880, 218ppi, backingScaleFactor=2, scale=3.03 - NSScreen *screen = [NSScreen mainScreen]; - double screenPixW = [screen frame].size.width * [screen backingScaleFactor]; - - CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue]; - CGSize screenSizeMM = CGDisplayScreenSize(display); // in millimeters - float ppi = 25.4 * screenPixW / screenSizeMM.width; - float pixelsPerPt = ppi/72.0; - - // The width and height reported to the geom package are the - // bounds of the OpenGL view. Several steps are necessary. - // First, [self bounds] gives us the number of logical pixels - // in the view. Multiplying this by the backingScaleFactor - // gives us the number of actual pixels. - NSRect r = [self bounds]; - int w = r.size.width * [screen backingScaleFactor]; - int h = r.size.height * [screen backingScaleFactor]; - - setGeom(pixelsPerPt, w, h); -} - -- (void)drawRect:(NSRect)theRect { - // Called during resize. This gets rid of flicker when resizing. - drawgl(); -} - -- (void)mouseDown:(NSEvent *)theEvent { - double scale = [[NSScreen mainScreen] backingScaleFactor]; - NSPoint p = [theEvent locationInWindow]; - eventMouseDown(p.x * scale, p.y * scale); -} - -- (void)mouseUp:(NSEvent *)theEvent { - double scale = [[NSScreen mainScreen] backingScaleFactor]; - NSPoint p = [theEvent locationInWindow]; - eventMouseEnd(p.x * scale, p.y * scale); -} - -- (void)mouseDragged:(NSEvent *)theEvent { - double scale = [[NSScreen mainScreen] backingScaleFactor]; - NSPoint p = [theEvent locationInWindow]; - eventMouseDragged(p.x * scale, p.y * scale); -} - -- (void)windowDidBecomeKey:(NSNotification *)notification { - lifecycleFocused(); -} - -- (void)windowDidResignKey:(NSNotification *)notification { - if (![NSApp isHidden]) { - lifecycleVisible(); - } -} - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - lifecycleAlive(); - [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)]; - [self.window makeKeyAndOrderFront:self]; - lifecycleVisible(); -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - lifecycleDead(); -} - -- (void)applicationDidHide:(NSNotification *)aNotification { - lifecycleAlive(); -} - -- (void)applicationWillUnhide:(NSNotification *)notification { - lifecycleVisible(); -} - -- (void)windowWillClose:(NSNotification *)notification { - lifecycleAlive(); -} -@end - -@interface MobileResponder : NSResponder -{ -} -@end - -@implementation MobileResponder -- (void)keyDown:(NSEvent *)theEvent { - [self key:theEvent]; -} -- (void)keyUp:(NSEvent *)theEvent { - [self key:theEvent]; -} -- (void)key:(NSEvent *)theEvent { - NSRange range = [theEvent.characters rangeOfComposedCharacterSequenceAtIndex:0]; - - uint8_t buf[4] = {0, 0, 0, 0}; - if (![theEvent.characters getBytes:buf - maxLength:4 - usedLength:nil - encoding:NSUTF32LittleEndianStringEncoding - options:NSStringEncodingConversionAllowLossy - range:range - remainingRange:nil]) { - NSLog(@"failed to read key event %@", theEvent); - return; - } - - uint32_t rune = (uint32_t)buf[0]<<0 | (uint32_t)buf[1]<<8 | (uint32_t)buf[2]<<16 | (uint32_t)buf[3]<<24; - - uint8_t direction; - if ([theEvent isARepeat]) { - direction = 0; - } else if (theEvent.type == NSEventTypeKeyDown) { - direction = 1; - } else { - direction = 2; - } - eventKey((int32_t)rune, direction, theEvent.keyCode, theEvent.modifierFlags); -} - -- (void)flagsChanged:(NSEvent *)theEvent { - eventFlags(theEvent.modifierFlags); -} -@end - -void -runApp(void) { - [NSAutoreleasePool new]; - [NSApplication sharedApplication]; - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - - id menuBar = [[NSMenu new] autorelease]; - id menuItem = [[NSMenuItem new] autorelease]; - [menuBar addItem:menuItem]; - [NSApp setMainMenu:menuBar]; - - id menu = [[NSMenu new] autorelease]; - id name = [[NSProcessInfo processInfo] processName]; - - id hideMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Hide" - action:@selector(hide:) keyEquivalent:@"h"] - autorelease]; - [menu addItem:hideMenuItem]; - - id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Quit" - action:@selector(terminate:) keyEquivalent:@"q"] - autorelease]; - [menu addItem:quitMenuItem]; - [menuItem setSubmenu:menu]; - - NSRect rect = NSMakeRect(0, 0, 600, 800); - - NSWindow* window = [[[NSWindow alloc] initWithContentRect:rect - styleMask:NSWindowStyleMaskTitled - backing:NSBackingStoreBuffered - defer:NO] - autorelease]; - window.styleMask |= NSWindowStyleMaskResizable; - window.styleMask |= NSWindowStyleMaskMiniaturizable; - window.styleMask |= NSWindowStyleMaskClosable; - window.title = name; - [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; - - NSOpenGLPixelFormatAttribute attr[] = { - NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 16, - NSOpenGLPFAAccelerated, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAllowOfflineRenderers, - 0 - }; - id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; - MobileGLView* view = [[MobileGLView alloc] initWithFrame:rect pixelFormat:pixFormat]; - [window setContentView:view]; - [window setDelegate:view]; - [NSApp setDelegate:view]; - - window.nextResponder = [[[MobileResponder alloc] init] autorelease]; - - [NSApp run]; -} - -void stopApp(void) { - [NSApp terminate:nil]; -} diff --git a/vendor/golang.org/x/mobile/app/darwin_ios.go b/vendor/golang.org/x/mobile/app/darwin_ios.go deleted file mode 100644 index 8fb30fe..0000000 --- a/vendor/golang.org/x/mobile/app/darwin_ios.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && ios -// +build darwin,ios - -package app - -/* -#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION -DGLES_SILENCE_DEPRECATION -#cgo LDFLAGS: -framework Foundation -framework UIKit -framework GLKit -framework OpenGLES -framework QuartzCore -#include -#include -#include -#include -#import - -extern struct utsname sysInfo; - -void runApp(void); -void makeCurrentContext(GLintptr ctx); -void swapBuffers(GLintptr ctx); -uint64_t threadID(); -*/ -import "C" -import ( - "log" - "runtime" - "strings" - "sync" - - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/event/touch" - "golang.org/x/mobile/geom" -) - -var initThreadID uint64 - -func init() { - // Lock the goroutine responsible for initialization to an OS thread. - // This means the goroutine running main (and calling the run function - // below) is locked to the OS thread that started the program. This is - // necessary for the correct delivery of UIKit events to the process. - // - // A discussion on this topic: - // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ - runtime.LockOSThread() - initThreadID = uint64(C.threadID()) -} - -func main(f func(App)) { - if tid := uint64(C.threadID()); tid != initThreadID { - log.Fatalf("app.Run called on thread %d, but app.init ran on %d", tid, initThreadID) - } - - go func() { - f(theApp) - // TODO(crawshaw): trigger runApp to return - }() - C.runApp() - panic("unexpected return from app.runApp") -} - -var pixelsPerPt float32 -var screenScale int // [UIScreen mainScreen].scale, either 1, 2, or 3. - -//export setScreen -func setScreen(scale int) { - C.uname(&C.sysInfo) - name := C.GoString(&C.sysInfo.machine[0]) - - var v float32 - - switch { - case strings.HasPrefix(name, "iPhone"): - v = 163 - case strings.HasPrefix(name, "iPad"): - // TODO: is there a better way to distinguish the iPad Mini? - switch name { - case "iPad2,5", "iPad2,6", "iPad2,7", "iPad4,4", "iPad4,5", "iPad4,6", "iPad4,7": - v = 163 // iPad Mini - default: - v = 132 - } - default: - v = 163 // names like i386 and x86_64 are the simulator - } - - if v == 0 { - log.Printf("unknown machine: %s", name) - v = 163 // emergency fallback - } - - pixelsPerPt = v * float32(scale) / 72 - screenScale = scale -} - -//export updateConfig -func updateConfig(width, height, orientation int32) { - o := size.OrientationUnknown - switch orientation { - case C.UIDeviceOrientationPortrait, C.UIDeviceOrientationPortraitUpsideDown: - o = size.OrientationPortrait - case C.UIDeviceOrientationLandscapeLeft, C.UIDeviceOrientationLandscapeRight: - o = size.OrientationLandscape - } - widthPx := screenScale * int(width) - heightPx := screenScale * int(height) - theApp.eventsIn <- size.Event{ - WidthPx: widthPx, - HeightPx: heightPx, - WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), - HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), - PixelsPerPt: pixelsPerPt, - Orientation: o, - } - theApp.eventsIn <- paint.Event{External: true} -} - -// touchIDs is the current active touches. The position in the array -// is the ID, the value is the UITouch* pointer value. -// -// It is widely reported that the iPhone can handle up to 5 simultaneous -// touch events, while the iPad can handle 11. -var touchIDs [11]uintptr - -var touchEvents struct { - sync.Mutex - pending []touch.Event -} - -//export sendTouch -func sendTouch(cTouch, cTouchType uintptr, x, y float32) { - id := -1 - for i, val := range touchIDs { - if val == cTouch { - id = i - break - } - } - if id == -1 { - for i, val := range touchIDs { - if val == 0 { - touchIDs[i] = cTouch - id = i - break - } - } - if id == -1 { - panic("out of touchIDs") - } - } - - t := touch.Type(cTouchType) - if t == touch.TypeEnd { - touchIDs[id] = 0 - } - - theApp.eventsIn <- touch.Event{ - X: x, - Y: y, - Sequence: touch.Sequence(id), - Type: t, - } -} - -//export lifecycleDead -func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) } - -//export lifecycleAlive -func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) } - -//export lifecycleVisible -func lifecycleVisible() { theApp.sendLifecycle(lifecycle.StageVisible) } - -//export lifecycleFocused -func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) } - -//export startloop -func startloop(ctx C.GLintptr) { - go theApp.loop(ctx) -} - -// loop is the primary drawing loop. -// -// After UIKit has captured the initial OS thread for processing UIKit -// events in runApp, it starts loop on another goroutine. It is locked -// to an OS thread for its OpenGL context. -func (a *app) loop(ctx C.GLintptr) { - runtime.LockOSThread() - C.makeCurrentContext(ctx) - - workAvailable := a.worker.WorkAvailable() - - for { - select { - case <-workAvailable: - a.worker.DoWork() - case <-theApp.publish: - loop1: - for { - select { - case <-workAvailable: - a.worker.DoWork() - default: - break loop1 - } - } - C.swapBuffers(ctx) - theApp.publishResult <- PublishResult{} - } - } -} diff --git a/vendor/golang.org/x/mobile/app/darwin_ios.m b/vendor/golang.org/x/mobile/app/darwin_ios.m deleted file mode 100644 index 21d73a5..0000000 --- a/vendor/golang.org/x/mobile/app/darwin_ios.m +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && ios -// +build darwin -// +build ios - -#include "_cgo_export.h" -#include -#include -#include - -#import -#import - -struct utsname sysInfo; - -@interface GoAppAppController : GLKViewController -@end - -@interface GoAppAppDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; -@property (strong, nonatomic) GoAppAppController *controller; -@end - -@implementation GoAppAppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - lifecycleAlive(); - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.controller = [[GoAppAppController alloc] initWithNibName:nil bundle:nil]; - self.window.rootViewController = self.controller; - [self.window makeKeyAndVisible]; - return YES; -} - -- (void)applicationDidBecomeActive:(UIApplication * )application { - lifecycleFocused(); -} - -- (void)applicationWillResignActive:(UIApplication *)application { - lifecycleVisible(); -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - lifecycleAlive(); -} - -- (void)applicationWillTerminate:(UIApplication *)application { - lifecycleDead(); -} -@end - -@interface GoAppAppController () -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKView *glview; -@end - -@implementation GoAppAppController -- (void)viewWillAppear:(BOOL)animated -{ - // TODO: replace by swapping out GLKViewController for a UIVIewController. - [super viewWillAppear:animated]; - self.paused = YES; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - self.glview = (GLKView*)self.view; - self.glview.drawableDepthFormat = GLKViewDrawableDepthFormat24; - self.glview.multipleTouchEnabled = true; // TODO expose setting to user. - self.glview.context = self.context; - self.glview.userInteractionEnabled = YES; - self.glview.enableSetNeedsDisplay = YES; // only invoked once - - // Do not use the GLKViewController draw loop. - self.paused = YES; - self.resumeOnDidBecomeActive = NO; - self.preferredFramesPerSecond = 0; - - int scale = 1; - if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)]) { - scale = (int)[UIScreen mainScreen].scale; // either 1.0, 2.0, or 3.0. - } - setScreen(scale); - - CGSize size = [UIScreen mainScreen].bounds.size; - UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; - updateConfig((int)size.width, (int)size.height, orientation); -} - -- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { - [coordinator animateAlongsideTransition:^(id context) { - // TODO(crawshaw): come up with a plan to handle animations. - } completion:^(id context) { - UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; - updateConfig((int)size.width, (int)size.height, orientation); - }]; -} - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - // Now that we have been asked to do the first draw, disable any - // future draw and hand control over to the Go paint.Event cycle. - self.glview.enableSetNeedsDisplay = NO; - startloop((GLintptr)self.context); -} - -#define TOUCH_TYPE_BEGIN 0 // touch.TypeBegin -#define TOUCH_TYPE_MOVE 1 // touch.TypeMove -#define TOUCH_TYPE_END 2 // touch.TypeEnd - -static void sendTouches(int change, NSSet* touches) { - CGFloat scale = [UIScreen mainScreen].scale; - for (UITouch* touch in touches) { - CGPoint p = [touch locationInView:touch.view]; - sendTouch((GoUintptr)touch, (GoUintptr)change, p.x*scale, p.y*scale); - } -} - -- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { - sendTouches(TOUCH_TYPE_BEGIN, touches); -} - -- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { - sendTouches(TOUCH_TYPE_MOVE, touches); -} - -- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { - sendTouches(TOUCH_TYPE_END, touches); -} - -- (void)touchesCanceled:(NSSet*)touches withEvent:(UIEvent*)event { - sendTouches(TOUCH_TYPE_END, touches); -} -@end - -void runApp(void) { - char* argv[] = {}; - @autoreleasepool { - UIApplicationMain(0, argv, nil, NSStringFromClass([GoAppAppDelegate class])); - } -} - -void makeCurrentContext(GLintptr context) { - EAGLContext* ctx = (EAGLContext*)context; - if (![EAGLContext setCurrentContext:ctx]) { - // TODO(crawshaw): determine how terrible this is. Exit? - NSLog(@"failed to set current context"); - } -} - -void swapBuffers(GLintptr context) { - __block EAGLContext* ctx = (EAGLContext*)context; - dispatch_sync(dispatch_get_main_queue(), ^{ - [EAGLContext setCurrentContext:ctx]; - [ctx presentRenderbuffer:GL_RENDERBUFFER]; - }); -} - -uint64_t threadID() { - uint64_t id; - if (pthread_threadid_np(pthread_self(), &id)) { - abort(); - } - return id; -} diff --git a/vendor/golang.org/x/mobile/app/doc.go b/vendor/golang.org/x/mobile/app/doc.go deleted file mode 100644 index 02bd6db..0000000 --- a/vendor/golang.org/x/mobile/app/doc.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package app lets you write portable all-Go apps for Android and iOS. - -There are typically two ways to use Go on Android and iOS. The first -is to write a Go library and use `gomobile bind` to generate language -bindings for Java and Objective-C. Building a library does not -require the app package. The `gomobile bind` command produces output -that you can include in an Android Studio or Xcode project. For more -on language bindings, see https://golang.org/x/mobile/cmd/gobind. - -The second way is to write an app entirely in Go. The APIs are limited -to those that are portable between both Android and iOS, in particular -OpenGL, audio, and other Android NDK-like APIs. An all-Go app should -use this app package to initialize the app, manage its lifecycle, and -receive events. - -# Building apps - -Apps written entirely in Go have a main function, and can be built -with `gomobile build`, which directly produces runnable output for -Android and iOS. - -The gomobile tool can get installed with go get. For reference, see -https://golang.org/x/mobile/cmd/gomobile. - -For detailed instructions and documentation, see -https://golang.org/wiki/Mobile. - -# Event processing in Native Apps - -The Go runtime is initialized on Android when NativeActivity onCreate is -called, and on iOS when the process starts. In both cases, Go init functions -run before the app lifecycle has started. - -An app is expected to call the Main function in main.main. When the function -exits, the app exits. Inside the func passed to Main, call Filter on every -event received, and then switch on its type. Registered filters run when the -event is received, not when it is sent, so that filters run in the same -goroutine as other code that calls OpenGL. - - package main - - import ( - "log" - - "golang.org/x/mobile/app" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/paint" - ) - - func main() { - app.Main(func(a app.App) { - for e := range a.Events() { - switch e := a.Filter(e).(type) { - case lifecycle.Event: - // ... - case paint.Event: - log.Print("Call OpenGL here.") - a.Publish() - } - } - }) - } - -An event is represented by the empty interface type interface{}. Any value can -be an event. Commonly used types include Event types defined by the following -packages: - - golang.org/x/mobile/event/lifecycle - - golang.org/x/mobile/event/mouse - - golang.org/x/mobile/event/paint - - golang.org/x/mobile/event/size - - golang.org/x/mobile/event/touch - -For example, touch.Event is the type that represents touch events. Other -packages may define their own events, and send them on an app's event channel. - -Other packages can also register event filters, e.g. to manage resources in -response to lifecycle events. Such packages should call: - - app.RegisterFilter(etc) - -in an init function inside that package. -*/ -package app // import "golang.org/x/mobile/app" diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn.go b/vendor/golang.org/x/mobile/app/internal/callfn/callfn.go deleted file mode 100644 index 7a3d050..0000000 --- a/vendor/golang.org/x/mobile/app/internal/callfn/callfn.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build android && (arm || 386 || amd64 || arm64) -// +build android -// +build arm 386 amd64 arm64 - -// Package callfn provides an android entry point. -// -// It is a separate package from app because it contains Go assembly, -// which does not compile in a package using cgo. -package callfn - -// CallFn calls a zero-argument function by its program counter. -// It is only intended for calling main.main. Using it for -// anything else will not end well. -func CallFn(fn uintptr) diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_386.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_386.s deleted file mode 100644 index d2bb54f..0000000 --- a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_386.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" -#include "funcdata.h" - -TEXT ·CallFn(SB),$0-4 - MOVL fn+0(FP), AX - CALL AX - RET diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_amd64.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_amd64.s deleted file mode 100644 index 8769604..0000000 --- a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_amd64.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" -#include "funcdata.h" - -TEXT ·CallFn(SB),$0-8 - MOVQ fn+0(FP), AX - CALL AX - RET diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm.s deleted file mode 100644 index d71f748..0000000 --- a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" -#include "funcdata.h" - -TEXT ·CallFn(SB),$0-4 - MOVW fn+0(FP), R0 - BL (R0) - RET diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm64.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm64.s deleted file mode 100644 index 545ad50..0000000 --- a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm64.s +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" -#include "funcdata.h" - -TEXT ·CallFn(SB),$0-8 - MOVD fn+0(FP), R0 - BL (R0) - RET diff --git a/vendor/golang.org/x/mobile/app/shiny.go b/vendor/golang.org/x/mobile/app/shiny.go deleted file mode 100644 index dd1722a..0000000 --- a/vendor/golang.org/x/mobile/app/shiny.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -package app - -import ( - "log" - - "golang.org/x/exp/shiny/driver/gldriver" - "golang.org/x/exp/shiny/screen" - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/mouse" - "golang.org/x/mobile/event/touch" - "golang.org/x/mobile/gl" -) - -func main(f func(a App)) { - gldriver.Main(func(s screen.Screen) { - w, err := s.NewWindow(nil) - if err != nil { - log.Fatal(err) - } - defer w.Release() - - theApp.glctx = nil - theApp.worker = nil // handled by shiny - - go func() { - for range theApp.publish { - res := w.Publish() - theApp.publishResult <- PublishResult{ - BackBufferPreserved: res.BackBufferPreserved, - } - } - }() - - donec := make(chan struct{}) - go func() { - // close the donec channel in a defer statement - // so that we could still be able to return even - // if f panics. - defer close(donec) - - f(theApp) - }() - - for { - select { - case <-donec: - return - default: - theApp.Send(convertEvent(w.NextEvent())) - } - } - }) -} - -func convertEvent(e interface{}) interface{} { - switch e := e.(type) { - case lifecycle.Event: - if theApp.glctx == nil { - theApp.glctx = e.DrawContext.(gl.Context) - } - case mouse.Event: - te := touch.Event{ - X: e.X, - Y: e.Y, - } - switch e.Direction { - case mouse.DirNone: - te.Type = touch.TypeMove - case mouse.DirPress: - te.Type = touch.TypeBegin - case mouse.DirRelease: - te.Type = touch.TypeEnd - } - return te - } - return e -} diff --git a/vendor/golang.org/x/mobile/app/x11.c b/vendor/golang.org/x/mobile/app/x11.c deleted file mode 100644 index 755bb24..0000000 --- a/vendor/golang.org/x/mobile/app/x11.c +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && !android -// +build linux,!android - -#include "_cgo_export.h" -#include -#include -#include -#include -#include -#include - -static Atom wm_delete_window; - -static Window -new_window(Display *x_dpy, EGLDisplay e_dpy, int w, int h, EGLContext *ctx, EGLSurface *surf) { - static const EGLint attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 16, - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_NONE - }; - EGLConfig config; - EGLint num_configs; - if (!eglChooseConfig(e_dpy, attribs, &config, 1, &num_configs)) { - fprintf(stderr, "eglChooseConfig failed\n"); - exit(1); - } - EGLint vid; - if (!eglGetConfigAttrib(e_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { - fprintf(stderr, "eglGetConfigAttrib failed\n"); - exit(1); - } - - XVisualInfo visTemplate; - visTemplate.visualid = vid; - int num_visuals; - XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); - if (!visInfo) { - fprintf(stderr, "XGetVisualInfo failed\n"); - exit(1); - } - - Window root = RootWindow(x_dpy, DefaultScreen(x_dpy)); - XSetWindowAttributes attr; - - attr.colormap = XCreateColormap(x_dpy, root, visInfo->visual, AllocNone); - if (!attr.colormap) { - fprintf(stderr, "XCreateColormap failed\n"); - exit(1); - } - - attr.event_mask = StructureNotifyMask | ExposureMask | - ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; - Window win = XCreateWindow( - x_dpy, root, 0, 0, w, h, 0, visInfo->depth, InputOutput, - visInfo->visual, CWColormap | CWEventMask, &attr); - XFree(visInfo); - - XSizeHints sizehints; - sizehints.width = w; - sizehints.height = h; - sizehints.flags = USSize; - XSetNormalHints(x_dpy, win, &sizehints); - XSetStandardProperties(x_dpy, win, "App", "App", None, (char **)NULL, 0, &sizehints); - - static const EGLint ctx_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - *ctx = eglCreateContext(e_dpy, config, EGL_NO_CONTEXT, ctx_attribs); - if (!*ctx) { - fprintf(stderr, "eglCreateContext failed\n"); - exit(1); - } - *surf = eglCreateWindowSurface(e_dpy, config, win, NULL); - if (!*surf) { - fprintf(stderr, "eglCreateWindowSurface failed\n"); - exit(1); - } - return win; -} - -Display *x_dpy; -EGLDisplay e_dpy; -EGLContext e_ctx; -EGLSurface e_surf; -Window win; - -void -createWindow(void) { - x_dpy = XOpenDisplay(NULL); - if (!x_dpy) { - fprintf(stderr, "XOpenDisplay failed\n"); - exit(1); - } - e_dpy = eglGetDisplay(x_dpy); - if (!e_dpy) { - fprintf(stderr, "eglGetDisplay failed\n"); - exit(1); - } - EGLint e_major, e_minor; - if (!eglInitialize(e_dpy, &e_major, &e_minor)) { - fprintf(stderr, "eglInitialize failed\n"); - exit(1); - } - eglBindAPI(EGL_OPENGL_ES_API); - win = new_window(x_dpy, e_dpy, 600, 800, &e_ctx, &e_surf); - - wm_delete_window = XInternAtom(x_dpy, "WM_DELETE_WINDOW", True); - if (wm_delete_window != None) { - XSetWMProtocols(x_dpy, win, &wm_delete_window, 1); - } - - XMapWindow(x_dpy, win); - if (!eglMakeCurrent(e_dpy, e_surf, e_surf, e_ctx)) { - fprintf(stderr, "eglMakeCurrent failed\n"); - exit(1); - } - - // Window size and DPI should be initialized before starting app. - XEvent ev; - while (1) { - if (XCheckMaskEvent(x_dpy, StructureNotifyMask, &ev) == False) { - continue; - } - if (ev.type == ConfigureNotify) { - onResize(ev.xconfigure.width, ev.xconfigure.height); - break; - } - } -} - -void -processEvents(void) { - while (XPending(x_dpy)) { - XEvent ev; - XNextEvent(x_dpy, &ev); - switch (ev.type) { - case ButtonPress: - onTouchBegin((float)ev.xbutton.x, (float)ev.xbutton.y); - break; - case ButtonRelease: - onTouchEnd((float)ev.xbutton.x, (float)ev.xbutton.y); - break; - case MotionNotify: - onTouchMove((float)ev.xmotion.x, (float)ev.xmotion.y); - break; - case ConfigureNotify: - onResize(ev.xconfigure.width, ev.xconfigure.height); - break; - case ClientMessage: - if (wm_delete_window != None && (Atom)ev.xclient.data.l[0] == wm_delete_window) { - onStop(); - return; - } - break; - } - } -} - -void -swapBuffers(void) { - if (eglSwapBuffers(e_dpy, e_surf) == EGL_FALSE) { - fprintf(stderr, "eglSwapBuffer failed\n"); - exit(1); - } -} diff --git a/vendor/golang.org/x/mobile/app/x11.go b/vendor/golang.org/x/mobile/app/x11.go deleted file mode 100644 index ec8c90a..0000000 --- a/vendor/golang.org/x/mobile/app/x11.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && !android -// +build linux,!android - -package app - -/* -Simple on-screen app debugging for X11. Not an officially supported -development target for apps, as screens with mice are very different -than screens with touch panels. -*/ - -/* -#cgo LDFLAGS: -lEGL -lGLESv2 -lX11 - -void createWindow(void); -void processEvents(void); -void swapBuffers(void); -*/ -import "C" -import ( - "runtime" - "time" - - "golang.org/x/mobile/event/lifecycle" - "golang.org/x/mobile/event/paint" - "golang.org/x/mobile/event/size" - "golang.org/x/mobile/event/touch" - "golang.org/x/mobile/geom" -) - -func init() { - theApp.registerGLViewportFilter() -} - -func main(f func(App)) { - runtime.LockOSThread() - - workAvailable := theApp.worker.WorkAvailable() - - C.createWindow() - - // TODO: send lifecycle events when e.g. the X11 window is iconified or moved off-screen. - theApp.sendLifecycle(lifecycle.StageFocused) - - // TODO: translate X11 expose events to shiny paint events, instead of - // sending this synthetic paint event as a hack. - theApp.eventsIn <- paint.Event{} - - donec := make(chan struct{}) - go func() { - // close the donec channel in a defer statement - // so that we could still be able to return even - // if f panics. - defer close(donec) - - f(theApp) - }() - - // TODO: can we get the actual vsync signal? - ticker := time.NewTicker(time.Second / 60) - defer ticker.Stop() - var tc <-chan time.Time - - for { - select { - case <-donec: - return - case <-workAvailable: - theApp.worker.DoWork() - case <-theApp.publish: - C.swapBuffers() - tc = ticker.C - case <-tc: - tc = nil - theApp.publishResult <- PublishResult{} - } - C.processEvents() - } -} - -//export onResize -func onResize(w, h int) { - // TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM - // is probably the best place to start looking. - pixelsPerPt := float32(1) - theApp.eventsIn <- size.Event{ - WidthPx: w, - HeightPx: h, - WidthPt: geom.Pt(w), - HeightPt: geom.Pt(h), - PixelsPerPt: pixelsPerPt, - } -} - -func sendTouch(t touch.Type, x, y float32) { - theApp.eventsIn <- touch.Event{ - X: x, - Y: y, - Sequence: 0, // TODO: button?? - Type: t, - } -} - -//export onTouchBegin -func onTouchBegin(x, y float32) { sendTouch(touch.TypeBegin, x, y) } - -//export onTouchMove -func onTouchMove(x, y float32) { sendTouch(touch.TypeMove, x, y) } - -//export onTouchEnd -func onTouchEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) } - -var stopped bool - -//export onStop -func onStop() { - if stopped { - return - } - stopped = true - theApp.sendLifecycle(lifecycle.StageDead) - theApp.eventsIn <- stopPumping{} -} diff --git a/vendor/golang.org/x/mobile/event/key/code_string.go b/vendor/golang.org/x/mobile/event/key/code_string.go deleted file mode 100644 index 6af78b3..0000000 --- a/vendor/golang.org/x/mobile/event/key/code_string.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by "stringer -type=Code"; DO NOT EDIT - -package key - -import "fmt" - -const ( - _Code_name_0 = "CodeUnknown" - _Code_name_1 = "CodeACodeBCodeCCodeDCodeECodeFCodeGCodeHCodeICodeJCodeKCodeLCodeMCodeNCodeOCodePCodeQCodeRCodeSCodeTCodeUCodeVCodeWCodeXCodeYCodeZCode1Code2Code3Code4Code5Code6Code7Code8Code9Code0CodeReturnEnterCodeEscapeCodeDeleteBackspaceCodeTabCodeSpacebarCodeHyphenMinusCodeEqualSignCodeLeftSquareBracketCodeRightSquareBracketCodeBackslash" - _Code_name_2 = "CodeSemicolonCodeApostropheCodeGraveAccentCodeCommaCodeFullStopCodeSlashCodeCapsLockCodeF1CodeF2CodeF3CodeF4CodeF5CodeF6CodeF7CodeF8CodeF9CodeF10CodeF11CodeF12" - _Code_name_3 = "CodePauseCodeInsertCodeHomeCodePageUpCodeDeleteForwardCodeEndCodePageDownCodeRightArrowCodeLeftArrowCodeDownArrowCodeUpArrowCodeKeypadNumLockCodeKeypadSlashCodeKeypadAsteriskCodeKeypadHyphenMinusCodeKeypadPlusSignCodeKeypadEnterCodeKeypad1CodeKeypad2CodeKeypad3CodeKeypad4CodeKeypad5CodeKeypad6CodeKeypad7CodeKeypad8CodeKeypad9CodeKeypad0CodeKeypadFullStop" - _Code_name_4 = "CodeKeypadEqualSignCodeF13CodeF14CodeF15CodeF16CodeF17CodeF18CodeF19CodeF20CodeF21CodeF22CodeF23CodeF24" - _Code_name_5 = "CodeHelp" - _Code_name_6 = "CodeMuteCodeVolumeUpCodeVolumeDown" - _Code_name_7 = "CodeLeftControlCodeLeftShiftCodeLeftAltCodeLeftGUICodeRightControlCodeRightShiftCodeRightAltCodeRightGUI" - _Code_name_8 = "CodeCompose" -) - -var ( - _Code_index_0 = [...]uint8{0, 11} - _Code_index_1 = [...]uint16{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 195, 205, 224, 231, 243, 258, 271, 292, 314, 327} - _Code_index_2 = [...]uint8{0, 13, 27, 42, 51, 63, 72, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 145, 152, 159} - _Code_index_3 = [...]uint16{0, 9, 19, 27, 37, 54, 61, 73, 87, 100, 113, 124, 141, 156, 174, 195, 213, 228, 239, 250, 261, 272, 283, 294, 305, 316, 327, 338, 356} - _Code_index_4 = [...]uint8{0, 19, 26, 33, 40, 47, 54, 61, 68, 75, 82, 89, 96, 103} - _Code_index_5 = [...]uint8{0, 8} - _Code_index_6 = [...]uint8{0, 8, 20, 34} - _Code_index_7 = [...]uint8{0, 15, 28, 39, 50, 66, 80, 92, 104} - _Code_index_8 = [...]uint8{0, 11} -) - -func (i Code) String() string { - switch { - case i == 0: - return _Code_name_0 - case 4 <= i && i <= 49: - i -= 4 - return _Code_name_1[_Code_index_1[i]:_Code_index_1[i+1]] - case 51 <= i && i <= 69: - i -= 51 - return _Code_name_2[_Code_index_2[i]:_Code_index_2[i+1]] - case 72 <= i && i <= 99: - i -= 72 - return _Code_name_3[_Code_index_3[i]:_Code_index_3[i+1]] - case 103 <= i && i <= 115: - i -= 103 - return _Code_name_4[_Code_index_4[i]:_Code_index_4[i+1]] - case i == 117: - return _Code_name_5 - case 127 <= i && i <= 129: - i -= 127 - return _Code_name_6[_Code_index_6[i]:_Code_index_6[i+1]] - case 224 <= i && i <= 231: - i -= 224 - return _Code_name_7[_Code_index_7[i]:_Code_index_7[i+1]] - case i == 65536: - return _Code_name_8 - default: - return fmt.Sprintf("Code(%d)", i) - } -} diff --git a/vendor/golang.org/x/mobile/event/key/key.go b/vendor/golang.org/x/mobile/event/key/key.go deleted file mode 100644 index d70f1c3..0000000 --- a/vendor/golang.org/x/mobile/event/key/key.go +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate stringer -type=Code - -// Package key defines an event for physical keyboard keys. -// -// On-screen software keyboards do not send key events. -// -// See the golang.org/x/mobile/app package for details on the event model. -package key - -import ( - "fmt" - "strings" -) - -// Event is a key event. -type Event struct { - // Rune is the meaning of the key event as determined by the - // operating system. The mapping is determined by system-dependent - // current layout, modifiers, lock-states, etc. - // - // If non-negative, it is a Unicode codepoint: pressing the 'a' key - // generates different Runes 'a' or 'A' (but the same Code) depending on - // the state of the shift key. - // - // If -1, the key does not generate a Unicode codepoint. To distinguish - // them, look at Code. - Rune rune - - // Code is the identity of the physical key relative to a notional - // "standard" keyboard, independent of current layout, modifiers, - // lock-states, etc - // - // For standard key codes, its value matches USB HID key codes. - // Compare its value to uint32-typed constants in this package, such - // as CodeLeftShift and CodeEscape. - // - // Pressing the regular '2' key and number-pad '2' key (with Num-Lock) - // generate different Codes (but the same Rune). - Code Code - - // Modifiers is a bitmask representing a set of modifier keys: ModShift, - // ModAlt, etc. - Modifiers Modifiers - - // Direction is the direction of the key event: DirPress, DirRelease, - // or DirNone (for key repeats). - Direction Direction - - // TODO: add a Device ID, for multiple input devices? - // TODO: add a time.Time? -} - -func (e Event) String() string { - if e.Rune >= 0 { - return fmt.Sprintf("key.Event{%q (%v), %v, %v}", e.Rune, e.Code, e.Modifiers, e.Direction) - } - return fmt.Sprintf("key.Event{(%v), %v, %v}", e.Code, e.Modifiers, e.Direction) -} - -// Direction is the direction of the key event. -type Direction uint8 - -const ( - DirNone Direction = 0 - DirPress Direction = 1 - DirRelease Direction = 2 -) - -// Modifiers is a bitmask representing a set of modifier keys. -type Modifiers uint32 - -const ( - ModShift Modifiers = 1 << 0 - ModControl Modifiers = 1 << 1 - ModAlt Modifiers = 1 << 2 - ModMeta Modifiers = 1 << 3 // called "Command" on OS X -) - -// Code is the identity of a key relative to a notional "standard" keyboard. -type Code uint32 - -// Physical key codes. -// -// For standard key codes, its value matches USB HID key codes. -// TODO: add missing codes. -const ( - CodeUnknown Code = 0 - - CodeA Code = 4 - CodeB Code = 5 - CodeC Code = 6 - CodeD Code = 7 - CodeE Code = 8 - CodeF Code = 9 - CodeG Code = 10 - CodeH Code = 11 - CodeI Code = 12 - CodeJ Code = 13 - CodeK Code = 14 - CodeL Code = 15 - CodeM Code = 16 - CodeN Code = 17 - CodeO Code = 18 - CodeP Code = 19 - CodeQ Code = 20 - CodeR Code = 21 - CodeS Code = 22 - CodeT Code = 23 - CodeU Code = 24 - CodeV Code = 25 - CodeW Code = 26 - CodeX Code = 27 - CodeY Code = 28 - CodeZ Code = 29 - - Code1 Code = 30 - Code2 Code = 31 - Code3 Code = 32 - Code4 Code = 33 - Code5 Code = 34 - Code6 Code = 35 - Code7 Code = 36 - Code8 Code = 37 - Code9 Code = 38 - Code0 Code = 39 - - CodeReturnEnter Code = 40 - CodeEscape Code = 41 - CodeDeleteBackspace Code = 42 - CodeTab Code = 43 - CodeSpacebar Code = 44 - CodeHyphenMinus Code = 45 // - - CodeEqualSign Code = 46 // = - CodeLeftSquareBracket Code = 47 // [ - CodeRightSquareBracket Code = 48 // ] - CodeBackslash Code = 49 // \ - CodeSemicolon Code = 51 // ; - CodeApostrophe Code = 52 // ' - CodeGraveAccent Code = 53 // ` - CodeComma Code = 54 // , - CodeFullStop Code = 55 // . - CodeSlash Code = 56 // / - CodeCapsLock Code = 57 - - CodeF1 Code = 58 - CodeF2 Code = 59 - CodeF3 Code = 60 - CodeF4 Code = 61 - CodeF5 Code = 62 - CodeF6 Code = 63 - CodeF7 Code = 64 - CodeF8 Code = 65 - CodeF9 Code = 66 - CodeF10 Code = 67 - CodeF11 Code = 68 - CodeF12 Code = 69 - - CodePause Code = 72 - CodeInsert Code = 73 - CodeHome Code = 74 - CodePageUp Code = 75 - CodeDeleteForward Code = 76 - CodeEnd Code = 77 - CodePageDown Code = 78 - - CodeRightArrow Code = 79 - CodeLeftArrow Code = 80 - CodeDownArrow Code = 81 - CodeUpArrow Code = 82 - - CodeKeypadNumLock Code = 83 - CodeKeypadSlash Code = 84 // / - CodeKeypadAsterisk Code = 85 // * - CodeKeypadHyphenMinus Code = 86 // - - CodeKeypadPlusSign Code = 87 // + - CodeKeypadEnter Code = 88 - CodeKeypad1 Code = 89 - CodeKeypad2 Code = 90 - CodeKeypad3 Code = 91 - CodeKeypad4 Code = 92 - CodeKeypad5 Code = 93 - CodeKeypad6 Code = 94 - CodeKeypad7 Code = 95 - CodeKeypad8 Code = 96 - CodeKeypad9 Code = 97 - CodeKeypad0 Code = 98 - CodeKeypadFullStop Code = 99 // . - CodeKeypadEqualSign Code = 103 // = - - CodeF13 Code = 104 - CodeF14 Code = 105 - CodeF15 Code = 106 - CodeF16 Code = 107 - CodeF17 Code = 108 - CodeF18 Code = 109 - CodeF19 Code = 110 - CodeF20 Code = 111 - CodeF21 Code = 112 - CodeF22 Code = 113 - CodeF23 Code = 114 - CodeF24 Code = 115 - - CodeHelp Code = 117 - - CodeMute Code = 127 - CodeVolumeUp Code = 128 - CodeVolumeDown Code = 129 - - CodeLeftControl Code = 224 - CodeLeftShift Code = 225 - CodeLeftAlt Code = 226 - CodeLeftGUI Code = 227 - CodeRightControl Code = 228 - CodeRightShift Code = 229 - CodeRightAlt Code = 230 - CodeRightGUI Code = 231 - - // The following codes are not part of the standard USB HID Usage IDs for - // keyboards. See http://www.usb.org/developers/hidpage/Hut1_12v2.pdf - // - // Usage IDs are uint16s, so these non-standard values start at 0x10000. - - // CodeCompose is the Code for a compose key, sometimes called a multi key, - // used to input non-ASCII characters such as ñ being composed of n and ~. - // - // See https://en.wikipedia.org/wiki/Compose_key - CodeCompose Code = 0x10000 -) - -// TODO: Given we use runes outside the unicode space, should we provide a -// printing function? Related: it's a little unfortunate that printing a -// key.Event with %v gives not very readable output like: -// {100 7 key.Modifiers() Press} - -var mods = [...]struct { - m Modifiers - s string -}{ - {ModShift, "Shift"}, - {ModControl, "Control"}, - {ModAlt, "Alt"}, - {ModMeta, "Meta"}, -} - -func (m Modifiers) String() string { - var match []string - for _, mod := range mods { - if mod.m&m != 0 { - match = append(match, mod.s) - } - } - return "key.Modifiers(" + strings.Join(match, "|") + ")" -} - -func (d Direction) String() string { - switch d { - case DirNone: - return "None" - case DirPress: - return "Press" - case DirRelease: - return "Release" - default: - return fmt.Sprintf("key.Direction(%d)", d) - } -} diff --git a/vendor/golang.org/x/mobile/event/lifecycle/lifecycle.go b/vendor/golang.org/x/mobile/event/lifecycle/lifecycle.go deleted file mode 100644 index 4c58858..0000000 --- a/vendor/golang.org/x/mobile/event/lifecycle/lifecycle.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package lifecycle defines an event for an app's lifecycle. -// -// The app lifecycle consists of moving back and forth between an ordered -// sequence of stages. For example, being at a stage greater than or equal to -// StageVisible means that the app is visible on the screen. -// -// A lifecycle event is a change from one stage to another, which crosses every -// intermediate stage. For example, changing from StageAlive to StageFocused -// implicitly crosses StageVisible. -// -// Crosses can be in a positive or negative direction. A positive crossing of -// StageFocused means that the app has gained the focus. A negative crossing -// means it has lost the focus. -// -// See the golang.org/x/mobile/app package for details on the event model. -package lifecycle // import "golang.org/x/mobile/event/lifecycle" - -import ( - "fmt" -) - -// Cross is whether a lifecycle stage was crossed. -type Cross uint32 - -func (c Cross) String() string { - switch c { - case CrossOn: - return "on" - case CrossOff: - return "off" - } - return "none" -} - -const ( - CrossNone Cross = 0 - CrossOn Cross = 1 - CrossOff Cross = 2 -) - -// Event is a lifecycle change from an old stage to a new stage. -type Event struct { - From, To Stage - - // DrawContext is the state used for painting, if any is valid. - // - // For OpenGL apps, a non-nil DrawContext is a gl.Context. - // - // TODO: make this an App method if we move away from an event channel? - DrawContext interface{} -} - -func (e Event) String() string { - return fmt.Sprintf("lifecycle.Event{From:%v, To:%v, DrawContext:%v}", e.From, e.To, e.DrawContext) -} - -// Crosses reports whether the transition from From to To crosses the stage s: -// - It returns CrossOn if it does, and the lifecycle change is positive. -// - It returns CrossOff if it does, and the lifecycle change is negative. -// - Otherwise, it returns CrossNone. -// -// See the documentation for Stage for more discussion of positive and negative -// crosses. -func (e Event) Crosses(s Stage) Cross { - switch { - case e.From < s && e.To >= s: - return CrossOn - case e.From >= s && e.To < s: - return CrossOff - } - return CrossNone -} - -// Stage is a stage in the app's lifecycle. The values are ordered, so that a -// lifecycle change from stage From to stage To implicitly crosses every stage -// in the range (min, max], exclusive on the low end and inclusive on the high -// end, where min is the minimum of From and To, and max is the maximum. -// -// The documentation for individual stages talk about positive and negative -// crosses. A positive lifecycle change is one where its From stage is less -// than its To stage. Similarly, a negative lifecycle change is one where From -// is greater than To. Thus, a positive lifecycle change crosses every stage in -// the range (From, To] in increasing order, and a negative lifecycle change -// crosses every stage in the range (To, From] in decreasing order. -type Stage uint32 - -// TODO: how does iOS map to these stages? What do cross-platform mobile -// abstractions do? - -const ( - // StageDead is the zero stage. No lifecycle change crosses this stage, - // but: - // - A positive change from this stage is the very first lifecycle change. - // - A negative change to this stage is the very last lifecycle change. - StageDead Stage = iota - - // StageAlive means that the app is alive. - // - A positive cross means that the app has been created. - // - A negative cross means that the app is being destroyed. - // Each cross, either from or to StageDead, will occur only once. - // On Android, these correspond to onCreate and onDestroy. - StageAlive - - // StageVisible means that the app window is visible. - // - A positive cross means that the app window has become visible. - // - A negative cross means that the app window has become invisible. - // On Android, these correspond to onStart and onStop. - // On Desktop, an app window can become invisible if e.g. it is minimized, - // unmapped, or not on a visible workspace. - StageVisible - - // StageFocused means that the app window has the focus. - // - A positive cross means that the app window has gained the focus. - // - A negative cross means that the app window has lost the focus. - // On Android, these correspond to onResume and onFreeze. - StageFocused -) - -func (s Stage) String() string { - switch s { - case StageDead: - return "StageDead" - case StageAlive: - return "StageAlive" - case StageVisible: - return "StageVisible" - case StageFocused: - return "StageFocused" - default: - return fmt.Sprintf("lifecycle.Stage(%d)", s) - } -} diff --git a/vendor/golang.org/x/mobile/event/mouse/mouse.go b/vendor/golang.org/x/mobile/event/mouse/mouse.go deleted file mode 100644 index eec2fc0..0000000 --- a/vendor/golang.org/x/mobile/event/mouse/mouse.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package mouse defines an event for mouse input. -// -// See the golang.org/x/mobile/app package for details on the event model. -package mouse // import "golang.org/x/mobile/event/mouse" - -import ( - "fmt" - - "golang.org/x/mobile/event/key" -) - -// Event is a mouse event. -type Event struct { - // X and Y are the mouse location, in pixels. - X, Y float32 - - // Button is the mouse button being pressed or released. Its value may be - // zero, for a mouse move or drag without any button change. - Button Button - - // TODO: have a field to hold what other buttons are down, for detecting - // drags or button-chords. - - // Modifiers is a bitmask representing a set of modifier keys: - // key.ModShift, key.ModAlt, etc. - Modifiers key.Modifiers - - // Direction is the direction of the mouse event: DirPress, DirRelease, - // or DirNone (for mouse moves or drags). - Direction Direction - - // TODO: add a Device ID, for multiple input devices? - // TODO: add a time.Time? -} - -// Button is a mouse button. -type Button int32 - -// IsWheel reports whether the button is for a scroll wheel. -func (b Button) IsWheel() bool { - return b < 0 -} - -// TODO: have a separate axis concept for wheel up/down? How does that relate -// to joystick events? - -const ( - ButtonNone Button = +0 - ButtonLeft Button = +1 - ButtonMiddle Button = +2 - ButtonRight Button = +3 - - ButtonWheelUp Button = -1 - ButtonWheelDown Button = -2 - ButtonWheelLeft Button = -3 - ButtonWheelRight Button = -4 -) - -// Direction is the direction of the mouse event. -type Direction uint8 - -const ( - DirNone Direction = 0 - DirPress Direction = 1 - DirRelease Direction = 2 - // DirStep is a simultaneous press and release, such as a single step of a - // mouse wheel. - // - // Its value equals DirPress | DirRelease. - DirStep Direction = 3 -) - -func (d Direction) String() string { - switch d { - case DirNone: - return "None" - case DirPress: - return "Press" - case DirRelease: - return "Release" - case DirStep: - return "Step" - default: - return fmt.Sprintf("mouse.Direction(%d)", d) - } -} diff --git a/vendor/golang.org/x/mobile/event/paint/paint.go b/vendor/golang.org/x/mobile/event/paint/paint.go deleted file mode 100644 index 0f24b1a..0000000 --- a/vendor/golang.org/x/mobile/event/paint/paint.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package paint defines an event for the app being ready to paint. -// -// See the golang.org/x/mobile/app package for details on the event model. -package paint // import "golang.org/x/mobile/event/paint" - -// Event indicates that the app is ready to paint the next frame of the GUI. -// -// A frame is completed by calling the App's Publish method. -type Event struct { - // External is true for paint events sent by the screen driver. - // - // An external event may be sent at any time in response to an - // operating system event, for example the window opened, was - // resized, or the screen memory was lost. - // - // Programs actively drawing to the screen as fast as vsync allows - // should ignore external paint events to avoid a backlog of paint - // events building up. - External bool -} diff --git a/vendor/golang.org/x/mobile/event/size/size.go b/vendor/golang.org/x/mobile/event/size/size.go deleted file mode 100644 index f396728..0000000 --- a/vendor/golang.org/x/mobile/event/size/size.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package size defines an event for the dimensions, physical resolution and -// orientation of the app's window. -// -// See the golang.org/x/mobile/app package for details on the event model. -package size // import "golang.org/x/mobile/event/size" - -import ( - "image" - - "golang.org/x/mobile/geom" -) - -// Event holds the dimensions, physical resolution and orientation of the app's -// window. -type Event struct { - // WidthPx and HeightPx are the window's dimensions in pixels. - WidthPx, HeightPx int - - // WidthPt and HeightPt are the window's physical dimensions in points - // (1/72 of an inch). - // - // The values are based on PixelsPerPt and are therefore approximate, as - // per the comment on PixelsPerPt. - WidthPt, HeightPt geom.Pt - - // PixelsPerPt is the window's physical resolution. It is the number of - // pixels in a single geom.Pt, from the golang.org/x/mobile/geom package. - // - // There are a wide variety of pixel densities in existing phones and - // tablets, so apps should be written to expect various non-integer - // PixelsPerPt values. In general, work in geom.Pt. - // - // The value is approximate, in that the OS, drivers or hardware may report - // approximate or quantized values. An N x N pixel square should be roughly - // 1 square inch for N = int(PixelsPerPt * 72), although different square - // lengths (in pixels) might be closer to 1 inch in practice. Nonetheless, - // this PixelsPerPt value should be consistent with e.g. the ratio of - // WidthPx to WidthPt. - PixelsPerPt float32 - - // Orientation is the orientation of the device screen. - Orientation Orientation -} - -// Size returns the window's size in pixels, at the time this size event was -// sent. -func (e Event) Size() image.Point { - return image.Point{e.WidthPx, e.HeightPx} -} - -// Bounds returns the window's bounds in pixels, at the time this size event -// was sent. -// -// The top-left pixel is always (0, 0). The bottom-right pixel is given by the -// width and height. -func (e Event) Bounds() image.Rectangle { - return image.Rectangle{Max: image.Point{e.WidthPx, e.HeightPx}} -} - -// Orientation is the orientation of the device screen. -type Orientation int - -const ( - // OrientationUnknown means device orientation cannot be determined. - // - // Equivalent on Android to Configuration.ORIENTATION_UNKNOWN - // and on iOS to: - // UIDeviceOrientationUnknown - // UIDeviceOrientationFaceUp - // UIDeviceOrientationFaceDown - OrientationUnknown Orientation = iota - - // OrientationPortrait is a device oriented so it is tall and thin. - // - // Equivalent on Android to Configuration.ORIENTATION_PORTRAIT - // and on iOS to: - // UIDeviceOrientationPortrait - // UIDeviceOrientationPortraitUpsideDown - OrientationPortrait - - // OrientationLandscape is a device oriented so it is short and wide. - // - // Equivalent on Android to Configuration.ORIENTATION_LANDSCAPE - // and on iOS to: - // UIDeviceOrientationLandscapeLeft - // UIDeviceOrientationLandscapeRight - OrientationLandscape -) diff --git a/vendor/golang.org/x/mobile/event/touch/touch.go b/vendor/golang.org/x/mobile/event/touch/touch.go deleted file mode 100644 index c91967b..0000000 --- a/vendor/golang.org/x/mobile/event/touch/touch.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package touch defines an event for touch input. -// -// See the golang.org/x/mobile/app package for details on the event model. -package touch // import "golang.org/x/mobile/event/touch" - -// The best source on android input events is the NDK: include/android/input.h -// -// iOS event handling guide: -// https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS - -import ( - "fmt" -) - -// Event is a touch event. -type Event struct { - // X and Y are the touch location, in pixels. - X, Y float32 - - // Sequence is the sequence number. The same number is shared by all events - // in a sequence. A sequence begins with a single TypeBegin, is followed by - // zero or more TypeMoves, and ends with a single TypeEnd. A Sequence - // distinguishes concurrent sequences but its value is subsequently reused. - Sequence Sequence - - // Type is the touch type. - Type Type -} - -// Sequence identifies a sequence of touch events. -type Sequence int64 - -// Type describes the type of a touch event. -type Type byte - -const ( - // TypeBegin is a user first touching the device. - // - // On Android, this is a AMOTION_EVENT_ACTION_DOWN. - // On iOS, this is a call to touchesBegan. - TypeBegin Type = iota - - // TypeMove is a user dragging across the device. - // - // A TypeMove is delivered between a TypeBegin and TypeEnd. - // - // On Android, this is a AMOTION_EVENT_ACTION_MOVE. - // On iOS, this is a call to touchesMoved. - TypeMove - - // TypeEnd is a user no longer touching the device. - // - // On Android, this is a AMOTION_EVENT_ACTION_UP. - // On iOS, this is a call to touchesEnded. - TypeEnd -) - -func (t Type) String() string { - switch t { - case TypeBegin: - return "begin" - case TypeMove: - return "move" - case TypeEnd: - return "end" - } - return fmt.Sprintf("touch.Type(%d)", t) -} diff --git a/vendor/golang.org/x/mobile/geom/geom.go b/vendor/golang.org/x/mobile/geom/geom.go deleted file mode 100644 index 23cf67b..0000000 --- a/vendor/golang.org/x/mobile/geom/geom.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package geom defines a two-dimensional coordinate system. - -The coordinate system is based on an left-handed Cartesian plane. -That is, X increases to the right and Y increases down. For (x,y), - - (0,0) → (1,0) - ↓ ↘ - (0,1) (1,1) - -The display window places the origin (0, 0) in the upper-left corner of -the screen. Positions on the plane are measured in typographic points, -1/72 of an inch, which is represented by the Pt type. - -Any interface that draws to the screen using types from the geom package -scales the number of pixels to maintain a Pt as 1/72 of an inch. -*/ -package geom // import "golang.org/x/mobile/geom" - -/* -Notes on the various underlying coordinate systems. - -Both Android and iOS (UIKit) use upper-left-origin coordinate systems -with for events, however they have different units. - -UIKit measures distance in points. A point is a single-pixel on a -pre-Retina display. UIKit maintains a scale factor that to turn points -into pixels. On current retina devices, the scale factor is 2.0. - -A UIKit point does not correspond to a fixed physical distance, as the -iPhone has a 163 DPI/PPI (326 PPI retina) display, and the iPad has a -132 PPI (264 retina) display. Points are 32-bit floats. - -Even though point is the official UIKit term, they are commonly called -pixels. Indeed, the units were equivalent until the retina display was -introduced. - -N.b. as a UIKit point is unrelated to a typographic point, it is not -related to this packages's Pt and Point types. - -More details about iOS drawing: - -https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/GraphicsDrawingOverview/GraphicsDrawingOverview.html - -Android uses pixels. Sub-pixel precision is possible, so pixels are -represented as 32-bit floats. The ACONFIGURATION_DENSITY enum provides -the screen DPI/PPI, which varies frequently between devices. - -It would be tempting to adopt the pixel, given the clear pixel/DPI split -in the core android events API. However, the plot thickens: - -http://developer.android.com/training/multiscreen/screendensities.html - -Android promotes the notion of a density-independent pixel in many of -their interfaces, often prefixed by "dp". 1dp is a real physical length, -as "independent" means it is assumed to be 1/160th of an inch and is -adjusted for the current screen. - -In addition, android has a scale-indepdendent pixel used for expressing -a user's preferred text size. The user text size preference is a useful -notion not yet expressed in the geom package. - -For the sake of clarity when working across platforms, the geom package -tries to put distance between it and the word pixel. -*/ - -import "fmt" - -// Pt is a length. -// -// The unit Pt is a typographical point, 1/72 of an inch (0.3527 mm). -// -// It can be be converted to a length in current device pixels by -// multiplying with PixelsPerPt after app initialization is complete. -type Pt float32 - -// Px converts the length to current device pixels. -func (p Pt) Px(pixelsPerPt float32) float32 { return float32(p) * pixelsPerPt } - -// String returns a string representation of p like "3.2pt". -func (p Pt) String() string { return fmt.Sprintf("%.2fpt", p) } - -// Point is a point in a two-dimensional plane. -type Point struct { - X, Y Pt -} - -// String returns a string representation of p like "(1.2,3.4)". -func (p Point) String() string { return fmt.Sprintf("(%.2f,%.2f)", p.X, p.Y) } - -// A Rectangle is region of points. -// The top-left point is Min, and the bottom-right point is Max. -type Rectangle struct { - Min, Max Point -} - -// String returns a string representation of r like "(3,4)-(6,5)". -func (r Rectangle) String() string { return r.Min.String() + "-" + r.Max.String() } diff --git a/vendor/golang.org/x/mobile/gl/consts.go b/vendor/golang.org/x/mobile/gl/consts.go deleted file mode 100644 index 370d0b8..0000000 --- a/vendor/golang.org/x/mobile/gl/consts.go +++ /dev/null @@ -1,657 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gl - -/* -Partially generated from the Khronos OpenGL API specification in XML -format, which is covered by the license: - - Copyright (c) 2013-2014 The Khronos Group Inc. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and/or associated documentation files (the - "Materials"), to deal in the Materials without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Materials, and to - permit persons to whom the Materials are furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Materials. - - THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. - -*/ - -const ( - POINTS = 0x0000 - LINES = 0x0001 - LINE_LOOP = 0x0002 - LINE_STRIP = 0x0003 - TRIANGLES = 0x0004 - TRIANGLE_STRIP = 0x0005 - TRIANGLE_FAN = 0x0006 - SRC_COLOR = 0x0300 - ONE_MINUS_SRC_COLOR = 0x0301 - SRC_ALPHA = 0x0302 - ONE_MINUS_SRC_ALPHA = 0x0303 - DST_ALPHA = 0x0304 - ONE_MINUS_DST_ALPHA = 0x0305 - DST_COLOR = 0x0306 - ONE_MINUS_DST_COLOR = 0x0307 - SRC_ALPHA_SATURATE = 0x0308 - FUNC_ADD = 0x8006 - BLEND_EQUATION = 0x8009 - BLEND_EQUATION_RGB = 0x8009 - BLEND_EQUATION_ALPHA = 0x883D - FUNC_SUBTRACT = 0x800A - FUNC_REVERSE_SUBTRACT = 0x800B - BLEND_DST_RGB = 0x80C8 - BLEND_SRC_RGB = 0x80C9 - BLEND_DST_ALPHA = 0x80CA - BLEND_SRC_ALPHA = 0x80CB - CONSTANT_COLOR = 0x8001 - ONE_MINUS_CONSTANT_COLOR = 0x8002 - CONSTANT_ALPHA = 0x8003 - ONE_MINUS_CONSTANT_ALPHA = 0x8004 - BLEND_COLOR = 0x8005 - ARRAY_BUFFER = 0x8892 - ELEMENT_ARRAY_BUFFER = 0x8893 - ARRAY_BUFFER_BINDING = 0x8894 - ELEMENT_ARRAY_BUFFER_BINDING = 0x8895 - STREAM_DRAW = 0x88E0 - STATIC_DRAW = 0x88E4 - DYNAMIC_DRAW = 0x88E8 - BUFFER_SIZE = 0x8764 - BUFFER_USAGE = 0x8765 - CURRENT_VERTEX_ATTRIB = 0x8626 - FRONT = 0x0404 - BACK = 0x0405 - FRONT_AND_BACK = 0x0408 - TEXTURE_2D = 0x0DE1 - CULL_FACE = 0x0B44 - BLEND = 0x0BE2 - DITHER = 0x0BD0 - STENCIL_TEST = 0x0B90 - DEPTH_TEST = 0x0B71 - SCISSOR_TEST = 0x0C11 - POLYGON_OFFSET_FILL = 0x8037 - SAMPLE_ALPHA_TO_COVERAGE = 0x809E - SAMPLE_COVERAGE = 0x80A0 - INVALID_ENUM = 0x0500 - INVALID_VALUE = 0x0501 - INVALID_OPERATION = 0x0502 - OUT_OF_MEMORY = 0x0505 - CW = 0x0900 - CCW = 0x0901 - LINE_WIDTH = 0x0B21 - ALIASED_POINT_SIZE_RANGE = 0x846D - ALIASED_LINE_WIDTH_RANGE = 0x846E - CULL_FACE_MODE = 0x0B45 - FRONT_FACE = 0x0B46 - DEPTH_RANGE = 0x0B70 - DEPTH_WRITEMASK = 0x0B72 - DEPTH_CLEAR_VALUE = 0x0B73 - DEPTH_FUNC = 0x0B74 - STENCIL_CLEAR_VALUE = 0x0B91 - STENCIL_FUNC = 0x0B92 - STENCIL_FAIL = 0x0B94 - STENCIL_PASS_DEPTH_FAIL = 0x0B95 - STENCIL_PASS_DEPTH_PASS = 0x0B96 - STENCIL_REF = 0x0B97 - STENCIL_VALUE_MASK = 0x0B93 - STENCIL_WRITEMASK = 0x0B98 - STENCIL_BACK_FUNC = 0x8800 - STENCIL_BACK_FAIL = 0x8801 - STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802 - STENCIL_BACK_PASS_DEPTH_PASS = 0x8803 - STENCIL_BACK_REF = 0x8CA3 - STENCIL_BACK_VALUE_MASK = 0x8CA4 - STENCIL_BACK_WRITEMASK = 0x8CA5 - VIEWPORT = 0x0BA2 - SCISSOR_BOX = 0x0C10 - COLOR_CLEAR_VALUE = 0x0C22 - COLOR_WRITEMASK = 0x0C23 - UNPACK_ALIGNMENT = 0x0CF5 - PACK_ALIGNMENT = 0x0D05 - MAX_TEXTURE_SIZE = 0x0D33 - MAX_VIEWPORT_DIMS = 0x0D3A - SUBPIXEL_BITS = 0x0D50 - RED_BITS = 0x0D52 - GREEN_BITS = 0x0D53 - BLUE_BITS = 0x0D54 - ALPHA_BITS = 0x0D55 - DEPTH_BITS = 0x0D56 - STENCIL_BITS = 0x0D57 - POLYGON_OFFSET_UNITS = 0x2A00 - POLYGON_OFFSET_FACTOR = 0x8038 - TEXTURE_BINDING_2D = 0x8069 - SAMPLE_BUFFERS = 0x80A8 - SAMPLES = 0x80A9 - SAMPLE_COVERAGE_VALUE = 0x80AA - SAMPLE_COVERAGE_INVERT = 0x80AB - NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2 - COMPRESSED_TEXTURE_FORMATS = 0x86A3 - DONT_CARE = 0x1100 - FASTEST = 0x1101 - NICEST = 0x1102 - GENERATE_MIPMAP_HINT = 0x8192 - BYTE = 0x1400 - UNSIGNED_BYTE = 0x1401 - SHORT = 0x1402 - UNSIGNED_SHORT = 0x1403 - INT = 0x1404 - UNSIGNED_INT = 0x1405 - FLOAT = 0x1406 - FIXED = 0x140C - DEPTH_COMPONENT = 0x1902 - ALPHA = 0x1906 - RGB = 0x1907 - RGBA = 0x1908 - LUMINANCE = 0x1909 - LUMINANCE_ALPHA = 0x190A - UNSIGNED_SHORT_4_4_4_4 = 0x8033 - UNSIGNED_SHORT_5_5_5_1 = 0x8034 - UNSIGNED_SHORT_5_6_5 = 0x8363 - MAX_VERTEX_ATTRIBS = 0x8869 - MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB - MAX_VARYING_VECTORS = 0x8DFC - MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D - MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C - MAX_TEXTURE_IMAGE_UNITS = 0x8872 - MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD - SHADER_TYPE = 0x8B4F - DELETE_STATUS = 0x8B80 - LINK_STATUS = 0x8B82 - VALIDATE_STATUS = 0x8B83 - ATTACHED_SHADERS = 0x8B85 - ACTIVE_UNIFORMS = 0x8B86 - ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87 - ACTIVE_ATTRIBUTES = 0x8B89 - ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A - SHADING_LANGUAGE_VERSION = 0x8B8C - CURRENT_PROGRAM = 0x8B8D - NEVER = 0x0200 - LESS = 0x0201 - EQUAL = 0x0202 - LEQUAL = 0x0203 - GREATER = 0x0204 - NOTEQUAL = 0x0205 - GEQUAL = 0x0206 - ALWAYS = 0x0207 - KEEP = 0x1E00 - REPLACE = 0x1E01 - INCR = 0x1E02 - DECR = 0x1E03 - INVERT = 0x150A - INCR_WRAP = 0x8507 - DECR_WRAP = 0x8508 - VENDOR = 0x1F00 - RENDERER = 0x1F01 - VERSION = 0x1F02 - EXTENSIONS = 0x1F03 - NEAREST = 0x2600 - LINEAR = 0x2601 - NEAREST_MIPMAP_NEAREST = 0x2700 - LINEAR_MIPMAP_NEAREST = 0x2701 - NEAREST_MIPMAP_LINEAR = 0x2702 - LINEAR_MIPMAP_LINEAR = 0x2703 - TEXTURE_MAG_FILTER = 0x2800 - TEXTURE_MIN_FILTER = 0x2801 - TEXTURE_WRAP_S = 0x2802 - TEXTURE_WRAP_T = 0x2803 - TEXTURE = 0x1702 - TEXTURE_CUBE_MAP = 0x8513 - TEXTURE_BINDING_CUBE_MAP = 0x8514 - TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515 - TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516 - TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517 - TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518 - TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519 - TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A - MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C - TEXTURE0 = 0x84C0 - TEXTURE1 = 0x84C1 - TEXTURE2 = 0x84C2 - TEXTURE3 = 0x84C3 - TEXTURE4 = 0x84C4 - TEXTURE5 = 0x84C5 - TEXTURE6 = 0x84C6 - TEXTURE7 = 0x84C7 - TEXTURE8 = 0x84C8 - TEXTURE9 = 0x84C9 - TEXTURE10 = 0x84CA - TEXTURE11 = 0x84CB - TEXTURE12 = 0x84CC - TEXTURE13 = 0x84CD - TEXTURE14 = 0x84CE - TEXTURE15 = 0x84CF - TEXTURE16 = 0x84D0 - TEXTURE17 = 0x84D1 - TEXTURE18 = 0x84D2 - TEXTURE19 = 0x84D3 - TEXTURE20 = 0x84D4 - TEXTURE21 = 0x84D5 - TEXTURE22 = 0x84D6 - TEXTURE23 = 0x84D7 - TEXTURE24 = 0x84D8 - TEXTURE25 = 0x84D9 - TEXTURE26 = 0x84DA - TEXTURE27 = 0x84DB - TEXTURE28 = 0x84DC - TEXTURE29 = 0x84DD - TEXTURE30 = 0x84DE - TEXTURE31 = 0x84DF - ACTIVE_TEXTURE = 0x84E0 - REPEAT = 0x2901 - CLAMP_TO_EDGE = 0x812F - MIRRORED_REPEAT = 0x8370 - VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622 - VERTEX_ATTRIB_ARRAY_SIZE = 0x8623 - VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624 - VERTEX_ATTRIB_ARRAY_TYPE = 0x8625 - VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A - VERTEX_ATTRIB_ARRAY_POINTER = 0x8645 - VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F - IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A - IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B - COMPILE_STATUS = 0x8B81 - INFO_LOG_LENGTH = 0x8B84 - SHADER_SOURCE_LENGTH = 0x8B88 - SHADER_COMPILER = 0x8DFA - SHADER_BINARY_FORMATS = 0x8DF8 - NUM_SHADER_BINARY_FORMATS = 0x8DF9 - LOW_FLOAT = 0x8DF0 - MEDIUM_FLOAT = 0x8DF1 - HIGH_FLOAT = 0x8DF2 - LOW_INT = 0x8DF3 - MEDIUM_INT = 0x8DF4 - HIGH_INT = 0x8DF5 - FRAMEBUFFER = 0x8D40 - RENDERBUFFER = 0x8D41 - RGBA4 = 0x8056 - RGB5_A1 = 0x8057 - RGB565 = 0x8D62 - DEPTH_COMPONENT16 = 0x81A5 - STENCIL_INDEX8 = 0x8D48 - RENDERBUFFER_WIDTH = 0x8D42 - RENDERBUFFER_HEIGHT = 0x8D43 - RENDERBUFFER_INTERNAL_FORMAT = 0x8D44 - RENDERBUFFER_RED_SIZE = 0x8D50 - RENDERBUFFER_GREEN_SIZE = 0x8D51 - RENDERBUFFER_BLUE_SIZE = 0x8D52 - RENDERBUFFER_ALPHA_SIZE = 0x8D53 - RENDERBUFFER_DEPTH_SIZE = 0x8D54 - RENDERBUFFER_STENCIL_SIZE = 0x8D55 - FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0 - FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1 - FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2 - FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3 - COLOR_ATTACHMENT0 = 0x8CE0 - DEPTH_ATTACHMENT = 0x8D00 - STENCIL_ATTACHMENT = 0x8D20 - FRAMEBUFFER_COMPLETE = 0x8CD5 - FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6 - FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7 - FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9 - FRAMEBUFFER_UNSUPPORTED = 0x8CDD - FRAMEBUFFER_BINDING = 0x8CA6 - RENDERBUFFER_BINDING = 0x8CA7 - MAX_RENDERBUFFER_SIZE = 0x84E8 - INVALID_FRAMEBUFFER_OPERATION = 0x0506 -) - -const ( - DEPTH_BUFFER_BIT = 0x00000100 - STENCIL_BUFFER_BIT = 0x00000400 - COLOR_BUFFER_BIT = 0x00004000 -) - -const ( - FLOAT_VEC2 = 0x8B50 - FLOAT_VEC3 = 0x8B51 - FLOAT_VEC4 = 0x8B52 - INT_VEC2 = 0x8B53 - INT_VEC3 = 0x8B54 - INT_VEC4 = 0x8B55 - BOOL = 0x8B56 - BOOL_VEC2 = 0x8B57 - BOOL_VEC3 = 0x8B58 - BOOL_VEC4 = 0x8B59 - FLOAT_MAT2 = 0x8B5A - FLOAT_MAT3 = 0x8B5B - FLOAT_MAT4 = 0x8B5C - SAMPLER_2D = 0x8B5E - SAMPLER_CUBE = 0x8B60 -) - -const ( - FRAGMENT_SHADER = 0x8B30 - VERTEX_SHADER = 0x8B31 -) - -const ( - FALSE = 0 - TRUE = 1 - ZERO = 0 - ONE = 1 - NO_ERROR = 0 - NONE = 0 -) - -// GL ES 3.0 constants. -const ( - ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH = 0x8A35 - ACTIVE_UNIFORM_BLOCKS = 0x8A36 - ALREADY_SIGNALED = 0x911A - ANY_SAMPLES_PASSED = 0x8C2F - ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A - BLUE = 0x1905 - BUFFER_ACCESS_FLAGS = 0x911F - BUFFER_MAP_LENGTH = 0x9120 - BUFFER_MAP_OFFSET = 0x9121 - BUFFER_MAPPED = 0x88BC - BUFFER_MAP_POINTER = 0x88BD - COLOR = 0x1800 - COLOR_ATTACHMENT10 = 0x8CEA - COLOR_ATTACHMENT1 = 0x8CE1 - COLOR_ATTACHMENT11 = 0x8CEB - COLOR_ATTACHMENT12 = 0x8CEC - COLOR_ATTACHMENT13 = 0x8CED - COLOR_ATTACHMENT14 = 0x8CEE - COLOR_ATTACHMENT15 = 0x8CEF - COLOR_ATTACHMENT2 = 0x8CE2 - COLOR_ATTACHMENT3 = 0x8CE3 - COLOR_ATTACHMENT4 = 0x8CE4 - COLOR_ATTACHMENT5 = 0x8CE5 - COLOR_ATTACHMENT6 = 0x8CE6 - COLOR_ATTACHMENT7 = 0x8CE7 - COLOR_ATTACHMENT8 = 0x8CE8 - COLOR_ATTACHMENT9 = 0x8CE9 - COMPARE_REF_TO_TEXTURE = 0x884E - COMPRESSED_R11_EAC = 0x9270 - COMPRESSED_RG11_EAC = 0x9272 - COMPRESSED_RGB8_ETC2 = 0x9274 - COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276 - COMPRESSED_RGBA8_ETC2_EAC = 0x9278 - COMPRESSED_SIGNED_R11_EAC = 0x9271 - COMPRESSED_SIGNED_RG11_EAC = 0x9273 - COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279 - COMPRESSED_SRGB8_ETC2 = 0x9275 - COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277 - CONDITION_SATISFIED = 0x911C - COPY_READ_BUFFER = 0x8F36 - COPY_READ_BUFFER_BINDING = 0x8F36 - COPY_WRITE_BUFFER = 0x8F37 - COPY_WRITE_BUFFER_BINDING = 0x8F37 - CURRENT_QUERY = 0x8865 - DEPTH = 0x1801 - DEPTH24_STENCIL8 = 0x88F0 - DEPTH32F_STENCIL8 = 0x8CAD - DEPTH_COMPONENT24 = 0x81A6 - DEPTH_COMPONENT32F = 0x8CAC - DEPTH_STENCIL = 0x84F9 - DEPTH_STENCIL_ATTACHMENT = 0x821A - DRAW_BUFFER0 = 0x8825 - DRAW_BUFFER10 = 0x882F - DRAW_BUFFER1 = 0x8826 - DRAW_BUFFER11 = 0x8830 - DRAW_BUFFER12 = 0x8831 - DRAW_BUFFER13 = 0x8832 - DRAW_BUFFER14 = 0x8833 - DRAW_BUFFER15 = 0x8834 - DRAW_BUFFER2 = 0x8827 - DRAW_BUFFER3 = 0x8828 - DRAW_BUFFER4 = 0x8829 - DRAW_BUFFER5 = 0x882A - DRAW_BUFFER6 = 0x882B - DRAW_BUFFER7 = 0x882C - DRAW_BUFFER8 = 0x882D - DRAW_BUFFER9 = 0x882E - DRAW_FRAMEBUFFER = 0x8CA9 - DRAW_FRAMEBUFFER_BINDING = 0x8CA6 - DYNAMIC_COPY = 0x88EA - DYNAMIC_READ = 0x88E9 - FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD - FLOAT_MAT2x3 = 0x8B65 - FLOAT_MAT2x4 = 0x8B66 - FLOAT_MAT3x2 = 0x8B67 - FLOAT_MAT3x4 = 0x8B68 - FLOAT_MAT4x2 = 0x8B69 - FLOAT_MAT4x3 = 0x8B6A - FRAGMENT_SHADER_DERIVATIVE_HINT = 0x8B8B - FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = 0x8215 - FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = 0x8214 - FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210 - FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = 0x8211 - FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = 0x8216 - FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = 0x8213 - FRAMEBUFFER_ATTACHMENT_RED_SIZE = 0x8212 - FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = 0x8217 - FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 0x8CD4 - FRAMEBUFFER_DEFAULT = 0x8218 - FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56 - FRAMEBUFFER_UNDEFINED = 0x8219 - GREEN = 0x1904 - HALF_FLOAT = 0x140B - INT_2_10_10_10_REV = 0x8D9F - INTERLEAVED_ATTRIBS = 0x8C8C - INT_SAMPLER_2D = 0x8DCA - INT_SAMPLER_2D_ARRAY = 0x8DCF - INT_SAMPLER_3D = 0x8DCB - INT_SAMPLER_CUBE = 0x8DCC - INVALID_INDEX = 0xFFFFFFFF - MAJOR_VERSION = 0x821B - MAP_FLUSH_EXPLICIT_BIT = 0x0010 - MAP_INVALIDATE_BUFFER_BIT = 0x0008 - MAP_INVALIDATE_RANGE_BIT = 0x0004 - MAP_READ_BIT = 0x0001 - MAP_UNSYNCHRONIZED_BIT = 0x0020 - MAP_WRITE_BIT = 0x0002 - MAX = 0x8008 - MAX_3D_TEXTURE_SIZE = 0x8073 - MAX_ARRAY_TEXTURE_LAYERS = 0x88FF - MAX_COLOR_ATTACHMENTS = 0x8CDF - MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33 - MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E - MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31 - MAX_DRAW_BUFFERS = 0x8824 - MAX_ELEMENT_INDEX = 0x8D6B - MAX_ELEMENTS_INDICES = 0x80E9 - MAX_ELEMENTS_VERTICES = 0x80E8 - MAX_FRAGMENT_INPUT_COMPONENTS = 0x9125 - MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D - MAX_FRAGMENT_UNIFORM_COMPONENTS = 0x8B49 - MAX_PROGRAM_TEXEL_OFFSET = 0x8905 - MAX_SAMPLES = 0x8D57 - MAX_SERVER_WAIT_TIMEOUT = 0x9111 - MAX_TEXTURE_LOD_BIAS = 0x84FD - MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 0x8C8A - MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B - MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 0x8C80 - MAX_UNIFORM_BLOCK_SIZE = 0x8A30 - MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F - MAX_VARYING_COMPONENTS = 0x8B4B - MAX_VERTEX_OUTPUT_COMPONENTS = 0x9122 - MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B - MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A - MIN = 0x8007 - MINOR_VERSION = 0x821C - MIN_PROGRAM_TEXEL_OFFSET = 0x8904 - NUM_EXTENSIONS = 0x821D - NUM_PROGRAM_BINARY_FORMATS = 0x87FE - NUM_SAMPLE_COUNTS = 0x9380 - OBJECT_TYPE = 0x9112 - PACK_ROW_LENGTH = 0x0D02 - PACK_SKIP_PIXELS = 0x0D04 - PACK_SKIP_ROWS = 0x0D03 - PIXEL_PACK_BUFFER = 0x88EB - PIXEL_PACK_BUFFER_BINDING = 0x88ED - PIXEL_UNPACK_BUFFER = 0x88EC - PIXEL_UNPACK_BUFFER_BINDING = 0x88EF - PRIMITIVE_RESTART_FIXED_INDEX = 0x8D69 - PROGRAM_BINARY_FORMATS = 0x87FF - PROGRAM_BINARY_LENGTH = 0x8741 - PROGRAM_BINARY_RETRIEVABLE_HINT = 0x8257 - QUERY_RESULT = 0x8866 - QUERY_RESULT_AVAILABLE = 0x8867 - R11F_G11F_B10F = 0x8C3A - R16F = 0x822D - R16I = 0x8233 - R16UI = 0x8234 - R32F = 0x822E - R32I = 0x8235 - R32UI = 0x8236 - R8 = 0x8229 - R8I = 0x8231 - R8_SNORM = 0x8F94 - R8UI = 0x8232 - RASTERIZER_DISCARD = 0x8C89 - READ_BUFFER = 0x0C02 - READ_FRAMEBUFFER = 0x8CA8 - READ_FRAMEBUFFER_BINDING = 0x8CAA - RED = 0x1903 - RED_INTEGER = 0x8D94 - RENDERBUFFER_SAMPLES = 0x8CAB - RG = 0x8227 - RG16F = 0x822F - RG16I = 0x8239 - RG16UI = 0x823A - RG32F = 0x8230 - RG32I = 0x823B - RG32UI = 0x823C - RG8 = 0x822B - RG8I = 0x8237 - RG8_SNORM = 0x8F95 - RG8UI = 0x8238 - RGB10_A2 = 0x8059 - RGB10_A2UI = 0x906F - RGB16F = 0x881B - RGB16I = 0x8D89 - RGB16UI = 0x8D77 - RGB32F = 0x8815 - RGB32I = 0x8D83 - RGB32UI = 0x8D71 - RGB8 = 0x8051 - RGB8I = 0x8D8F - RGB8_SNORM = 0x8F96 - RGB8UI = 0x8D7D - RGB9_E5 = 0x8C3D - RGBA16F = 0x881A - RGBA16I = 0x8D88 - RGBA16UI = 0x8D76 - RGBA32F = 0x8814 - RGBA32I = 0x8D82 - RGBA32UI = 0x8D70 - RGBA8 = 0x8058 - RGBA8I = 0x8D8E - RGBA8_SNORM = 0x8F97 - RGBA8UI = 0x8D7C - RGBA_INTEGER = 0x8D99 - RGB_INTEGER = 0x8D98 - RG_INTEGER = 0x8228 - SAMPLER_2D_ARRAY = 0x8DC1 - SAMPLER_2D_ARRAY_SHADOW = 0x8DC4 - SAMPLER_2D_SHADOW = 0x8B62 - SAMPLER_3D = 0x8B5F - SAMPLER_BINDING = 0x8919 - SAMPLER_CUBE_SHADOW = 0x8DC5 - SEPARATE_ATTRIBS = 0x8C8D - SIGNALED = 0x9119 - SIGNED_NORMALIZED = 0x8F9C - SRGB = 0x8C40 - SRGB8 = 0x8C41 - SRGB8_ALPHA8 = 0x8C43 - STATIC_COPY = 0x88E6 - STATIC_READ = 0x88E5 - STENCIL = 0x1802 - STREAM_COPY = 0x88E2 - STREAM_READ = 0x88E1 - SYNC_CONDITION = 0x9113 - SYNC_FENCE = 0x9116 - SYNC_FLAGS = 0x9115 - SYNC_FLUSH_COMMANDS_BIT = 0x00000001 - SYNC_GPU_COMMANDS_COMPLETE = 0x9117 - SYNC_STATUS = 0x9114 - TEXTURE_2D_ARRAY = 0x8C1A - TEXTURE_3D = 0x806F - TEXTURE_BASE_LEVEL = 0x813C - TEXTURE_BINDING_2D_ARRAY = 0x8C1D - TEXTURE_BINDING_3D = 0x806A - TEXTURE_COMPARE_FUNC = 0x884D - TEXTURE_COMPARE_MODE = 0x884C - TEXTURE_IMMUTABLE_FORMAT = 0x912F - TEXTURE_IMMUTABLE_LEVELS = 0x82DF - TEXTURE_MAX_LEVEL = 0x813D - TEXTURE_MAX_LOD = 0x813B - TEXTURE_MIN_LOD = 0x813A - TEXTURE_SWIZZLE_A = 0x8E45 - TEXTURE_SWIZZLE_B = 0x8E44 - TEXTURE_SWIZZLE_G = 0x8E43 - TEXTURE_SWIZZLE_R = 0x8E42 - TEXTURE_WRAP_R = 0x8072 - TIMEOUT_EXPIRED = 0x911B - TIMEOUT_IGNORED = 0xFFFFFFFFFFFFFFFF - TRANSFORM_FEEDBACK = 0x8E22 - TRANSFORM_FEEDBACK_ACTIVE = 0x8E24 - TRANSFORM_FEEDBACK_BINDING = 0x8E25 - TRANSFORM_FEEDBACK_BUFFER = 0x8C8E - TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F - TRANSFORM_FEEDBACK_BUFFER_MODE = 0x8C7F - TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85 - TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84 - TRANSFORM_FEEDBACK_PAUSED = 0x8E23 - TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88 - TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH = 0x8C76 - TRANSFORM_FEEDBACK_VARYINGS = 0x8C83 - UNIFORM_ARRAY_STRIDE = 0x8A3C - UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8A43 - UNIFORM_BLOCK_ACTIVE_UNIFORMS = 0x8A42 - UNIFORM_BLOCK_BINDING = 0x8A3F - UNIFORM_BLOCK_DATA_SIZE = 0x8A40 - UNIFORM_BLOCK_INDEX = 0x8A3A - UNIFORM_BLOCK_NAME_LENGTH = 0x8A41 - UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46 - UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8A44 - UNIFORM_BUFFER = 0x8A11 - UNIFORM_BUFFER_BINDING = 0x8A28 - UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34 - UNIFORM_BUFFER_SIZE = 0x8A2A - UNIFORM_BUFFER_START = 0x8A29 - UNIFORM_IS_ROW_MAJOR = 0x8A3E - UNIFORM_MATRIX_STRIDE = 0x8A3D - UNIFORM_NAME_LENGTH = 0x8A39 - UNIFORM_OFFSET = 0x8A3B - UNIFORM_SIZE = 0x8A38 - UNIFORM_TYPE = 0x8A37 - UNPACK_IMAGE_HEIGHT = 0x806E - UNPACK_ROW_LENGTH = 0x0CF2 - UNPACK_SKIP_IMAGES = 0x806D - UNPACK_SKIP_PIXELS = 0x0CF4 - UNPACK_SKIP_ROWS = 0x0CF3 - UNSIGNALED = 0x9118 - UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B - UNSIGNED_INT_2_10_10_10_REV = 0x8368 - UNSIGNED_INT_24_8 = 0x84FA - UNSIGNED_INT_5_9_9_9_REV = 0x8C3E - UNSIGNED_INT_SAMPLER_2D = 0x8DD2 - UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7 - UNSIGNED_INT_SAMPLER_3D = 0x8DD3 - UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4 - UNSIGNED_INT_VEC2 = 0x8DC6 - UNSIGNED_INT_VEC3 = 0x8DC7 - UNSIGNED_INT_VEC4 = 0x8DC8 - UNSIGNED_NORMALIZED = 0x8C17 - VERTEX_ARRAY_BINDING = 0x85B5 - VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE - VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD - WAIT_FAILED = 0x911D -) diff --git a/vendor/golang.org/x/mobile/gl/dll_windows.go b/vendor/golang.org/x/mobile/gl/dll_windows.go deleted file mode 100644 index 1afc5f8..0000000 --- a/vendor/golang.org/x/mobile/gl/dll_windows.go +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gl - -import ( - "archive/tar" - "compress/gzip" - "debug/pe" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "os" - "path/filepath" - "runtime" -) - -var debug = log.New(ioutil.Discard, "gl: ", log.LstdFlags) - -func downloadDLLs() (path string, err error) { - url := "https://dl.google.com/go/mobile/angle-bd3f8780b-" + runtime.GOARCH + ".tgz" - debug.Printf("downloading %s", url) - resp, err := http.Get(url) - if err != nil { - return "", fmt.Errorf("gl: %v", err) - } - defer func() { - err2 := resp.Body.Close() - if err == nil && err2 != nil { - err = fmt.Errorf("gl: error reading body from %v: %v", url, err2) - } - }() - if resp.StatusCode != http.StatusOK { - err := fmt.Errorf("gl: error fetching %v, status: %v", url, resp.Status) - return "", err - } - - r, err := gzip.NewReader(resp.Body) - if err != nil { - return "", fmt.Errorf("gl: error reading gzip from %v: %v", url, err) - } - tr := tar.NewReader(r) - var bytesGLESv2, bytesEGL, bytesD3DCompiler []byte - for { - header, err := tr.Next() - if err == io.EOF { - break - } - if err != nil { - return "", fmt.Errorf("gl: error reading tar from %v: %v", url, err) - } - switch header.Name { - case "angle-" + runtime.GOARCH + "/libglesv2.dll": - bytesGLESv2, err = ioutil.ReadAll(tr) - case "angle-" + runtime.GOARCH + "/libegl.dll": - bytesEGL, err = ioutil.ReadAll(tr) - case "angle-" + runtime.GOARCH + "/d3dcompiler_47.dll": - bytesD3DCompiler, err = ioutil.ReadAll(tr) - default: // skip - } - if err != nil { - return "", fmt.Errorf("gl: error reading %v from %v: %v", header.Name, url, err) - } - } - if len(bytesGLESv2) == 0 || len(bytesEGL) == 0 || len(bytesD3DCompiler) == 0 { - return "", fmt.Errorf("gl: did not find all DLLs in %v", url) - } - - writeDLLs := func(path string) error { - if err := ioutil.WriteFile(filepath.Join(path, "libglesv2.dll"), bytesGLESv2, 0755); err != nil { - return fmt.Errorf("gl: cannot install ANGLE: %v", err) - } - if err := ioutil.WriteFile(filepath.Join(path, "libegl.dll"), bytesEGL, 0755); err != nil { - return fmt.Errorf("gl: cannot install ANGLE: %v", err) - } - if err := ioutil.WriteFile(filepath.Join(path, "d3dcompiler_47.dll"), bytesD3DCompiler, 0755); err != nil { - return fmt.Errorf("gl: cannot install ANGLE: %v", err) - } - return nil - } - - // First, we attempt to install these DLLs in LOCALAPPDATA/Shiny. - // - // Traditionally we would use the system32 directory, but it is - // no longer writable by normal programs. - os.MkdirAll(appdataPath(), 0775) - if err := writeDLLs(appdataPath()); err == nil { - return appdataPath(), nil - } - debug.Printf("DLLs could not be written to %s", appdataPath()) - - // Second, install in GOPATH/pkg if it exists. - gopath := os.Getenv("GOPATH") - gopathpkg := filepath.Join(gopath, "pkg") - if _, err := os.Stat(gopathpkg); err == nil && gopath != "" { - if err := writeDLLs(gopathpkg); err == nil { - return gopathpkg, nil - } - } - debug.Printf("DLLs could not be written to GOPATH") - - // Third, pick a temporary directory. - tmp := os.TempDir() - if err := writeDLLs(tmp); err != nil { - return "", fmt.Errorf("gl: unable to install ANGLE DLLs: %v", err) - } - return tmp, nil -} - -func appdataPath() string { - return filepath.Join(os.Getenv("LOCALAPPDATA"), "GoGL", runtime.GOARCH) -} - -func containsDLLs(dir string) bool { - compatible := func(name string) bool { - file, err := pe.Open(filepath.Join(dir, name)) - if err != nil { - return false - } - defer file.Close() - - switch file.Machine { - case pe.IMAGE_FILE_MACHINE_AMD64: - return "amd64" == runtime.GOARCH - case pe.IMAGE_FILE_MACHINE_ARM: - return "arm" == runtime.GOARCH - case pe.IMAGE_FILE_MACHINE_I386: - return "386" == runtime.GOARCH - } - return false - } - - return compatible("libglesv2.dll") && compatible("libegl.dll") && compatible("d3dcompiler_47.dll") -} - -func chromePath() string { - // dlls are stored in: - // //libglesv2.dll - - var installdirs = []string{ - // Chrome User - filepath.Join(os.Getenv("LOCALAPPDATA"), "Google", "Chrome", "Application"), - // Chrome System - filepath.Join(os.Getenv("ProgramFiles(x86)"), "Google", "Chrome", "Application"), - // Chromium - filepath.Join(os.Getenv("LOCALAPPDATA"), "Chromium", "Application"), - // Chrome Canary - filepath.Join(os.Getenv("LOCALAPPDATA"), "Google", "Chrome SxS", "Application"), - } - - for _, installdir := range installdirs { - versiondirs, err := ioutil.ReadDir(installdir) - if err != nil { - continue - } - - for _, versiondir := range versiondirs { - if !versiondir.IsDir() { - continue - } - - versionpath := filepath.Join(installdir, versiondir.Name()) - if containsDLLs(versionpath) { - return versionpath - } - } - } - - return "" -} - -func findDLLs() (err error) { - load := func(path string) (bool, error) { - if path != "" { - // don't try to start when one of the files is missing - if !containsDLLs(path) { - return false, nil - } - - LibD3DCompiler.Name = filepath.Join(path, filepath.Base(LibD3DCompiler.Name)) - LibGLESv2.Name = filepath.Join(path, filepath.Base(LibGLESv2.Name)) - LibEGL.Name = filepath.Join(path, filepath.Base(LibEGL.Name)) - } - - if err := LibGLESv2.Load(); err == nil { - if err := LibEGL.Load(); err != nil { - return false, fmt.Errorf("gl: loaded libglesv2 but not libegl: %v", err) - } - if err := LibD3DCompiler.Load(); err != nil { - return false, fmt.Errorf("gl: loaded libglesv2, libegl but not d3dcompiler: %v", err) - } - if path == "" { - debug.Printf("DLLs found") - } else { - debug.Printf("DLLs found in: %q", path) - } - return true, nil - } - - return false, nil - } - - // Look in the system directory. - if ok, err := load(""); ok || err != nil { - return err - } - - // Look in the AppData directory. - if ok, err := load(appdataPath()); ok || err != nil { - return err - } - - // Look for a Chrome installation - if dir := chromePath(); dir != "" { - if ok, err := load(dir); ok || err != nil { - return err - } - } - - // Look in GOPATH/pkg. - if ok, err := load(filepath.Join(os.Getenv("GOPATH"), "pkg")); ok || err != nil { - return err - } - - // Look in temporary directory. - if ok, err := load(os.TempDir()); ok || err != nil { - return err - } - - // Download the DLL binary. - path, err := downloadDLLs() - if err != nil { - return err - } - debug.Printf("DLLs written to %s", path) - if ok, err := load(path); !ok || err != nil { - return fmt.Errorf("gl: unable to load ANGLE after installation: %v", err) - } - return nil -} diff --git a/vendor/golang.org/x/mobile/gl/doc.go b/vendor/golang.org/x/mobile/gl/doc.go deleted file mode 100644 index 880d5f9..0000000 --- a/vendor/golang.org/x/mobile/gl/doc.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package gl implements Go bindings for OpenGL ES 2.0 and ES 3.0. - -The GL functions are defined on a Context object that is responsible for -tracking a GL context. Typically a windowing system package (such as -golang.org/x/exp/shiny/screen) will call NewContext and provide -a gl.Context for a user application. - -If the gl package is compiled on a platform capable of supporting ES 3.0, -the gl.Context object also implements gl.Context3. - -The bindings are deliberately minimal, staying as close the C API as -possible. The semantics of each function maps onto functions -described in the Khronos documentation: - -https://www.khronos.org/opengles/sdk/docs/man/ - -One notable departure from the C API is the introduction of types -to represent common uses of GLint: Texture, Surface, Buffer, etc. - -# Debug Logging - -A tracing version of the OpenGL bindings is behind the `gldebug` build -tag. It acts as a simplified version of apitrace. Build your Go binary -with - - -tags gldebug - -and each call to a GL function will log its input, output, and any -error messages. For example, - - I/GoLog (27668): gl.GenBuffers(1) [Buffer(70001)] - I/GoLog (27668): gl.BindBuffer(ARRAY_BUFFER, Buffer(70001)) - I/GoLog (27668): gl.BufferData(ARRAY_BUFFER, 36, len(36), STATIC_DRAW) - I/GoLog (27668): gl.BindBuffer(ARRAY_BUFFER, Buffer(70001)) - I/GoLog (27668): gl.VertexAttribPointer(Attrib(0), 6, FLOAT, false, 0, 0) error: [INVALID_VALUE] - -The gldebug tracing has very high overhead, so make sure to remove -the build tag before deploying any binaries. -*/ -package gl // import "golang.org/x/mobile/gl" - -/* -Implementation details. - -All GL function calls fill out a C.struct_fnargs and drop it on the work -queue. The Start function drains the work queue and hands over a batch -of calls to C.process which runs them. This allows multiple GL calls to -be executed in a single cgo call. - -A GL call is marked as blocking if it returns a value, or if it takes a -Go pointer. In this case the call will not return until C.process sends a -value on the retvalue channel. - -This implementation ensures any goroutine can make GL calls, but it does -not make the GL interface safe for simultaneous use by multiple goroutines. -For the purpose of analyzing this code for race conditions, picture two -separate goroutines: one blocked on gl.Start, and another making calls to -the gl package exported functions. -*/ - -//go:generate go run gendebug.go -o gldebug.go diff --git a/vendor/golang.org/x/mobile/gl/fn.go b/vendor/golang.org/x/mobile/gl/fn.go deleted file mode 100644 index 3f2f3ad..0000000 --- a/vendor/golang.org/x/mobile/gl/fn.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gl - -import "unsafe" - -type call struct { - args fnargs - parg unsafe.Pointer - blocking bool -} - -type fnargs struct { - fn glfn - - a0 uintptr - a1 uintptr - a2 uintptr - a3 uintptr - a4 uintptr - a5 uintptr - a6 uintptr - a7 uintptr - a8 uintptr - a9 uintptr -} - -type glfn int - -const ( - glfnUNDEFINED glfn = iota - glfnActiveTexture - glfnAttachShader - glfnBindAttribLocation - glfnBindBuffer - glfnBindFramebuffer - glfnBindRenderbuffer - glfnBindTexture - glfnBindVertexArray - glfnBlendColor - glfnBlendEquation - glfnBlendEquationSeparate - glfnBlendFunc - glfnBlendFuncSeparate - glfnBufferData - glfnBufferSubData - glfnCheckFramebufferStatus - glfnClear - glfnClearColor - glfnClearDepthf - glfnClearStencil - glfnColorMask - glfnCompileShader - glfnCompressedTexImage2D - glfnCompressedTexSubImage2D - glfnCopyTexImage2D - glfnCopyTexSubImage2D - glfnCreateProgram - glfnCreateShader - glfnCullFace - glfnDeleteBuffer - glfnDeleteFramebuffer - glfnDeleteProgram - glfnDeleteRenderbuffer - glfnDeleteShader - glfnDeleteTexture - glfnDeleteVertexArray - glfnDepthFunc - glfnDepthRangef - glfnDepthMask - glfnDetachShader - glfnDisable - glfnDisableVertexAttribArray - glfnDrawArrays - glfnDrawElements - glfnEnable - glfnEnableVertexAttribArray - glfnFinish - glfnFlush - glfnFramebufferRenderbuffer - glfnFramebufferTexture2D - glfnFrontFace - glfnGenBuffer - glfnGenFramebuffer - glfnGenRenderbuffer - glfnGenTexture - glfnGenVertexArray - glfnGenerateMipmap - glfnGetActiveAttrib - glfnGetActiveUniform - glfnGetAttachedShaders - glfnGetAttribLocation - glfnGetBooleanv - glfnGetBufferParameteri - glfnGetError - glfnGetFloatv - glfnGetFramebufferAttachmentParameteriv - glfnGetIntegerv - glfnGetProgramInfoLog - glfnGetProgramiv - glfnGetRenderbufferParameteriv - glfnGetShaderInfoLog - glfnGetShaderPrecisionFormat - glfnGetShaderSource - glfnGetShaderiv - glfnGetString - glfnGetTexParameterfv - glfnGetTexParameteriv - glfnGetUniformLocation - glfnGetUniformfv - glfnGetUniformiv - glfnGetVertexAttribfv - glfnGetVertexAttribiv - glfnHint - glfnIsBuffer - glfnIsEnabled - glfnIsFramebuffer - glfnIsProgram - glfnIsRenderbuffer - glfnIsShader - glfnIsTexture - glfnLineWidth - glfnLinkProgram - glfnPixelStorei - glfnPolygonOffset - glfnReadPixels - glfnReleaseShaderCompiler - glfnRenderbufferStorage - glfnSampleCoverage - glfnScissor - glfnShaderSource - glfnStencilFunc - glfnStencilFuncSeparate - glfnStencilMask - glfnStencilMaskSeparate - glfnStencilOp - glfnStencilOpSeparate - glfnTexImage2D - glfnTexParameterf - glfnTexParameterfv - glfnTexParameteri - glfnTexParameteriv - glfnTexSubImage2D - glfnUniform1f - glfnUniform1fv - glfnUniform1i - glfnUniform1iv - glfnUniform2f - glfnUniform2fv - glfnUniform2i - glfnUniform2iv - glfnUniform3f - glfnUniform3fv - glfnUniform3i - glfnUniform3iv - glfnUniform4f - glfnUniform4fv - glfnUniform4i - glfnUniform4iv - glfnUniformMatrix2fv - glfnUniformMatrix3fv - glfnUniformMatrix4fv - glfnUseProgram - glfnValidateProgram - glfnVertexAttrib1f - glfnVertexAttrib1fv - glfnVertexAttrib2f - glfnVertexAttrib2fv - glfnVertexAttrib3f - glfnVertexAttrib3fv - glfnVertexAttrib4f - glfnVertexAttrib4fv - glfnVertexAttribPointer - glfnViewport - - // ES 3.0 functions - glfnUniformMatrix2x3fv - glfnUniformMatrix3x2fv - glfnUniformMatrix2x4fv - glfnUniformMatrix4x2fv - glfnUniformMatrix3x4fv - glfnUniformMatrix4x3fv - glfnBlitFramebuffer - glfnUniform1ui - glfnUniform2ui - glfnUniform3ui - glfnUniform4ui - glfnUniform1uiv - glfnUniform2uiv - glfnUniform3uiv - glfnUniform4uiv -) - -func goString(buf []byte) string { - for i, b := range buf { - if b == 0 { - return string(buf[:i]) - } - } - panic("buf is not NUL-terminated") -} - -func glBoolean(b bool) uintptr { - if b { - return TRUE - } - return FALSE -} diff --git a/vendor/golang.org/x/mobile/gl/gl.go b/vendor/golang.org/x/mobile/gl/gl.go deleted file mode 100644 index 195a309..0000000 --- a/vendor/golang.org/x/mobile/gl/gl.go +++ /dev/null @@ -1,1853 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (darwin || linux || openbsd || windows) && !gldebug -// +build darwin linux openbsd windows -// +build !gldebug - -package gl - -// TODO(crawshaw): should functions on specific types become methods? E.g. -// func (t Texture) Bind(target Enum) -// this seems natural in Go, but moves us slightly -// further away from the underlying OpenGL spec. - -import ( - "math" - "unsafe" -) - -func (ctx *context) ActiveTexture(texture Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnActiveTexture, - a0: texture.c(), - }, - }) -} - -func (ctx *context) AttachShader(p Program, s Shader) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnAttachShader, - a0: p.c(), - a1: s.c(), - }, - }) -} - -func (ctx *context) BindAttribLocation(p Program, a Attrib, name string) { - s, free := ctx.cString(name) - defer free() - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBindAttribLocation, - a0: p.c(), - a1: a.c(), - a2: s, - }, - blocking: true, - }) -} - -func (ctx *context) BindBuffer(target Enum, b Buffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBindBuffer, - a0: target.c(), - a1: b.c(), - }, - }) -} - -func (ctx *context) BindFramebuffer(target Enum, fb Framebuffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBindFramebuffer, - a0: target.c(), - a1: fb.c(), - }, - }) -} - -func (ctx *context) BindRenderbuffer(target Enum, rb Renderbuffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBindRenderbuffer, - a0: target.c(), - a1: rb.c(), - }, - }) -} - -func (ctx *context) BindTexture(target Enum, t Texture) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBindTexture, - a0: target.c(), - a1: t.c(), - }, - }) -} - -func (ctx *context) BindVertexArray(va VertexArray) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBindVertexArray, - a0: va.c(), - }, - }) -} - -func (ctx *context) BlendColor(red, green, blue, alpha float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBlendColor, - a0: uintptr(math.Float32bits(red)), - a1: uintptr(math.Float32bits(green)), - a2: uintptr(math.Float32bits(blue)), - a3: uintptr(math.Float32bits(alpha)), - }, - }) -} - -func (ctx *context) BlendEquation(mode Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBlendEquation, - a0: mode.c(), - }, - }) -} - -func (ctx *context) BlendEquationSeparate(modeRGB, modeAlpha Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBlendEquationSeparate, - a0: modeRGB.c(), - a1: modeAlpha.c(), - }, - }) -} - -func (ctx *context) BlendFunc(sfactor, dfactor Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBlendFunc, - a0: sfactor.c(), - a1: dfactor.c(), - }, - }) -} - -func (ctx *context) BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBlendFuncSeparate, - a0: sfactorRGB.c(), - a1: dfactorRGB.c(), - a2: sfactorAlpha.c(), - a3: dfactorAlpha.c(), - }, - }) -} - -func (ctx *context) BufferData(target Enum, src []byte, usage Enum) { - parg := unsafe.Pointer(nil) - if len(src) > 0 { - parg = unsafe.Pointer(&src[0]) - } - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBufferData, - a0: target.c(), - a1: uintptr(len(src)), - a2: usage.c(), - }, - parg: parg, - blocking: true, - }) -} - -func (ctx *context) BufferInit(target Enum, size int, usage Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBufferData, - a0: target.c(), - a1: uintptr(size), - a2: usage.c(), - }, - parg: unsafe.Pointer(nil), - }) -} - -func (ctx *context) BufferSubData(target Enum, offset int, data []byte) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBufferSubData, - a0: target.c(), - a1: uintptr(offset), - a2: uintptr(len(data)), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) CheckFramebufferStatus(target Enum) Enum { - return Enum(ctx.enqueue(call{ - args: fnargs{ - fn: glfnCheckFramebufferStatus, - a0: target.c(), - }, - blocking: true, - })) -} - -func (ctx *context) Clear(mask Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnClear, - a0: uintptr(mask), - }, - }) -} - -func (ctx *context) ClearColor(red, green, blue, alpha float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnClearColor, - a0: uintptr(math.Float32bits(red)), - a1: uintptr(math.Float32bits(green)), - a2: uintptr(math.Float32bits(blue)), - a3: uintptr(math.Float32bits(alpha)), - }, - }) -} - -func (ctx *context) ClearDepthf(d float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnClearDepthf, - a0: uintptr(math.Float32bits(d)), - }, - }) -} - -func (ctx *context) ClearStencil(s int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnClearStencil, - a0: uintptr(s), - }, - }) -} - -func (ctx *context) ColorMask(red, green, blue, alpha bool) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnColorMask, - a0: glBoolean(red), - a1: glBoolean(green), - a2: glBoolean(blue), - a3: glBoolean(alpha), - }, - }) -} - -func (ctx *context) CompileShader(s Shader) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnCompileShader, - a0: s.c(), - }, - }) -} - -func (ctx *context) CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnCompressedTexImage2D, - a0: target.c(), - a1: uintptr(level), - a2: internalformat.c(), - a3: uintptr(width), - a4: uintptr(height), - a5: uintptr(border), - a6: uintptr(len(data)), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnCompressedTexSubImage2D, - a0: target.c(), - a1: uintptr(level), - a2: uintptr(xoffset), - a3: uintptr(yoffset), - a4: uintptr(width), - a5: uintptr(height), - a6: format.c(), - a7: uintptr(len(data)), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnCopyTexImage2D, - a0: target.c(), - a1: uintptr(level), - a2: internalformat.c(), - a3: uintptr(x), - a4: uintptr(y), - a5: uintptr(width), - a6: uintptr(height), - a7: uintptr(border), - }, - }) -} - -func (ctx *context) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnCopyTexSubImage2D, - a0: target.c(), - a1: uintptr(level), - a2: uintptr(xoffset), - a3: uintptr(yoffset), - a4: uintptr(x), - a5: uintptr(y), - a6: uintptr(width), - a7: uintptr(height), - }, - }) -} - -func (ctx *context) CreateBuffer() Buffer { - return Buffer{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenBuffer, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateFramebuffer() Framebuffer { - return Framebuffer{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenFramebuffer, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateProgram() Program { - return Program{ - Init: true, - Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnCreateProgram, - }, - blocking: true, - }, - ))} -} - -func (ctx *context) CreateRenderbuffer() Renderbuffer { - return Renderbuffer{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenRenderbuffer, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateShader(ty Enum) Shader { - return Shader{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnCreateShader, - a0: uintptr(ty), - }, - blocking: true, - }))} -} - -func (ctx *context) CreateTexture() Texture { - return Texture{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenTexture, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateVertexArray() VertexArray { - return VertexArray{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenVertexArray, - }, - blocking: true, - }))} -} - -func (ctx *context) CullFace(mode Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnCullFace, - a0: mode.c(), - }, - }) -} - -func (ctx *context) DeleteBuffer(v Buffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteBuffer, - a0: v.c(), - }, - }) -} - -func (ctx *context) DeleteFramebuffer(v Framebuffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteFramebuffer, - a0: v.c(), - }, - }) -} - -func (ctx *context) DeleteProgram(p Program) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteProgram, - a0: p.c(), - }, - }) -} - -func (ctx *context) DeleteRenderbuffer(v Renderbuffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteRenderbuffer, - a0: v.c(), - }, - }) -} - -func (ctx *context) DeleteShader(s Shader) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteShader, - a0: s.c(), - }, - }) -} - -func (ctx *context) DeleteTexture(v Texture) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteTexture, - a0: v.c(), - }, - }) -} - -func (ctx *context) DeleteVertexArray(v VertexArray) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDeleteVertexArray, - a0: v.c(), - }, - }) -} - -func (ctx *context) DepthFunc(fn Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDepthFunc, - a0: fn.c(), - }, - }) -} - -func (ctx *context) DepthMask(flag bool) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDepthMask, - a0: glBoolean(flag), - }, - }) -} - -func (ctx *context) DepthRangef(n, f float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDepthRangef, - a0: uintptr(math.Float32bits(n)), - a1: uintptr(math.Float32bits(f)), - }, - }) -} - -func (ctx *context) DetachShader(p Program, s Shader) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDetachShader, - a0: p.c(), - a1: s.c(), - }, - }) -} - -func (ctx *context) Disable(cap Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDisable, - a0: cap.c(), - }, - }) -} - -func (ctx *context) DisableVertexAttribArray(a Attrib) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDisableVertexAttribArray, - a0: a.c(), - }, - }) -} - -func (ctx *context) DrawArrays(mode Enum, first, count int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDrawArrays, - a0: mode.c(), - a1: uintptr(first), - a2: uintptr(count), - }, - }) -} - -func (ctx *context) DrawElements(mode Enum, count int, ty Enum, offset int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnDrawElements, - a0: mode.c(), - a1: uintptr(count), - a2: ty.c(), - a3: uintptr(offset), - }, - }) -} - -func (ctx *context) Enable(cap Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnEnable, - a0: cap.c(), - }, - }) -} - -func (ctx *context) EnableVertexAttribArray(a Attrib) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnEnableVertexAttribArray, - a0: a.c(), - }, - }) -} - -func (ctx *context) Finish() { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnFinish, - }, - blocking: true, - }) -} - -func (ctx *context) Flush() { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnFlush, - }, - blocking: true, - }) -} - -func (ctx *context) FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnFramebufferRenderbuffer, - a0: target.c(), - a1: attachment.c(), - a2: rbTarget.c(), - a3: rb.c(), - }, - }) -} - -func (ctx *context) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnFramebufferTexture2D, - a0: target.c(), - a1: attachment.c(), - a2: texTarget.c(), - a3: t.c(), - a4: uintptr(level), - }, - }) -} - -func (ctx *context) FrontFace(mode Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnFrontFace, - a0: mode.c(), - }, - }) -} - -func (ctx *context) GenerateMipmap(target Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenerateMipmap, - a0: target.c(), - }, - }) -} - -func (ctx *context) GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { - bufSize := ctx.GetProgrami(p, ACTIVE_ATTRIBUTE_MAX_LENGTH) - buf := make([]byte, bufSize) - var cType int - - cSize := ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetActiveAttrib, - a0: p.c(), - a1: uintptr(index), - a2: uintptr(bufSize), - a3: uintptr(unsafe.Pointer(&cType)), // TODO(crawshaw): not safe for a moving collector - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - - return goString(buf), int(cSize), Enum(cType) -} - -func (ctx *context) GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { - bufSize := ctx.GetProgrami(p, ACTIVE_UNIFORM_MAX_LENGTH) - buf := make([]byte, bufSize+8) // extra space for cType - var cType int - - cSize := ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetActiveUniform, - a0: p.c(), - a1: uintptr(index), - a2: uintptr(bufSize), - a3: uintptr(unsafe.Pointer(&cType)), // TODO(crawshaw): not safe for a moving collector - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - - return goString(buf), int(cSize), Enum(cType) -} - -func (ctx *context) GetAttachedShaders(p Program) []Shader { - shadersLen := ctx.GetProgrami(p, ATTACHED_SHADERS) - if shadersLen == 0 { - return nil - } - buf := make([]uint32, shadersLen) - - n := int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetAttachedShaders, - a0: p.c(), - a1: uintptr(shadersLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - })) - - buf = buf[:int(n)] - shaders := make([]Shader, len(buf)) - for i, s := range buf { - shaders[i] = Shader{Value: uint32(s)} - } - return shaders -} - -func (ctx *context) GetAttribLocation(p Program, name string) Attrib { - s, free := ctx.cString(name) - defer free() - return Attrib{Value: uint(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetAttribLocation, - a0: p.c(), - a1: s, - }, - blocking: true, - }))} -} - -func (ctx *context) GetBooleanv(dst []bool, pname Enum) { - buf := make([]int32, len(dst)) - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetBooleanv, - a0: pname.c(), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - - for i, v := range buf { - dst[i] = v != 0 - } -} - -func (ctx *context) GetFloatv(dst []float32, pname Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetFloatv, - a0: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetIntegerv(dst []int32, pname Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetIntegerv, - a0: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetInteger(pname Enum) int { - var v [1]int32 - ctx.GetIntegerv(v[:], pname) - return int(v[0]) -} - -func (ctx *context) GetBufferParameteri(target, value Enum) int { - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetBufferParameteri, - a0: target.c(), - a1: value.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetError() Enum { - return Enum(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetError, - }, - blocking: true, - })) -} - -func (ctx *context) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int { - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetFramebufferAttachmentParameteriv, - a0: target.c(), - a1: attachment.c(), - a2: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetProgrami(p Program, pname Enum) int { - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetProgramiv, - a0: p.c(), - a1: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetProgramInfoLog(p Program) string { - infoLen := ctx.GetProgrami(p, INFO_LOG_LENGTH) - if infoLen == 0 { - return "" - } - buf := make([]byte, infoLen) - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetProgramInfoLog, - a0: p.c(), - a1: uintptr(infoLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - - return goString(buf) -} - -func (ctx *context) GetRenderbufferParameteri(target, pname Enum) int { - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetRenderbufferParameteriv, - a0: target.c(), - a1: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetShaderi(s Shader, pname Enum) int { - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetShaderiv, - a0: s.c(), - a1: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetShaderInfoLog(s Shader) string { - infoLen := ctx.GetShaderi(s, INFO_LOG_LENGTH) - if infoLen == 0 { - return "" - } - buf := make([]byte, infoLen) - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetShaderInfoLog, - a0: s.c(), - a1: uintptr(infoLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - - return goString(buf) -} - -func (ctx *context) GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) { - var rangeAndPrec [3]int32 - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetShaderPrecisionFormat, - a0: shadertype.c(), - a1: precisiontype.c(), - }, - parg: unsafe.Pointer(&rangeAndPrec[0]), - blocking: true, - }) - - return int(rangeAndPrec[0]), int(rangeAndPrec[1]), int(rangeAndPrec[2]) -} - -func (ctx *context) GetShaderSource(s Shader) string { - sourceLen := ctx.GetShaderi(s, SHADER_SOURCE_LENGTH) - if sourceLen == 0 { - return "" - } - buf := make([]byte, sourceLen) - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetShaderSource, - a0: s.c(), - a1: uintptr(sourceLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - - return goString(buf) -} - -func (ctx *context) GetString(pname Enum) string { - ret := ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetString, - a0: pname.c(), - }, - blocking: true, - }) - retp := unsafe.Pointer(ret) - buf := (*[1 << 24]byte)(retp)[:] - return goString(buf) -} - -func (ctx *context) GetTexParameterfv(dst []float32, target, pname Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetTexParameterfv, - a0: target.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetTexParameteriv(dst []int32, target, pname Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetTexParameteriv, - a0: target.c(), - a1: pname.c(), - }, - blocking: true, - }) -} - -func (ctx *context) GetUniformfv(dst []float32, src Uniform, p Program) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetUniformfv, - a0: p.c(), - a1: src.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetUniformiv(dst []int32, src Uniform, p Program) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetUniformiv, - a0: p.c(), - a1: src.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetUniformLocation(p Program, name string) Uniform { - s, free := ctx.cString(name) - defer free() - return Uniform{Value: int32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetUniformLocation, - a0: p.c(), - a1: s, - }, - blocking: true, - }))} -} - -func (ctx *context) GetVertexAttribf(src Attrib, pname Enum) float32 { - var params [1]float32 - ctx.GetVertexAttribfv(params[:], src, pname) - return params[0] -} - -func (ctx *context) GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetVertexAttribfv, - a0: src.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetVertexAttribi(src Attrib, pname Enum) int32 { - var params [1]int32 - ctx.GetVertexAttribiv(params[:], src, pname) - return params[0] -} - -func (ctx *context) GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetVertexAttribiv, - a0: src.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) Hint(target, mode Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnHint, - a0: target.c(), - a1: mode.c(), - }, - }) -} - -func (ctx *context) IsBuffer(b Buffer) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsBuffer, - a0: b.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsEnabled(cap Enum) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsEnabled, - a0: cap.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsFramebuffer(fb Framebuffer) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsFramebuffer, - a0: fb.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsProgram(p Program) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsProgram, - a0: p.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsRenderbuffer(rb Renderbuffer) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsRenderbuffer, - a0: rb.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsShader(s Shader) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsShader, - a0: s.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsTexture(t Texture) bool { - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsTexture, - a0: t.c(), - }, - blocking: true, - }) -} - -func (ctx *context) LineWidth(width float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnLineWidth, - a0: uintptr(math.Float32bits(width)), - }, - }) -} - -func (ctx *context) LinkProgram(p Program) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnLinkProgram, - a0: p.c(), - }, - }) -} - -func (ctx *context) PixelStorei(pname Enum, param int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnPixelStorei, - a0: pname.c(), - a1: uintptr(param), - }, - }) -} - -func (ctx *context) PolygonOffset(factor, units float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnPolygonOffset, - a0: uintptr(math.Float32bits(factor)), - a1: uintptr(math.Float32bits(units)), - }, - }) -} - -func (ctx *context) ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnReadPixels, - // TODO(crawshaw): support PIXEL_PACK_BUFFER in GLES3, uses offset. - a0: uintptr(x), - a1: uintptr(y), - a2: uintptr(width), - a3: uintptr(height), - a4: format.c(), - a5: ty.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) ReleaseShaderCompiler() { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnReleaseShaderCompiler, - }, - }) -} - -func (ctx *context) RenderbufferStorage(target, internalFormat Enum, width, height int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnRenderbufferStorage, - a0: target.c(), - a1: internalFormat.c(), - a2: uintptr(width), - a3: uintptr(height), - }, - }) -} - -func (ctx *context) SampleCoverage(value float32, invert bool) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnSampleCoverage, - a0: uintptr(math.Float32bits(value)), - a1: glBoolean(invert), - }, - }) -} - -func (ctx *context) Scissor(x, y, width, height int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnScissor, - a0: uintptr(x), - a1: uintptr(y), - a2: uintptr(width), - a3: uintptr(height), - }, - }) -} - -func (ctx *context) ShaderSource(s Shader, src string) { - strp, free := ctx.cStringPtr(src) - defer free() - ctx.enqueue(call{ - args: fnargs{ - fn: glfnShaderSource, - a0: s.c(), - a1: 1, - a2: strp, - }, - blocking: true, - }) -} - -func (ctx *context) StencilFunc(fn Enum, ref int, mask uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnStencilFunc, - a0: fn.c(), - a1: uintptr(ref), - a2: uintptr(mask), - }, - }) -} - -func (ctx *context) StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnStencilFuncSeparate, - a0: face.c(), - a1: fn.c(), - a2: uintptr(ref), - a3: uintptr(mask), - }, - }) -} - -func (ctx *context) StencilMask(mask uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnStencilMask, - a0: uintptr(mask), - }, - }) -} - -func (ctx *context) StencilMaskSeparate(face Enum, mask uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnStencilMaskSeparate, - a0: face.c(), - a1: uintptr(mask), - }, - }) -} - -func (ctx *context) StencilOp(fail, zfail, zpass Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnStencilOp, - a0: fail.c(), - a1: zfail.c(), - a2: zpass.c(), - }, - }) -} - -func (ctx *context) StencilOpSeparate(face, sfail, dpfail, dppass Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnStencilOpSeparate, - a0: face.c(), - a1: sfail.c(), - a2: dpfail.c(), - a3: dppass.c(), - }, - }) -} - -func (ctx *context) TexImage2D(target Enum, level int, internalFormat int, width, height int, format Enum, ty Enum, data []byte) { - // It is common to pass TexImage2D a nil data, indicating that a - // bound GL buffer is being used as the source. In that case, it - // is not necessary to block. - parg := unsafe.Pointer(nil) - if len(data) > 0 { - parg = unsafe.Pointer(&data[0]) - } - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnTexImage2D, - // TODO(crawshaw): GLES3 offset for PIXEL_UNPACK_BUFFER and PIXEL_PACK_BUFFER. - a0: target.c(), - a1: uintptr(level), - a2: uintptr(internalFormat), - a3: uintptr(width), - a4: uintptr(height), - a5: format.c(), - a6: ty.c(), - }, - parg: parg, - blocking: parg != nil, - }) -} - -func (ctx *context) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { - // It is common to pass TexSubImage2D a nil data, indicating that a - // bound GL buffer is being used as the source. In that case, it - // is not necessary to block. - parg := unsafe.Pointer(nil) - if len(data) > 0 { - parg = unsafe.Pointer(&data[0]) - } - - ctx.enqueue(call{ - args: fnargs{ - fn: glfnTexSubImage2D, - // TODO(crawshaw): GLES3 offset for PIXEL_UNPACK_BUFFER and PIXEL_PACK_BUFFER. - a0: target.c(), - a1: uintptr(level), - a2: uintptr(x), - a3: uintptr(y), - a4: uintptr(width), - a5: uintptr(height), - a6: format.c(), - a7: ty.c(), - }, - parg: parg, - blocking: parg != nil, - }) -} - -func (ctx *context) TexParameterf(target, pname Enum, param float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnTexParameterf, - a0: target.c(), - a1: pname.c(), - a2: uintptr(math.Float32bits(param)), - }, - }) -} - -func (ctx *context) TexParameterfv(target, pname Enum, params []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnTexParameterfv, - a0: target.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(¶ms[0]), - blocking: true, - }) -} - -func (ctx *context) TexParameteri(target, pname Enum, param int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnTexParameteri, - a0: target.c(), - a1: pname.c(), - a2: uintptr(param), - }, - }) -} - -func (ctx *context) TexParameteriv(target, pname Enum, params []int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnTexParameteriv, - a0: target.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(¶ms[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform1f(dst Uniform, v float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform1f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v)), - }, - }) -} - -func (ctx *context) Uniform1fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform1fv, - a0: dst.c(), - a1: uintptr(len(src)), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform1i(dst Uniform, v int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform1i, - a0: dst.c(), - a1: uintptr(v), - }, - }) -} - -func (ctx *context) Uniform1iv(dst Uniform, src []int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform1iv, - a0: dst.c(), - a1: uintptr(len(src)), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform2f(dst Uniform, v0, v1 float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform2f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v0)), - a2: uintptr(math.Float32bits(v1)), - }, - }) -} - -func (ctx *context) Uniform2fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform2fv, - a0: dst.c(), - a1: uintptr(len(src) / 2), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform2i(dst Uniform, v0, v1 int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform2i, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - }, - }) -} - -func (ctx *context) Uniform2iv(dst Uniform, src []int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform2iv, - a0: dst.c(), - a1: uintptr(len(src) / 2), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform3f(dst Uniform, v0, v1, v2 float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform3f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v0)), - a2: uintptr(math.Float32bits(v1)), - a3: uintptr(math.Float32bits(v2)), - }, - }) -} - -func (ctx *context) Uniform3fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform3fv, - a0: dst.c(), - a1: uintptr(len(src) / 3), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform3i(dst Uniform, v0, v1, v2 int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform3i, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - }, - }) -} - -func (ctx *context) Uniform3iv(dst Uniform, src []int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform3iv, - a0: dst.c(), - a1: uintptr(len(src) / 3), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform4f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v0)), - a2: uintptr(math.Float32bits(v1)), - a3: uintptr(math.Float32bits(v2)), - a4: uintptr(math.Float32bits(v3)), - }, - }) -} - -func (ctx *context) Uniform4fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform4fv, - a0: dst.c(), - a1: uintptr(len(src) / 4), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform4i, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - a4: uintptr(v3), - }, - }) -} - -func (ctx *context) Uniform4iv(dst Uniform, src []int32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform4iv, - a0: dst.c(), - a1: uintptr(len(src) / 4), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UniformMatrix2fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix2fv, - // OpenGL ES 2 does not support transpose. - a0: dst.c(), - a1: uintptr(len(src) / 4), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UniformMatrix3fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix3fv, - a0: dst.c(), - a1: uintptr(len(src) / 9), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UniformMatrix4fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix4fv, - a0: dst.c(), - a1: uintptr(len(src) / 16), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UseProgram(p Program) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUseProgram, - a0: p.c(), - }, - }) -} - -func (ctx *context) ValidateProgram(p Program) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnValidateProgram, - a0: p.c(), - }, - }) -} - -func (ctx *context) VertexAttrib1f(dst Attrib, x float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib1f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - }, - }) -} - -func (ctx *context) VertexAttrib1fv(dst Attrib, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib1fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttrib2f(dst Attrib, x, y float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib2f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - a2: uintptr(math.Float32bits(y)), - }, - }) -} - -func (ctx *context) VertexAttrib2fv(dst Attrib, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib2fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttrib3f(dst Attrib, x, y, z float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib3f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - a2: uintptr(math.Float32bits(y)), - a3: uintptr(math.Float32bits(z)), - }, - }) -} - -func (ctx *context) VertexAttrib3fv(dst Attrib, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib3fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttrib4f(dst Attrib, x, y, z, w float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib4f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - a2: uintptr(math.Float32bits(y)), - a3: uintptr(math.Float32bits(z)), - a4: uintptr(math.Float32bits(w)), - }, - }) -} - -func (ctx *context) VertexAttrib4fv(dst Attrib, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttrib4fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnVertexAttribPointer, - a0: dst.c(), - a1: uintptr(size), - a2: ty.c(), - a3: glBoolean(normalized), - a4: uintptr(stride), - a5: uintptr(offset), - }, - }) -} - -func (ctx *context) Viewport(x, y, width, height int) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnViewport, - a0: uintptr(x), - a1: uintptr(y), - a2: uintptr(width), - a3: uintptr(height), - }, - }) -} - -func (ctx context3) UniformMatrix2x3fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix2x3fv, - a0: dst.c(), - a1: uintptr(len(src) / 6), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix3x2fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix3x2fv, - a0: dst.c(), - a1: uintptr(len(src) / 6), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix2x4fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix2x4fv, - a0: dst.c(), - a1: uintptr(len(src) / 8), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix4x2fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix4x2fv, - a0: dst.c(), - a1: uintptr(len(src) / 8), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix3x4fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix3x4fv, - a0: dst.c(), - a1: uintptr(len(src) / 12), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix4x3fv(dst Uniform, src []float32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniformMatrix4x3fv, - a0: dst.c(), - a1: uintptr(len(src) / 12), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnBlitFramebuffer, - a0: uintptr(srcX0), - a1: uintptr(srcY0), - a2: uintptr(srcX1), - a3: uintptr(srcY1), - a4: uintptr(dstX0), - a5: uintptr(dstY0), - a6: uintptr(dstX1), - a7: uintptr(dstY1), - a8: uintptr(mask), - a9: filter.c(), - }, - }) -} - -func (ctx context3) Uniform1ui(dst Uniform, v uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform1ui, - a0: dst.c(), - a1: uintptr(v), - }, - }) -} - -func (ctx context3) Uniform2ui(dst Uniform, v0, v1 uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform2ui, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - }, - }) -} - -func (ctx context3) Uniform3ui(dst Uniform, v0, v1, v2 uint) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform3ui, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - }, - }) -} - -func (ctx context3) Uniform4ui(dst Uniform, v0, v1, v2, v3 uint32) { - ctx.enqueue(call{ - args: fnargs{ - fn: glfnUniform4ui, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - a4: uintptr(v3), - }, - }) -} diff --git a/vendor/golang.org/x/mobile/gl/gldebug.go b/vendor/golang.org/x/mobile/gl/gldebug.go deleted file mode 100644 index 5a4bf71..0000000 --- a/vendor/golang.org/x/mobile/gl/gldebug.go +++ /dev/null @@ -1,3674 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated from gl.go using go generate. DO NOT EDIT. -// See doc.go for details. - -//go:build (darwin || linux || openbsd || windows) && gldebug -// +build darwin linux openbsd windows -// +build gldebug - -package gl - -import ( - "fmt" - "log" - "math" - "sync/atomic" - "unsafe" -) - -func (ctx *context) errDrain() string { - var errs []Enum - for { - e := ctx.GetError() - if e == 0 { - break - } - errs = append(errs, e) - } - if len(errs) > 0 { - return fmt.Sprintf(" error: %v", errs) - } - return "" -} - -func (ctx *context) enqueueDebug(c call) uintptr { - numCalls := atomic.AddInt32(&ctx.debug, 1) - if numCalls > 1 { - panic("concurrent calls made to the same GL context") - } - defer func() { - if atomic.AddInt32(&ctx.debug, -1) > 0 { - select {} // block so you see us in the panic - } - }() - - return ctx.enqueue(c) -} - -func (v Enum) String() string { - switch v { - case 0x0: - return "0" - case 0x1: - return "1" - case 0x2: - return "2" - case 0x3: - return "LINE_STRIP" - case 0x4: - return "4" - case 0x5: - return "TRIANGLE_STRIP" - case 0x6: - return "TRIANGLE_FAN" - case 0x300: - return "SRC_COLOR" - case 0x301: - return "ONE_MINUS_SRC_COLOR" - case 0x302: - return "SRC_ALPHA" - case 0x303: - return "ONE_MINUS_SRC_ALPHA" - case 0x304: - return "DST_ALPHA" - case 0x305: - return "ONE_MINUS_DST_ALPHA" - case 0x306: - return "DST_COLOR" - case 0x307: - return "ONE_MINUS_DST_COLOR" - case 0x308: - return "SRC_ALPHA_SATURATE" - case 0x8006: - return "FUNC_ADD" - case 0x8009: - return "32777" - case 0x883d: - return "BLEND_EQUATION_ALPHA" - case 0x800a: - return "FUNC_SUBTRACT" - case 0x800b: - return "FUNC_REVERSE_SUBTRACT" - case 0x80c8: - return "BLEND_DST_RGB" - case 0x80c9: - return "BLEND_SRC_RGB" - case 0x80ca: - return "BLEND_DST_ALPHA" - case 0x80cb: - return "BLEND_SRC_ALPHA" - case 0x8001: - return "CONSTANT_COLOR" - case 0x8002: - return "ONE_MINUS_CONSTANT_COLOR" - case 0x8003: - return "CONSTANT_ALPHA" - case 0x8004: - return "ONE_MINUS_CONSTANT_ALPHA" - case 0x8005: - return "BLEND_COLOR" - case 0x8892: - return "ARRAY_BUFFER" - case 0x8893: - return "ELEMENT_ARRAY_BUFFER" - case 0x8894: - return "ARRAY_BUFFER_BINDING" - case 0x8895: - return "ELEMENT_ARRAY_BUFFER_BINDING" - case 0x88e0: - return "STREAM_DRAW" - case 0x88e4: - return "STATIC_DRAW" - case 0x88e8: - return "DYNAMIC_DRAW" - case 0x8764: - return "BUFFER_SIZE" - case 0x8765: - return "BUFFER_USAGE" - case 0x8626: - return "CURRENT_VERTEX_ATTRIB" - case 0x404: - return "FRONT" - case 0x405: - return "BACK" - case 0x408: - return "FRONT_AND_BACK" - case 0xde1: - return "TEXTURE_2D" - case 0xb44: - return "CULL_FACE" - case 0xbe2: - return "BLEND" - case 0xbd0: - return "DITHER" - case 0xb90: - return "STENCIL_TEST" - case 0xb71: - return "DEPTH_TEST" - case 0xc11: - return "SCISSOR_TEST" - case 0x8037: - return "POLYGON_OFFSET_FILL" - case 0x809e: - return "SAMPLE_ALPHA_TO_COVERAGE" - case 0x80a0: - return "SAMPLE_COVERAGE" - case 0x500: - return "INVALID_ENUM" - case 0x501: - return "INVALID_VALUE" - case 0x502: - return "INVALID_OPERATION" - case 0x505: - return "OUT_OF_MEMORY" - case 0x900: - return "CW" - case 0x901: - return "CCW" - case 0xb21: - return "LINE_WIDTH" - case 0x846d: - return "ALIASED_POINT_SIZE_RANGE" - case 0x846e: - return "ALIASED_LINE_WIDTH_RANGE" - case 0xb45: - return "CULL_FACE_MODE" - case 0xb46: - return "FRONT_FACE" - case 0xb70: - return "DEPTH_RANGE" - case 0xb72: - return "DEPTH_WRITEMASK" - case 0xb73: - return "DEPTH_CLEAR_VALUE" - case 0xb74: - return "DEPTH_FUNC" - case 0xb91: - return "STENCIL_CLEAR_VALUE" - case 0xb92: - return "STENCIL_FUNC" - case 0xb94: - return "STENCIL_FAIL" - case 0xb95: - return "STENCIL_PASS_DEPTH_FAIL" - case 0xb96: - return "STENCIL_PASS_DEPTH_PASS" - case 0xb97: - return "STENCIL_REF" - case 0xb93: - return "STENCIL_VALUE_MASK" - case 0xb98: - return "STENCIL_WRITEMASK" - case 0x8800: - return "STENCIL_BACK_FUNC" - case 0x8801: - return "STENCIL_BACK_FAIL" - case 0x8802: - return "STENCIL_BACK_PASS_DEPTH_FAIL" - case 0x8803: - return "STENCIL_BACK_PASS_DEPTH_PASS" - case 0x8ca3: - return "STENCIL_BACK_REF" - case 0x8ca4: - return "STENCIL_BACK_VALUE_MASK" - case 0x8ca5: - return "STENCIL_BACK_WRITEMASK" - case 0xba2: - return "VIEWPORT" - case 0xc10: - return "SCISSOR_BOX" - case 0xc22: - return "COLOR_CLEAR_VALUE" - case 0xc23: - return "COLOR_WRITEMASK" - case 0xcf5: - return "UNPACK_ALIGNMENT" - case 0xd05: - return "PACK_ALIGNMENT" - case 0xd33: - return "MAX_TEXTURE_SIZE" - case 0xd3a: - return "MAX_VIEWPORT_DIMS" - case 0xd50: - return "SUBPIXEL_BITS" - case 0xd52: - return "RED_BITS" - case 0xd53: - return "GREEN_BITS" - case 0xd54: - return "BLUE_BITS" - case 0xd55: - return "ALPHA_BITS" - case 0xd56: - return "DEPTH_BITS" - case 0xd57: - return "STENCIL_BITS" - case 0x2a00: - return "POLYGON_OFFSET_UNITS" - case 0x8038: - return "POLYGON_OFFSET_FACTOR" - case 0x8069: - return "TEXTURE_BINDING_2D" - case 0x80a8: - return "SAMPLE_BUFFERS" - case 0x80a9: - return "SAMPLES" - case 0x80aa: - return "SAMPLE_COVERAGE_VALUE" - case 0x80ab: - return "SAMPLE_COVERAGE_INVERT" - case 0x86a2: - return "NUM_COMPRESSED_TEXTURE_FORMATS" - case 0x86a3: - return "COMPRESSED_TEXTURE_FORMATS" - case 0x1100: - return "DONT_CARE" - case 0x1101: - return "FASTEST" - case 0x1102: - return "NICEST" - case 0x8192: - return "GENERATE_MIPMAP_HINT" - case 0x1400: - return "BYTE" - case 0x1401: - return "UNSIGNED_BYTE" - case 0x1402: - return "SHORT" - case 0x1403: - return "UNSIGNED_SHORT" - case 0x1404: - return "INT" - case 0x1405: - return "UNSIGNED_INT" - case 0x1406: - return "FLOAT" - case 0x140c: - return "FIXED" - case 0x1902: - return "DEPTH_COMPONENT" - case 0x1906: - return "ALPHA" - case 0x1907: - return "RGB" - case 0x1908: - return "RGBA" - case 0x1909: - return "LUMINANCE" - case 0x190a: - return "LUMINANCE_ALPHA" - case 0x8033: - return "UNSIGNED_SHORT_4_4_4_4" - case 0x8034: - return "UNSIGNED_SHORT_5_5_5_1" - case 0x8363: - return "UNSIGNED_SHORT_5_6_5" - case 0x8869: - return "MAX_VERTEX_ATTRIBS" - case 0x8dfb: - return "MAX_VERTEX_UNIFORM_VECTORS" - case 0x8dfc: - return "MAX_VARYING_VECTORS" - case 0x8b4d: - return "MAX_COMBINED_TEXTURE_IMAGE_UNITS" - case 0x8b4c: - return "MAX_VERTEX_TEXTURE_IMAGE_UNITS" - case 0x8872: - return "MAX_TEXTURE_IMAGE_UNITS" - case 0x8dfd: - return "MAX_FRAGMENT_UNIFORM_VECTORS" - case 0x8b4f: - return "SHADER_TYPE" - case 0x8b80: - return "DELETE_STATUS" - case 0x8b82: - return "LINK_STATUS" - case 0x8b83: - return "VALIDATE_STATUS" - case 0x8b85: - return "ATTACHED_SHADERS" - case 0x8b86: - return "ACTIVE_UNIFORMS" - case 0x8b87: - return "ACTIVE_UNIFORM_MAX_LENGTH" - case 0x8b89: - return "ACTIVE_ATTRIBUTES" - case 0x8b8a: - return "ACTIVE_ATTRIBUTE_MAX_LENGTH" - case 0x8b8c: - return "SHADING_LANGUAGE_VERSION" - case 0x8b8d: - return "CURRENT_PROGRAM" - case 0x200: - return "NEVER" - case 0x201: - return "LESS" - case 0x202: - return "EQUAL" - case 0x203: - return "LEQUAL" - case 0x204: - return "GREATER" - case 0x205: - return "NOTEQUAL" - case 0x206: - return "GEQUAL" - case 0x207: - return "ALWAYS" - case 0x1e00: - return "KEEP" - case 0x1e01: - return "REPLACE" - case 0x1e02: - return "INCR" - case 0x1e03: - return "DECR" - case 0x150a: - return "INVERT" - case 0x8507: - return "INCR_WRAP" - case 0x8508: - return "DECR_WRAP" - case 0x1f00: - return "VENDOR" - case 0x1f01: - return "RENDERER" - case 0x1f02: - return "VERSION" - case 0x1f03: - return "EXTENSIONS" - case 0x2600: - return "NEAREST" - case 0x2601: - return "LINEAR" - case 0x2700: - return "NEAREST_MIPMAP_NEAREST" - case 0x2701: - return "LINEAR_MIPMAP_NEAREST" - case 0x2702: - return "NEAREST_MIPMAP_LINEAR" - case 0x2703: - return "LINEAR_MIPMAP_LINEAR" - case 0x2800: - return "TEXTURE_MAG_FILTER" - case 0x2801: - return "TEXTURE_MIN_FILTER" - case 0x2802: - return "TEXTURE_WRAP_S" - case 0x2803: - return "TEXTURE_WRAP_T" - case 0x1702: - return "TEXTURE" - case 0x8513: - return "TEXTURE_CUBE_MAP" - case 0x8514: - return "TEXTURE_BINDING_CUBE_MAP" - case 0x8515: - return "TEXTURE_CUBE_MAP_POSITIVE_X" - case 0x8516: - return "TEXTURE_CUBE_MAP_NEGATIVE_X" - case 0x8517: - return "TEXTURE_CUBE_MAP_POSITIVE_Y" - case 0x8518: - return "TEXTURE_CUBE_MAP_NEGATIVE_Y" - case 0x8519: - return "TEXTURE_CUBE_MAP_POSITIVE_Z" - case 0x851a: - return "TEXTURE_CUBE_MAP_NEGATIVE_Z" - case 0x851c: - return "MAX_CUBE_MAP_TEXTURE_SIZE" - case 0x84c0: - return "TEXTURE0" - case 0x84c1: - return "TEXTURE1" - case 0x84c2: - return "TEXTURE2" - case 0x84c3: - return "TEXTURE3" - case 0x84c4: - return "TEXTURE4" - case 0x84c5: - return "TEXTURE5" - case 0x84c6: - return "TEXTURE6" - case 0x84c7: - return "TEXTURE7" - case 0x84c8: - return "TEXTURE8" - case 0x84c9: - return "TEXTURE9" - case 0x84ca: - return "TEXTURE10" - case 0x84cb: - return "TEXTURE11" - case 0x84cc: - return "TEXTURE12" - case 0x84cd: - return "TEXTURE13" - case 0x84ce: - return "TEXTURE14" - case 0x84cf: - return "TEXTURE15" - case 0x84d0: - return "TEXTURE16" - case 0x84d1: - return "TEXTURE17" - case 0x84d2: - return "TEXTURE18" - case 0x84d3: - return "TEXTURE19" - case 0x84d4: - return "TEXTURE20" - case 0x84d5: - return "TEXTURE21" - case 0x84d6: - return "TEXTURE22" - case 0x84d7: - return "TEXTURE23" - case 0x84d8: - return "TEXTURE24" - case 0x84d9: - return "TEXTURE25" - case 0x84da: - return "TEXTURE26" - case 0x84db: - return "TEXTURE27" - case 0x84dc: - return "TEXTURE28" - case 0x84dd: - return "TEXTURE29" - case 0x84de: - return "TEXTURE30" - case 0x84df: - return "TEXTURE31" - case 0x84e0: - return "ACTIVE_TEXTURE" - case 0x2901: - return "REPEAT" - case 0x812f: - return "CLAMP_TO_EDGE" - case 0x8370: - return "MIRRORED_REPEAT" - case 0x8622: - return "VERTEX_ATTRIB_ARRAY_ENABLED" - case 0x8623: - return "VERTEX_ATTRIB_ARRAY_SIZE" - case 0x8624: - return "VERTEX_ATTRIB_ARRAY_STRIDE" - case 0x8625: - return "VERTEX_ATTRIB_ARRAY_TYPE" - case 0x886a: - return "VERTEX_ATTRIB_ARRAY_NORMALIZED" - case 0x8645: - return "VERTEX_ATTRIB_ARRAY_POINTER" - case 0x889f: - return "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING" - case 0x8b9a: - return "IMPLEMENTATION_COLOR_READ_TYPE" - case 0x8b9b: - return "IMPLEMENTATION_COLOR_READ_FORMAT" - case 0x8b81: - return "COMPILE_STATUS" - case 0x8b84: - return "INFO_LOG_LENGTH" - case 0x8b88: - return "SHADER_SOURCE_LENGTH" - case 0x8dfa: - return "SHADER_COMPILER" - case 0x8df8: - return "SHADER_BINARY_FORMATS" - case 0x8df9: - return "NUM_SHADER_BINARY_FORMATS" - case 0x8df0: - return "LOW_FLOAT" - case 0x8df1: - return "MEDIUM_FLOAT" - case 0x8df2: - return "HIGH_FLOAT" - case 0x8df3: - return "LOW_INT" - case 0x8df4: - return "MEDIUM_INT" - case 0x8df5: - return "HIGH_INT" - case 0x8d40: - return "FRAMEBUFFER" - case 0x8d41: - return "RENDERBUFFER" - case 0x8056: - return "RGBA4" - case 0x8057: - return "RGB5_A1" - case 0x8d62: - return "RGB565" - case 0x81a5: - return "DEPTH_COMPONENT16" - case 0x8d48: - return "STENCIL_INDEX8" - case 0x8d42: - return "RENDERBUFFER_WIDTH" - case 0x8d43: - return "RENDERBUFFER_HEIGHT" - case 0x8d44: - return "RENDERBUFFER_INTERNAL_FORMAT" - case 0x8d50: - return "RENDERBUFFER_RED_SIZE" - case 0x8d51: - return "RENDERBUFFER_GREEN_SIZE" - case 0x8d52: - return "RENDERBUFFER_BLUE_SIZE" - case 0x8d53: - return "RENDERBUFFER_ALPHA_SIZE" - case 0x8d54: - return "RENDERBUFFER_DEPTH_SIZE" - case 0x8d55: - return "RENDERBUFFER_STENCIL_SIZE" - case 0x8cd0: - return "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE" - case 0x8cd1: - return "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME" - case 0x8cd2: - return "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL" - case 0x8cd3: - return "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE" - case 0x8ce0: - return "COLOR_ATTACHMENT0" - case 0x8d00: - return "DEPTH_ATTACHMENT" - case 0x8d20: - return "STENCIL_ATTACHMENT" - case 0x8cd5: - return "FRAMEBUFFER_COMPLETE" - case 0x8cd6: - return "FRAMEBUFFER_INCOMPLETE_ATTACHMENT" - case 0x8cd7: - return "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" - case 0x8cd9: - return "FRAMEBUFFER_INCOMPLETE_DIMENSIONS" - case 0x8cdd: - return "FRAMEBUFFER_UNSUPPORTED" - case 0x8ca6: - return "36006" - case 0x8ca7: - return "RENDERBUFFER_BINDING" - case 0x84e8: - return "MAX_RENDERBUFFER_SIZE" - case 0x506: - return "INVALID_FRAMEBUFFER_OPERATION" - case 0x100: - return "DEPTH_BUFFER_BIT" - case 0x400: - return "STENCIL_BUFFER_BIT" - case 0x4000: - return "COLOR_BUFFER_BIT" - case 0x8b50: - return "FLOAT_VEC2" - case 0x8b51: - return "FLOAT_VEC3" - case 0x8b52: - return "FLOAT_VEC4" - case 0x8b53: - return "INT_VEC2" - case 0x8b54: - return "INT_VEC3" - case 0x8b55: - return "INT_VEC4" - case 0x8b56: - return "BOOL" - case 0x8b57: - return "BOOL_VEC2" - case 0x8b58: - return "BOOL_VEC3" - case 0x8b59: - return "BOOL_VEC4" - case 0x8b5a: - return "FLOAT_MAT2" - case 0x8b5b: - return "FLOAT_MAT3" - case 0x8b5c: - return "FLOAT_MAT4" - case 0x8b5e: - return "SAMPLER_2D" - case 0x8b60: - return "SAMPLER_CUBE" - case 0x8b30: - return "FRAGMENT_SHADER" - case 0x8b31: - return "VERTEX_SHADER" - case 0x8a35: - return "ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH" - case 0x8a36: - return "ACTIVE_UNIFORM_BLOCKS" - case 0x911a: - return "ALREADY_SIGNALED" - case 0x8c2f: - return "ANY_SAMPLES_PASSED" - case 0x8d6a: - return "ANY_SAMPLES_PASSED_CONSERVATIVE" - case 0x1905: - return "BLUE" - case 0x911f: - return "BUFFER_ACCESS_FLAGS" - case 0x9120: - return "BUFFER_MAP_LENGTH" - case 0x9121: - return "BUFFER_MAP_OFFSET" - case 0x88bc: - return "BUFFER_MAPPED" - case 0x88bd: - return "BUFFER_MAP_POINTER" - case 0x1800: - return "COLOR" - case 0x8cea: - return "COLOR_ATTACHMENT10" - case 0x8ce1: - return "COLOR_ATTACHMENT1" - case 0x8ceb: - return "COLOR_ATTACHMENT11" - case 0x8cec: - return "COLOR_ATTACHMENT12" - case 0x8ced: - return "COLOR_ATTACHMENT13" - case 0x8cee: - return "COLOR_ATTACHMENT14" - case 0x8cef: - return "COLOR_ATTACHMENT15" - case 0x8ce2: - return "COLOR_ATTACHMENT2" - case 0x8ce3: - return "COLOR_ATTACHMENT3" - case 0x8ce4: - return "COLOR_ATTACHMENT4" - case 0x8ce5: - return "COLOR_ATTACHMENT5" - case 0x8ce6: - return "COLOR_ATTACHMENT6" - case 0x8ce7: - return "COLOR_ATTACHMENT7" - case 0x8ce8: - return "COLOR_ATTACHMENT8" - case 0x8ce9: - return "COLOR_ATTACHMENT9" - case 0x884e: - return "COMPARE_REF_TO_TEXTURE" - case 0x9270: - return "COMPRESSED_R11_EAC" - case 0x9272: - return "COMPRESSED_RG11_EAC" - case 0x9274: - return "COMPRESSED_RGB8_ETC2" - case 0x9276: - return "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2" - case 0x9278: - return "COMPRESSED_RGBA8_ETC2_EAC" - case 0x9271: - return "COMPRESSED_SIGNED_R11_EAC" - case 0x9273: - return "COMPRESSED_SIGNED_RG11_EAC" - case 0x9279: - return "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC" - case 0x9275: - return "COMPRESSED_SRGB8_ETC2" - case 0x9277: - return "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2" - case 0x911c: - return "CONDITION_SATISFIED" - case 0x8f36: - return "36662" - case 0x8f37: - return "36663" - case 0x8865: - return "CURRENT_QUERY" - case 0x1801: - return "DEPTH" - case 0x88f0: - return "DEPTH24_STENCIL8" - case 0x8cad: - return "DEPTH32F_STENCIL8" - case 0x81a6: - return "DEPTH_COMPONENT24" - case 0x8cac: - return "DEPTH_COMPONENT32F" - case 0x84f9: - return "DEPTH_STENCIL" - case 0x821a: - return "DEPTH_STENCIL_ATTACHMENT" - case 0x8825: - return "DRAW_BUFFER0" - case 0x882f: - return "DRAW_BUFFER10" - case 0x8826: - return "DRAW_BUFFER1" - case 0x8830: - return "DRAW_BUFFER11" - case 0x8831: - return "DRAW_BUFFER12" - case 0x8832: - return "DRAW_BUFFER13" - case 0x8833: - return "DRAW_BUFFER14" - case 0x8834: - return "DRAW_BUFFER15" - case 0x8827: - return "DRAW_BUFFER2" - case 0x8828: - return "DRAW_BUFFER3" - case 0x8829: - return "DRAW_BUFFER4" - case 0x882a: - return "DRAW_BUFFER5" - case 0x882b: - return "DRAW_BUFFER6" - case 0x882c: - return "DRAW_BUFFER7" - case 0x882d: - return "DRAW_BUFFER8" - case 0x882e: - return "DRAW_BUFFER9" - case 0x8ca9: - return "DRAW_FRAMEBUFFER" - case 0x88ea: - return "DYNAMIC_COPY" - case 0x88e9: - return "DYNAMIC_READ" - case 0x8dad: - return "FLOAT_32_UNSIGNED_INT_24_8_REV" - case 0x8b65: - return "FLOAT_MAT2x3" - case 0x8b66: - return "FLOAT_MAT2x4" - case 0x8b67: - return "FLOAT_MAT3x2" - case 0x8b68: - return "FLOAT_MAT3x4" - case 0x8b69: - return "FLOAT_MAT4x2" - case 0x8b6a: - return "FLOAT_MAT4x3" - case 0x8b8b: - return "FRAGMENT_SHADER_DERIVATIVE_HINT" - case 0x8215: - return "FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE" - case 0x8214: - return "FRAMEBUFFER_ATTACHMENT_BLUE_SIZE" - case 0x8210: - return "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" - case 0x8211: - return "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" - case 0x8216: - return "FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE" - case 0x8213: - return "FRAMEBUFFER_ATTACHMENT_GREEN_SIZE" - case 0x8212: - return "FRAMEBUFFER_ATTACHMENT_RED_SIZE" - case 0x8217: - return "FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE" - case 0x8cd4: - return "FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER" - case 0x8218: - return "FRAMEBUFFER_DEFAULT" - case 0x8d56: - return "FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" - case 0x8219: - return "FRAMEBUFFER_UNDEFINED" - case 0x1904: - return "GREEN" - case 0x140b: - return "HALF_FLOAT" - case 0x8d9f: - return "INT_2_10_10_10_REV" - case 0x8c8c: - return "INTERLEAVED_ATTRIBS" - case 0x8dca: - return "INT_SAMPLER_2D" - case 0x8dcf: - return "INT_SAMPLER_2D_ARRAY" - case 0x8dcb: - return "INT_SAMPLER_3D" - case 0x8dcc: - return "INT_SAMPLER_CUBE" - case 0xffffffff: - return "INVALID_INDEX" - case 0x821b: - return "MAJOR_VERSION" - case 0x10: - return "MAP_FLUSH_EXPLICIT_BIT" - case 0x8: - return "MAP_INVALIDATE_BUFFER_BIT" - case 0x20: - return "MAP_UNSYNCHRONIZED_BIT" - case 0x8008: - return "MAX" - case 0x8073: - return "MAX_3D_TEXTURE_SIZE" - case 0x88ff: - return "MAX_ARRAY_TEXTURE_LAYERS" - case 0x8cdf: - return "MAX_COLOR_ATTACHMENTS" - case 0x8a33: - return "MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS" - case 0x8a2e: - return "MAX_COMBINED_UNIFORM_BLOCKS" - case 0x8a31: - return "MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS" - case 0x8824: - return "MAX_DRAW_BUFFERS" - case 0x8d6b: - return "MAX_ELEMENT_INDEX" - case 0x80e9: - return "MAX_ELEMENTS_INDICES" - case 0x80e8: - return "MAX_ELEMENTS_VERTICES" - case 0x9125: - return "MAX_FRAGMENT_INPUT_COMPONENTS" - case 0x8a2d: - return "MAX_FRAGMENT_UNIFORM_BLOCKS" - case 0x8b49: - return "MAX_FRAGMENT_UNIFORM_COMPONENTS" - case 0x8905: - return "MAX_PROGRAM_TEXEL_OFFSET" - case 0x8d57: - return "MAX_SAMPLES" - case 0x9111: - return "MAX_SERVER_WAIT_TIMEOUT" - case 0x84fd: - return "MAX_TEXTURE_LOD_BIAS" - case 0x8c8a: - return "MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS" - case 0x8c8b: - return "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS" - case 0x8c80: - return "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS" - case 0x8a30: - return "MAX_UNIFORM_BLOCK_SIZE" - case 0x8a2f: - return "MAX_UNIFORM_BUFFER_BINDINGS" - case 0x8b4b: - return "MAX_VARYING_COMPONENTS" - case 0x9122: - return "MAX_VERTEX_OUTPUT_COMPONENTS" - case 0x8a2b: - return "MAX_VERTEX_UNIFORM_BLOCKS" - case 0x8b4a: - return "MAX_VERTEX_UNIFORM_COMPONENTS" - case 0x8007: - return "MIN" - case 0x821c: - return "MINOR_VERSION" - case 0x8904: - return "MIN_PROGRAM_TEXEL_OFFSET" - case 0x821d: - return "NUM_EXTENSIONS" - case 0x87fe: - return "NUM_PROGRAM_BINARY_FORMATS" - case 0x9380: - return "NUM_SAMPLE_COUNTS" - case 0x9112: - return "OBJECT_TYPE" - case 0xd02: - return "PACK_ROW_LENGTH" - case 0xd04: - return "PACK_SKIP_PIXELS" - case 0xd03: - return "PACK_SKIP_ROWS" - case 0x88eb: - return "PIXEL_PACK_BUFFER" - case 0x88ed: - return "PIXEL_PACK_BUFFER_BINDING" - case 0x88ec: - return "PIXEL_UNPACK_BUFFER" - case 0x88ef: - return "PIXEL_UNPACK_BUFFER_BINDING" - case 0x8d69: - return "PRIMITIVE_RESTART_FIXED_INDEX" - case 0x87ff: - return "PROGRAM_BINARY_FORMATS" - case 0x8741: - return "PROGRAM_BINARY_LENGTH" - case 0x8257: - return "PROGRAM_BINARY_RETRIEVABLE_HINT" - case 0x8866: - return "QUERY_RESULT" - case 0x8867: - return "QUERY_RESULT_AVAILABLE" - case 0x8c3a: - return "R11F_G11F_B10F" - case 0x822d: - return "R16F" - case 0x8233: - return "R16I" - case 0x8234: - return "R16UI" - case 0x822e: - return "R32F" - case 0x8235: - return "R32I" - case 0x8236: - return "R32UI" - case 0x8229: - return "R8" - case 0x8231: - return "R8I" - case 0x8f94: - return "R8_SNORM" - case 0x8232: - return "R8UI" - case 0x8c89: - return "RASTERIZER_DISCARD" - case 0xc02: - return "READ_BUFFER" - case 0x8ca8: - return "READ_FRAMEBUFFER" - case 0x8caa: - return "READ_FRAMEBUFFER_BINDING" - case 0x1903: - return "RED" - case 0x8d94: - return "RED_INTEGER" - case 0x8cab: - return "RENDERBUFFER_SAMPLES" - case 0x8227: - return "RG" - case 0x822f: - return "RG16F" - case 0x8239: - return "RG16I" - case 0x823a: - return "RG16UI" - case 0x8230: - return "RG32F" - case 0x823b: - return "RG32I" - case 0x823c: - return "RG32UI" - case 0x822b: - return "RG8" - case 0x8237: - return "RG8I" - case 0x8f95: - return "RG8_SNORM" - case 0x8238: - return "RG8UI" - case 0x8059: - return "RGB10_A2" - case 0x906f: - return "RGB10_A2UI" - case 0x881b: - return "RGB16F" - case 0x8d89: - return "RGB16I" - case 0x8d77: - return "RGB16UI" - case 0x8815: - return "RGB32F" - case 0x8d83: - return "RGB32I" - case 0x8d71: - return "RGB32UI" - case 0x8051: - return "RGB8" - case 0x8d8f: - return "RGB8I" - case 0x8f96: - return "RGB8_SNORM" - case 0x8d7d: - return "RGB8UI" - case 0x8c3d: - return "RGB9_E5" - case 0x881a: - return "RGBA16F" - case 0x8d88: - return "RGBA16I" - case 0x8d76: - return "RGBA16UI" - case 0x8814: - return "RGBA32F" - case 0x8d82: - return "RGBA32I" - case 0x8d70: - return "RGBA32UI" - case 0x8058: - return "RGBA8" - case 0x8d8e: - return "RGBA8I" - case 0x8f97: - return "RGBA8_SNORM" - case 0x8d7c: - return "RGBA8UI" - case 0x8d99: - return "RGBA_INTEGER" - case 0x8d98: - return "RGB_INTEGER" - case 0x8228: - return "RG_INTEGER" - case 0x8dc1: - return "SAMPLER_2D_ARRAY" - case 0x8dc4: - return "SAMPLER_2D_ARRAY_SHADOW" - case 0x8b62: - return "SAMPLER_2D_SHADOW" - case 0x8b5f: - return "SAMPLER_3D" - case 0x8919: - return "SAMPLER_BINDING" - case 0x8dc5: - return "SAMPLER_CUBE_SHADOW" - case 0x8c8d: - return "SEPARATE_ATTRIBS" - case 0x9119: - return "SIGNALED" - case 0x8f9c: - return "SIGNED_NORMALIZED" - case 0x8c40: - return "SRGB" - case 0x8c41: - return "SRGB8" - case 0x8c43: - return "SRGB8_ALPHA8" - case 0x88e6: - return "STATIC_COPY" - case 0x88e5: - return "STATIC_READ" - case 0x1802: - return "STENCIL" - case 0x88e2: - return "STREAM_COPY" - case 0x88e1: - return "STREAM_READ" - case 0x9113: - return "SYNC_CONDITION" - case 0x9116: - return "SYNC_FENCE" - case 0x9115: - return "SYNC_FLAGS" - case 0x9117: - return "SYNC_GPU_COMMANDS_COMPLETE" - case 0x9114: - return "SYNC_STATUS" - case 0x8c1a: - return "TEXTURE_2D_ARRAY" - case 0x806f: - return "TEXTURE_3D" - case 0x813c: - return "TEXTURE_BASE_LEVEL" - case 0x8c1d: - return "TEXTURE_BINDING_2D_ARRAY" - case 0x806a: - return "TEXTURE_BINDING_3D" - case 0x884d: - return "TEXTURE_COMPARE_FUNC" - case 0x884c: - return "TEXTURE_COMPARE_MODE" - case 0x912f: - return "TEXTURE_IMMUTABLE_FORMAT" - case 0x82df: - return "TEXTURE_IMMUTABLE_LEVELS" - case 0x813d: - return "TEXTURE_MAX_LEVEL" - case 0x813b: - return "TEXTURE_MAX_LOD" - case 0x813a: - return "TEXTURE_MIN_LOD" - case 0x8e45: - return "TEXTURE_SWIZZLE_A" - case 0x8e44: - return "TEXTURE_SWIZZLE_B" - case 0x8e43: - return "TEXTURE_SWIZZLE_G" - case 0x8e42: - return "TEXTURE_SWIZZLE_R" - case 0x8072: - return "TEXTURE_WRAP_R" - case 0x911b: - return "TIMEOUT_EXPIRED" - case 0x8e22: - return "TRANSFORM_FEEDBACK" - case 0x8e24: - return "TRANSFORM_FEEDBACK_ACTIVE" - case 0x8e25: - return "TRANSFORM_FEEDBACK_BINDING" - case 0x8c8e: - return "TRANSFORM_FEEDBACK_BUFFER" - case 0x8c8f: - return "TRANSFORM_FEEDBACK_BUFFER_BINDING" - case 0x8c7f: - return "TRANSFORM_FEEDBACK_BUFFER_MODE" - case 0x8c85: - return "TRANSFORM_FEEDBACK_BUFFER_SIZE" - case 0x8c84: - return "TRANSFORM_FEEDBACK_BUFFER_START" - case 0x8e23: - return "TRANSFORM_FEEDBACK_PAUSED" - case 0x8c88: - return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN" - case 0x8c76: - return "TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH" - case 0x8c83: - return "TRANSFORM_FEEDBACK_VARYINGS" - case 0x8a3c: - return "UNIFORM_ARRAY_STRIDE" - case 0x8a43: - return "UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES" - case 0x8a42: - return "UNIFORM_BLOCK_ACTIVE_UNIFORMS" - case 0x8a3f: - return "UNIFORM_BLOCK_BINDING" - case 0x8a40: - return "UNIFORM_BLOCK_DATA_SIZE" - case 0x8a3a: - return "UNIFORM_BLOCK_INDEX" - case 0x8a41: - return "UNIFORM_BLOCK_NAME_LENGTH" - case 0x8a46: - return "UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER" - case 0x8a44: - return "UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER" - case 0x8a11: - return "UNIFORM_BUFFER" - case 0x8a28: - return "UNIFORM_BUFFER_BINDING" - case 0x8a34: - return "UNIFORM_BUFFER_OFFSET_ALIGNMENT" - case 0x8a2a: - return "UNIFORM_BUFFER_SIZE" - case 0x8a29: - return "UNIFORM_BUFFER_START" - case 0x8a3e: - return "UNIFORM_IS_ROW_MAJOR" - case 0x8a3d: - return "UNIFORM_MATRIX_STRIDE" - case 0x8a39: - return "UNIFORM_NAME_LENGTH" - case 0x8a3b: - return "UNIFORM_OFFSET" - case 0x8a38: - return "UNIFORM_SIZE" - case 0x8a37: - return "UNIFORM_TYPE" - case 0x806e: - return "UNPACK_IMAGE_HEIGHT" - case 0xcf2: - return "UNPACK_ROW_LENGTH" - case 0x806d: - return "UNPACK_SKIP_IMAGES" - case 0xcf4: - return "UNPACK_SKIP_PIXELS" - case 0xcf3: - return "UNPACK_SKIP_ROWS" - case 0x9118: - return "UNSIGNALED" - case 0x8c3b: - return "UNSIGNED_INT_10F_11F_11F_REV" - case 0x8368: - return "UNSIGNED_INT_2_10_10_10_REV" - case 0x84fa: - return "UNSIGNED_INT_24_8" - case 0x8c3e: - return "UNSIGNED_INT_5_9_9_9_REV" - case 0x8dd2: - return "UNSIGNED_INT_SAMPLER_2D" - case 0x8dd7: - return "UNSIGNED_INT_SAMPLER_2D_ARRAY" - case 0x8dd3: - return "UNSIGNED_INT_SAMPLER_3D" - case 0x8dd4: - return "UNSIGNED_INT_SAMPLER_CUBE" - case 0x8dc6: - return "UNSIGNED_INT_VEC2" - case 0x8dc7: - return "UNSIGNED_INT_VEC3" - case 0x8dc8: - return "UNSIGNED_INT_VEC4" - case 0x8c17: - return "UNSIGNED_NORMALIZED" - case 0x85b5: - return "VERTEX_ARRAY_BINDING" - case 0x88fe: - return "VERTEX_ATTRIB_ARRAY_DIVISOR" - case 0x88fd: - return "VERTEX_ATTRIB_ARRAY_INTEGER" - case 0x911d: - return "WAIT_FAILED" - default: - return fmt.Sprintf("gl.Enum(0x%x)", uint32(v)) - } -} - -func (ctx *context) ActiveTexture(texture Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ActiveTexture(%v) %v", texture, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnActiveTexture, - a0: texture.c(), - }, - blocking: true}) -} - -func (ctx *context) AttachShader(p Program, s Shader) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.AttachShader(%v, %v) %v", p, s, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnAttachShader, - a0: p.c(), - a1: s.c(), - }, - blocking: true}) -} - -func (ctx *context) BindAttribLocation(p Program, a Attrib, name string) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BindAttribLocation(%v, %v, %v) %v", p, a, name, errstr) - }() - s, free := ctx.cString(name) - defer free() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBindAttribLocation, - a0: p.c(), - a1: a.c(), - a2: s, - }, - blocking: true, - }) -} - -func (ctx *context) BindBuffer(target Enum, b Buffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BindBuffer(%v, %v) %v", target, b, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBindBuffer, - a0: target.c(), - a1: b.c(), - }, - blocking: true}) -} - -func (ctx *context) BindFramebuffer(target Enum, fb Framebuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BindFramebuffer(%v, %v) %v", target, fb, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBindFramebuffer, - a0: target.c(), - a1: fb.c(), - }, - blocking: true}) -} - -func (ctx *context) BindRenderbuffer(target Enum, rb Renderbuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BindRenderbuffer(%v, %v) %v", target, rb, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBindRenderbuffer, - a0: target.c(), - a1: rb.c(), - }, - blocking: true}) -} - -func (ctx *context) BindTexture(target Enum, t Texture) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BindTexture(%v, %v) %v", target, t, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBindTexture, - a0: target.c(), - a1: t.c(), - }, - blocking: true}) -} - -func (ctx *context) BindVertexArray(va VertexArray) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BindVertexArray(%v) %v", va, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBindVertexArray, - a0: va.c(), - }, - blocking: true}) -} - -func (ctx *context) BlendColor(red, green, blue, alpha float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BlendColor(%v, %v, %v, %v) %v", red, green, blue, alpha, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBlendColor, - a0: uintptr(math.Float32bits(red)), - a1: uintptr(math.Float32bits(green)), - a2: uintptr(math.Float32bits(blue)), - a3: uintptr(math.Float32bits(alpha)), - }, - blocking: true}) -} - -func (ctx *context) BlendEquation(mode Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BlendEquation(%v) %v", mode, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBlendEquation, - a0: mode.c(), - }, - blocking: true}) -} - -func (ctx *context) BlendEquationSeparate(modeRGB, modeAlpha Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BlendEquationSeparate(%v, %v) %v", modeRGB, modeAlpha, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBlendEquationSeparate, - a0: modeRGB.c(), - a1: modeAlpha.c(), - }, - blocking: true}) -} - -func (ctx *context) BlendFunc(sfactor, dfactor Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BlendFunc(%v, %v) %v", sfactor, dfactor, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBlendFunc, - a0: sfactor.c(), - a1: dfactor.c(), - }, - blocking: true}) -} - -func (ctx *context) BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BlendFuncSeparate(%v, %v, %v, %v) %v", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBlendFuncSeparate, - a0: sfactorRGB.c(), - a1: dfactorRGB.c(), - a2: sfactorAlpha.c(), - a3: dfactorAlpha.c(), - }, - blocking: true}) -} - -func (ctx *context) BufferData(target Enum, src []byte, usage Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BufferData(%v, len(%d), %v) %v", target, len(src), usage, errstr) - }() - parg := unsafe.Pointer(nil) - if len(src) > 0 { - parg = unsafe.Pointer(&src[0]) - } - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBufferData, - a0: target.c(), - a1: uintptr(len(src)), - a2: usage.c(), - }, - parg: parg, - blocking: true, - }) -} - -func (ctx *context) BufferInit(target Enum, size int, usage Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BufferInit(%v, %v, %v) %v", target, size, usage, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBufferData, - a0: target.c(), - a1: uintptr(size), - a2: usage.c(), - }, - parg: unsafe.Pointer(nil), - blocking: true}) -} - -func (ctx *context) BufferSubData(target Enum, offset int, data []byte) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BufferSubData(%v, %v, len(%d)) %v", target, offset, len(data), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBufferSubData, - a0: target.c(), - a1: uintptr(offset), - a2: uintptr(len(data)), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) CheckFramebufferStatus(target Enum) (r0 Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CheckFramebufferStatus(%v) %v%v", target, r0, errstr) - }() - return Enum(ctx.enqueue(call{ - args: fnargs{ - fn: glfnCheckFramebufferStatus, - a0: target.c(), - }, - blocking: true, - })) -} - -func (ctx *context) Clear(mask Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Clear(%v) %v", mask, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnClear, - a0: uintptr(mask), - }, - blocking: true}) -} - -func (ctx *context) ClearColor(red, green, blue, alpha float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ClearColor(%v, %v, %v, %v) %v", red, green, blue, alpha, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnClearColor, - a0: uintptr(math.Float32bits(red)), - a1: uintptr(math.Float32bits(green)), - a2: uintptr(math.Float32bits(blue)), - a3: uintptr(math.Float32bits(alpha)), - }, - blocking: true}) -} - -func (ctx *context) ClearDepthf(d float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ClearDepthf(%v) %v", d, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnClearDepthf, - a0: uintptr(math.Float32bits(d)), - }, - blocking: true}) -} - -func (ctx *context) ClearStencil(s int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ClearStencil(%v) %v", s, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnClearStencil, - a0: uintptr(s), - }, - blocking: true}) -} - -func (ctx *context) ColorMask(red, green, blue, alpha bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ColorMask(%v, %v, %v, %v) %v", red, green, blue, alpha, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnColorMask, - a0: glBoolean(red), - a1: glBoolean(green), - a2: glBoolean(blue), - a3: glBoolean(alpha), - }, - blocking: true}) -} - -func (ctx *context) CompileShader(s Shader) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CompileShader(%v) %v", s, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnCompileShader, - a0: s.c(), - }, - blocking: true}) -} - -func (ctx *context) CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CompressedTexImage2D(%v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, internalformat, width, height, border, len(data), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnCompressedTexImage2D, - a0: target.c(), - a1: uintptr(level), - a2: internalformat.c(), - a3: uintptr(width), - a4: uintptr(height), - a5: uintptr(border), - a6: uintptr(len(data)), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CompressedTexSubImage2D(%v, %v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, xoffset, yoffset, width, height, format, len(data), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnCompressedTexSubImage2D, - a0: target.c(), - a1: uintptr(level), - a2: uintptr(xoffset), - a3: uintptr(yoffset), - a4: uintptr(width), - a5: uintptr(height), - a6: format.c(), - a7: uintptr(len(data)), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CopyTexImage2D(%v, %v, %v, %v, %v, %v, %v, %v) %v", target, level, internalformat, x, y, width, height, border, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnCopyTexImage2D, - a0: target.c(), - a1: uintptr(level), - a2: internalformat.c(), - a3: uintptr(x), - a4: uintptr(y), - a5: uintptr(width), - a6: uintptr(height), - a7: uintptr(border), - }, - blocking: true}) -} - -func (ctx *context) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CopyTexSubImage2D(%v, %v, %v, %v, %v, %v, %v, %v) %v", target, level, xoffset, yoffset, x, y, width, height, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnCopyTexSubImage2D, - a0: target.c(), - a1: uintptr(level), - a2: uintptr(xoffset), - a3: uintptr(yoffset), - a4: uintptr(x), - a5: uintptr(y), - a6: uintptr(width), - a7: uintptr(height), - }, - blocking: true}) -} - -func (ctx *context) CreateBuffer() (r0 Buffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateBuffer() %v%v", r0, errstr) - }() - return Buffer{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenBuffer, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateFramebuffer() (r0 Framebuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateFramebuffer() %v%v", r0, errstr) - }() - return Framebuffer{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenFramebuffer, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateProgram() (r0 Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateProgram() %v%v", r0, errstr) - }() - return Program{ - Init: true, - Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnCreateProgram, - }, - blocking: true, - }, - ))} -} - -func (ctx *context) CreateRenderbuffer() (r0 Renderbuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateRenderbuffer() %v%v", r0, errstr) - }() - return Renderbuffer{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenRenderbuffer, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateShader(ty Enum) (r0 Shader) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateShader(%v) %v%v", ty, r0, errstr) - }() - return Shader{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnCreateShader, - a0: uintptr(ty), - }, - blocking: true, - }))} -} - -func (ctx *context) CreateTexture() (r0 Texture) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateTexture() %v%v", r0, errstr) - }() - return Texture{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenTexture, - }, - blocking: true, - }))} -} - -func (ctx *context) CreateVertexArray() (r0 VertexArray) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CreateVertexArray() %v%v", r0, errstr) - }() - return VertexArray{Value: uint32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGenVertexArray, - }, - blocking: true, - }))} -} - -func (ctx *context) CullFace(mode Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.CullFace(%v) %v", mode, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnCullFace, - a0: mode.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteBuffer(v Buffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteBuffer(%v) %v", v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteBuffer, - a0: v.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteFramebuffer(v Framebuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteFramebuffer(%v) %v", v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteFramebuffer, - a0: v.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteProgram(p Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteProgram(%v) %v", p, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteProgram, - a0: p.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteRenderbuffer(v Renderbuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteRenderbuffer(%v) %v", v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteRenderbuffer, - a0: v.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteShader(s Shader) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteShader(%v) %v", s, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteShader, - a0: s.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteTexture(v Texture) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteTexture(%v) %v", v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteTexture, - a0: v.c(), - }, - blocking: true}) -} - -func (ctx *context) DeleteVertexArray(v VertexArray) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DeleteVertexArray(%v) %v", v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDeleteVertexArray, - a0: v.c(), - }, - blocking: true}) -} - -func (ctx *context) DepthFunc(fn Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DepthFunc(%v) %v", fn, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDepthFunc, - a0: fn.c(), - }, - blocking: true}) -} - -func (ctx *context) DepthMask(flag bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DepthMask(%v) %v", flag, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDepthMask, - a0: glBoolean(flag), - }, - blocking: true}) -} - -func (ctx *context) DepthRangef(n, f float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DepthRangef(%v, %v) %v", n, f, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDepthRangef, - a0: uintptr(math.Float32bits(n)), - a1: uintptr(math.Float32bits(f)), - }, - blocking: true}) -} - -func (ctx *context) DetachShader(p Program, s Shader) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DetachShader(%v, %v) %v", p, s, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDetachShader, - a0: p.c(), - a1: s.c(), - }, - blocking: true}) -} - -func (ctx *context) Disable(cap Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Disable(%v) %v", cap, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDisable, - a0: cap.c(), - }, - blocking: true}) -} - -func (ctx *context) DisableVertexAttribArray(a Attrib) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DisableVertexAttribArray(%v) %v", a, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDisableVertexAttribArray, - a0: a.c(), - }, - blocking: true}) -} - -func (ctx *context) DrawArrays(mode Enum, first, count int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DrawArrays(%v, %v, %v) %v", mode, first, count, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDrawArrays, - a0: mode.c(), - a1: uintptr(first), - a2: uintptr(count), - }, - blocking: true}) -} - -func (ctx *context) DrawElements(mode Enum, count int, ty Enum, offset int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.DrawElements(%v, %v, %v, %v) %v", mode, count, ty, offset, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnDrawElements, - a0: mode.c(), - a1: uintptr(count), - a2: ty.c(), - a3: uintptr(offset), - }, - blocking: true}) -} - -func (ctx *context) Enable(cap Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Enable(%v) %v", cap, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnEnable, - a0: cap.c(), - }, - blocking: true}) -} - -func (ctx *context) EnableVertexAttribArray(a Attrib) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.EnableVertexAttribArray(%v) %v", a, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnEnableVertexAttribArray, - a0: a.c(), - }, - blocking: true}) -} - -func (ctx *context) Finish() { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Finish() %v", errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnFinish, - }, - blocking: true, - }) -} - -func (ctx *context) Flush() { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Flush() %v", errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnFlush, - }, - blocking: true, - }) -} - -func (ctx *context) FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.FramebufferRenderbuffer(%v, %v, %v, %v) %v", target, attachment, rbTarget, rb, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnFramebufferRenderbuffer, - a0: target.c(), - a1: attachment.c(), - a2: rbTarget.c(), - a3: rb.c(), - }, - blocking: true}) -} - -func (ctx *context) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.FramebufferTexture2D(%v, %v, %v, %v, %v) %v", target, attachment, texTarget, t, level, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnFramebufferTexture2D, - a0: target.c(), - a1: attachment.c(), - a2: texTarget.c(), - a3: t.c(), - a4: uintptr(level), - }, - blocking: true}) -} - -func (ctx *context) FrontFace(mode Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.FrontFace(%v) %v", mode, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnFrontFace, - a0: mode.c(), - }, - blocking: true}) -} - -func (ctx *context) GenerateMipmap(target Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GenerateMipmap(%v) %v", target, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGenerateMipmap, - a0: target.c(), - }, - blocking: true}) -} - -func (ctx *context) GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetActiveAttrib(%v, %v) (%v, %v, %v) %v", p, index, name, size, ty, errstr) - }() - bufSize := ctx.GetProgrami(p, ACTIVE_ATTRIBUTE_MAX_LENGTH) - buf := make([]byte, bufSize) - var cType int - cSize := ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetActiveAttrib, - a0: p.c(), - a1: uintptr(index), - a2: uintptr(bufSize), - a3: uintptr(unsafe.Pointer(&cType)), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - return goString(buf), int(cSize), Enum(cType) -} - -func (ctx *context) GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetActiveUniform(%v, %v) (%v, %v, %v) %v", p, index, name, size, ty, errstr) - }() - bufSize := ctx.GetProgrami(p, ACTIVE_UNIFORM_MAX_LENGTH) - buf := make([]byte, bufSize+8) - var cType int - cSize := ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetActiveUniform, - a0: p.c(), - a1: uintptr(index), - a2: uintptr(bufSize), - a3: uintptr(unsafe.Pointer(&cType)), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - return goString(buf), int(cSize), Enum(cType) -} - -func (ctx *context) GetAttachedShaders(p Program) (r0 []Shader) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetAttachedShaders(%v) %v%v", p, r0, errstr) - }() - shadersLen := ctx.GetProgrami(p, ATTACHED_SHADERS) - if shadersLen == 0 { - return nil - } - buf := make([]uint32, shadersLen) - n := int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetAttachedShaders, - a0: p.c(), - a1: uintptr(shadersLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - })) - buf = buf[:int(n)] - shaders := make([]Shader, len(buf)) - for i, s := range buf { - shaders[i] = Shader{Value: uint32(s)} - } - return shaders -} - -func (ctx *context) GetAttribLocation(p Program, name string) (r0 Attrib) { - defer func() { - errstr := ctx.errDrain() - r0.name = name - log.Printf("gl.GetAttribLocation(%v, %v) %v%v", p, name, r0, errstr) - }() - s, free := ctx.cString(name) - defer free() - return Attrib{Value: uint(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetAttribLocation, - a0: p.c(), - a1: s, - }, - blocking: true, - }))} -} - -func (ctx *context) GetBooleanv(dst []bool, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetBooleanv(%v, %v) %v", dst, pname, errstr) - }() - buf := make([]int32, len(dst)) - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetBooleanv, - a0: pname.c(), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - for i, v := range buf { - dst[i] = v != 0 - } -} - -func (ctx *context) GetFloatv(dst []float32, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetFloatv(len(%d), %v) %v", len(dst), pname, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetFloatv, - a0: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetIntegerv(dst []int32, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetIntegerv(%v, %v) %v", dst, pname, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetIntegerv, - a0: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetInteger(pname Enum) (r0 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetInteger(%v) %v%v", pname, r0, errstr) - }() - var v [1]int32 - ctx.GetIntegerv(v[:], pname) - return int(v[0]) -} - -func (ctx *context) GetBufferParameteri(target, value Enum) (r0 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetBufferParameteri(%v, %v) %v%v", target, value, r0, errstr) - }() - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetBufferParameteri, - a0: target.c(), - a1: value.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetError() (r0 Enum) { - return Enum(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetError, - }, - blocking: true, - })) -} - -func (ctx *context) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) (r0 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetFramebufferAttachmentParameteri(%v, %v, %v) %v%v", target, attachment, pname, r0, errstr) - }() - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetFramebufferAttachmentParameteriv, - a0: target.c(), - a1: attachment.c(), - a2: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetProgrami(p Program, pname Enum) (r0 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetProgrami(%v, %v) %v%v", p, pname, r0, errstr) - }() - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetProgramiv, - a0: p.c(), - a1: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetProgramInfoLog(p Program) (r0 string) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetProgramInfoLog(%v) %v%v", p, r0, errstr) - }() - infoLen := ctx.GetProgrami(p, INFO_LOG_LENGTH) - if infoLen == 0 { - return "" - } - buf := make([]byte, infoLen) - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetProgramInfoLog, - a0: p.c(), - a1: uintptr(infoLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - return goString(buf) -} - -func (ctx *context) GetRenderbufferParameteri(target, pname Enum) (r0 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetRenderbufferParameteri(%v, %v) %v%v", target, pname, r0, errstr) - }() - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetRenderbufferParameteriv, - a0: target.c(), - a1: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetShaderi(s Shader, pname Enum) (r0 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetShaderi(%v, %v) %v%v", s, pname, r0, errstr) - }() - return int(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetShaderiv, - a0: s.c(), - a1: pname.c(), - }, - blocking: true, - })) -} - -func (ctx *context) GetShaderInfoLog(s Shader) (r0 string) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetShaderInfoLog(%v) %v%v", s, r0, errstr) - }() - infoLen := ctx.GetShaderi(s, INFO_LOG_LENGTH) - if infoLen == 0 { - return "" - } - buf := make([]byte, infoLen) - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetShaderInfoLog, - a0: s.c(), - a1: uintptr(infoLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - return goString(buf) -} - -func (ctx *context) GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetShaderPrecisionFormat(%v, %v) (%v, %v, %v) %v", shadertype, precisiontype, rangeLow, rangeHigh, precision, errstr) - }() - var rangeAndPrec [3]int32 - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetShaderPrecisionFormat, - a0: shadertype.c(), - a1: precisiontype.c(), - }, - parg: unsafe.Pointer(&rangeAndPrec[0]), - blocking: true, - }) - return int(rangeAndPrec[0]), int(rangeAndPrec[1]), int(rangeAndPrec[2]) -} - -func (ctx *context) GetShaderSource(s Shader) (r0 string) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetShaderSource(%v) %v%v", s, r0, errstr) - }() - sourceLen := ctx.GetShaderi(s, SHADER_SOURCE_LENGTH) - if sourceLen == 0 { - return "" - } - buf := make([]byte, sourceLen) - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetShaderSource, - a0: s.c(), - a1: uintptr(sourceLen), - }, - parg: unsafe.Pointer(&buf[0]), - blocking: true, - }) - return goString(buf) -} - -func (ctx *context) GetString(pname Enum) (r0 string) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetString(%v) %v%v", pname, r0, errstr) - }() - ret := ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetString, - a0: pname.c(), - }, - blocking: true, - }) - retp := unsafe.Pointer(ret) - buf := (*[1 << 24]byte)(retp)[:] - return goString(buf) -} - -func (ctx *context) GetTexParameterfv(dst []float32, target, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetTexParameterfv(len(%d), %v, %v) %v", len(dst), target, pname, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetTexParameterfv, - a0: target.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetTexParameteriv(dst []int32, target, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetTexParameteriv(%v, %v, %v) %v", dst, target, pname, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetTexParameteriv, - a0: target.c(), - a1: pname.c(), - }, - blocking: true, - }) -} - -func (ctx *context) GetUniformfv(dst []float32, src Uniform, p Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetUniformfv(len(%d), %v, %v) %v", len(dst), src, p, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetUniformfv, - a0: p.c(), - a1: src.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetUniformiv(dst []int32, src Uniform, p Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetUniformiv(%v, %v, %v) %v", dst, src, p, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetUniformiv, - a0: p.c(), - a1: src.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetUniformLocation(p Program, name string) (r0 Uniform) { - defer func() { - errstr := ctx.errDrain() - r0.name = name - log.Printf("gl.GetUniformLocation(%v, %v) %v%v", p, name, r0, errstr) - }() - s, free := ctx.cString(name) - defer free() - return Uniform{Value: int32(ctx.enqueue(call{ - args: fnargs{ - fn: glfnGetUniformLocation, - a0: p.c(), - a1: s, - }, - blocking: true, - }))} -} - -func (ctx *context) GetVertexAttribf(src Attrib, pname Enum) (r0 float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetVertexAttribf(%v, %v) %v%v", src, pname, r0, errstr) - }() - var params [1]float32 - ctx.GetVertexAttribfv(params[:], src, pname) - return params[0] -} - -func (ctx *context) GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetVertexAttribfv(len(%d), %v, %v) %v", len(dst), src, pname, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetVertexAttribfv, - a0: src.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) GetVertexAttribi(src Attrib, pname Enum) (r0 int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetVertexAttribi(%v, %v) %v%v", src, pname, r0, errstr) - }() - var params [1]int32 - ctx.GetVertexAttribiv(params[:], src, pname) - return params[0] -} - -func (ctx *context) GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.GetVertexAttribiv(%v, %v, %v) %v", dst, src, pname, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnGetVertexAttribiv, - a0: src.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) Hint(target, mode Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Hint(%v, %v) %v", target, mode, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnHint, - a0: target.c(), - a1: mode.c(), - }, - blocking: true}) -} - -func (ctx *context) IsBuffer(b Buffer) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsBuffer(%v) %v%v", b, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsBuffer, - a0: b.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsEnabled(cap Enum) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsEnabled(%v) %v%v", cap, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsEnabled, - a0: cap.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsFramebuffer(fb Framebuffer) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsFramebuffer(%v) %v%v", fb, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsFramebuffer, - a0: fb.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsProgram(p Program) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsProgram(%v) %v%v", p, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsProgram, - a0: p.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsRenderbuffer(rb Renderbuffer) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsRenderbuffer(%v) %v%v", rb, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsRenderbuffer, - a0: rb.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsShader(s Shader) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsShader(%v) %v%v", s, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsShader, - a0: s.c(), - }, - blocking: true, - }) -} - -func (ctx *context) IsTexture(t Texture) (r0 bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.IsTexture(%v) %v%v", t, r0, errstr) - }() - return 0 != ctx.enqueue(call{ - args: fnargs{ - fn: glfnIsTexture, - a0: t.c(), - }, - blocking: true, - }) -} - -func (ctx *context) LineWidth(width float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.LineWidth(%v) %v", width, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnLineWidth, - a0: uintptr(math.Float32bits(width)), - }, - blocking: true}) -} - -func (ctx *context) LinkProgram(p Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.LinkProgram(%v) %v", p, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnLinkProgram, - a0: p.c(), - }, - blocking: true}) -} - -func (ctx *context) PixelStorei(pname Enum, param int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.PixelStorei(%v, %v) %v", pname, param, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnPixelStorei, - a0: pname.c(), - a1: uintptr(param), - }, - blocking: true}) -} - -func (ctx *context) PolygonOffset(factor, units float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.PolygonOffset(%v, %v) %v", factor, units, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnPolygonOffset, - a0: uintptr(math.Float32bits(factor)), - a1: uintptr(math.Float32bits(units)), - }, - blocking: true}) -} - -func (ctx *context) ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ReadPixels(len(%d), %v, %v, %v, %v, %v, %v) %v", len(dst), x, y, width, height, format, ty, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnReadPixels, - - a0: uintptr(x), - a1: uintptr(y), - a2: uintptr(width), - a3: uintptr(height), - a4: format.c(), - a5: ty.c(), - }, - parg: unsafe.Pointer(&dst[0]), - blocking: true, - }) -} - -func (ctx *context) ReleaseShaderCompiler() { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ReleaseShaderCompiler() %v", errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnReleaseShaderCompiler, - }, - blocking: true}) -} - -func (ctx *context) RenderbufferStorage(target, internalFormat Enum, width, height int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.RenderbufferStorage(%v, %v, %v, %v) %v", target, internalFormat, width, height, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnRenderbufferStorage, - a0: target.c(), - a1: internalFormat.c(), - a2: uintptr(width), - a3: uintptr(height), - }, - blocking: true}) -} - -func (ctx *context) SampleCoverage(value float32, invert bool) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.SampleCoverage(%v, %v) %v", value, invert, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnSampleCoverage, - a0: uintptr(math.Float32bits(value)), - a1: glBoolean(invert), - }, - blocking: true}) -} - -func (ctx *context) Scissor(x, y, width, height int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Scissor(%v, %v, %v, %v) %v", x, y, width, height, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnScissor, - a0: uintptr(x), - a1: uintptr(y), - a2: uintptr(width), - a3: uintptr(height), - }, - blocking: true}) -} - -func (ctx *context) ShaderSource(s Shader, src string) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ShaderSource(%v, %v) %v", s, src, errstr) - }() - strp, free := ctx.cStringPtr(src) - defer free() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnShaderSource, - a0: s.c(), - a1: 1, - a2: strp, - }, - blocking: true, - }) -} - -func (ctx *context) StencilFunc(fn Enum, ref int, mask uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.StencilFunc(%v, %v, %v) %v", fn, ref, mask, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnStencilFunc, - a0: fn.c(), - a1: uintptr(ref), - a2: uintptr(mask), - }, - blocking: true}) -} - -func (ctx *context) StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.StencilFuncSeparate(%v, %v, %v, %v) %v", face, fn, ref, mask, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnStencilFuncSeparate, - a0: face.c(), - a1: fn.c(), - a2: uintptr(ref), - a3: uintptr(mask), - }, - blocking: true}) -} - -func (ctx *context) StencilMask(mask uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.StencilMask(%v) %v", mask, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnStencilMask, - a0: uintptr(mask), - }, - blocking: true}) -} - -func (ctx *context) StencilMaskSeparate(face Enum, mask uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.StencilMaskSeparate(%v, %v) %v", face, mask, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnStencilMaskSeparate, - a0: face.c(), - a1: uintptr(mask), - }, - blocking: true}) -} - -func (ctx *context) StencilOp(fail, zfail, zpass Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.StencilOp(%v, %v, %v) %v", fail, zfail, zpass, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnStencilOp, - a0: fail.c(), - a1: zfail.c(), - a2: zpass.c(), - }, - blocking: true}) -} - -func (ctx *context) StencilOpSeparate(face, sfail, dpfail, dppass Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.StencilOpSeparate(%v, %v, %v, %v) %v", face, sfail, dpfail, dppass, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnStencilOpSeparate, - a0: face.c(), - a1: sfail.c(), - a2: dpfail.c(), - a3: dppass.c(), - }, - blocking: true}) -} - -func (ctx *context) TexImage2D(target Enum, level int, internalFormat int, width, height int, format Enum, ty Enum, data []byte) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.TexImage2D(%v, %v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, internalFormat, width, height, format, ty, len(data), errstr) - }() - parg := unsafe.Pointer(nil) - if len(data) > 0 { - parg = unsafe.Pointer(&data[0]) - } - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnTexImage2D, - - a0: target.c(), - a1: uintptr(level), - a2: uintptr(internalFormat), - a3: uintptr(width), - a4: uintptr(height), - a5: format.c(), - a6: ty.c(), - }, - parg: parg, - blocking: true, - }) -} - -func (ctx *context) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.TexSubImage2D(%v, %v, %v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, x, y, width, height, format, ty, len(data), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnTexSubImage2D, - - a0: target.c(), - a1: uintptr(level), - a2: uintptr(x), - a3: uintptr(y), - a4: uintptr(width), - a5: uintptr(height), - a6: format.c(), - a7: ty.c(), - }, - parg: unsafe.Pointer(&data[0]), - blocking: true, - }) -} - -func (ctx *context) TexParameterf(target, pname Enum, param float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.TexParameterf(%v, %v, %v) %v", target, pname, param, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnTexParameterf, - a0: target.c(), - a1: pname.c(), - a2: uintptr(math.Float32bits(param)), - }, - blocking: true}) -} - -func (ctx *context) TexParameterfv(target, pname Enum, params []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.TexParameterfv(%v, %v, len(%d)) %v", target, pname, len(params), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnTexParameterfv, - a0: target.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(¶ms[0]), - blocking: true, - }) -} - -func (ctx *context) TexParameteri(target, pname Enum, param int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.TexParameteri(%v, %v, %v) %v", target, pname, param, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnTexParameteri, - a0: target.c(), - a1: pname.c(), - a2: uintptr(param), - }, - blocking: true}) -} - -func (ctx *context) TexParameteriv(target, pname Enum, params []int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.TexParameteriv(%v, %v, %v) %v", target, pname, params, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnTexParameteriv, - a0: target.c(), - a1: pname.c(), - }, - parg: unsafe.Pointer(¶ms[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform1f(dst Uniform, v float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform1f(%v, %v) %v", dst, v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform1f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v)), - }, - blocking: true}) -} - -func (ctx *context) Uniform1fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform1fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform1fv, - a0: dst.c(), - a1: uintptr(len(src)), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform1i(dst Uniform, v int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform1i(%v, %v) %v", dst, v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform1i, - a0: dst.c(), - a1: uintptr(v), - }, - blocking: true}) -} - -func (ctx *context) Uniform1iv(dst Uniform, src []int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform1iv(%v, %v) %v", dst, src, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform1iv, - a0: dst.c(), - a1: uintptr(len(src)), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform2f(dst Uniform, v0, v1 float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform2f(%v, %v, %v) %v", dst, v0, v1, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform2f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v0)), - a2: uintptr(math.Float32bits(v1)), - }, - blocking: true}) -} - -func (ctx *context) Uniform2fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform2fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform2fv, - a0: dst.c(), - a1: uintptr(len(src) / 2), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform2i(dst Uniform, v0, v1 int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform2i(%v, %v, %v) %v", dst, v0, v1, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform2i, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - }, - blocking: true}) -} - -func (ctx *context) Uniform2iv(dst Uniform, src []int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform2iv(%v, %v) %v", dst, src, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform2iv, - a0: dst.c(), - a1: uintptr(len(src) / 2), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform3f(dst Uniform, v0, v1, v2 float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform3f(%v, %v, %v, %v) %v", dst, v0, v1, v2, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform3f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v0)), - a2: uintptr(math.Float32bits(v1)), - a3: uintptr(math.Float32bits(v2)), - }, - blocking: true}) -} - -func (ctx *context) Uniform3fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform3fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform3fv, - a0: dst.c(), - a1: uintptr(len(src) / 3), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform3i(dst Uniform, v0, v1, v2 int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform3i(%v, %v, %v, %v) %v", dst, v0, v1, v2, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform3i, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - }, - blocking: true}) -} - -func (ctx *context) Uniform3iv(dst Uniform, src []int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform3iv(%v, %v) %v", dst, src, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform3iv, - a0: dst.c(), - a1: uintptr(len(src) / 3), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform4f(%v, %v, %v, %v, %v) %v", dst, v0, v1, v2, v3, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform4f, - a0: dst.c(), - a1: uintptr(math.Float32bits(v0)), - a2: uintptr(math.Float32bits(v1)), - a3: uintptr(math.Float32bits(v2)), - a4: uintptr(math.Float32bits(v3)), - }, - blocking: true}) -} - -func (ctx *context) Uniform4fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform4fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform4fv, - a0: dst.c(), - a1: uintptr(len(src) / 4), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform4i(%v, %v, %v, %v, %v) %v", dst, v0, v1, v2, v3, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform4i, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - a4: uintptr(v3), - }, - blocking: true}) -} - -func (ctx *context) Uniform4iv(dst Uniform, src []int32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform4iv(%v, %v) %v", dst, src, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform4iv, - a0: dst.c(), - a1: uintptr(len(src) / 4), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UniformMatrix2fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix2fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix2fv, - - a0: dst.c(), - a1: uintptr(len(src) / 4), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UniformMatrix3fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix3fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix3fv, - a0: dst.c(), - a1: uintptr(len(src) / 9), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UniformMatrix4fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix4fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix4fv, - a0: dst.c(), - a1: uintptr(len(src) / 16), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) UseProgram(p Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UseProgram(%v) %v", p, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUseProgram, - a0: p.c(), - }, - blocking: true}) -} - -func (ctx *context) ValidateProgram(p Program) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.ValidateProgram(%v) %v", p, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnValidateProgram, - a0: p.c(), - }, - blocking: true}) -} - -func (ctx *context) VertexAttrib1f(dst Attrib, x float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib1f(%v, %v) %v", dst, x, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib1f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - }, - blocking: true}) -} - -func (ctx *context) VertexAttrib1fv(dst Attrib, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib1fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib1fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttrib2f(dst Attrib, x, y float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib2f(%v, %v, %v) %v", dst, x, y, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib2f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - a2: uintptr(math.Float32bits(y)), - }, - blocking: true}) -} - -func (ctx *context) VertexAttrib2fv(dst Attrib, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib2fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib2fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttrib3f(dst Attrib, x, y, z float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib3f(%v, %v, %v, %v) %v", dst, x, y, z, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib3f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - a2: uintptr(math.Float32bits(y)), - a3: uintptr(math.Float32bits(z)), - }, - blocking: true}) -} - -func (ctx *context) VertexAttrib3fv(dst Attrib, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib3fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib3fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttrib4f(dst Attrib, x, y, z, w float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib4f(%v, %v, %v, %v, %v) %v", dst, x, y, z, w, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib4f, - a0: dst.c(), - a1: uintptr(math.Float32bits(x)), - a2: uintptr(math.Float32bits(y)), - a3: uintptr(math.Float32bits(z)), - a4: uintptr(math.Float32bits(w)), - }, - blocking: true}) -} - -func (ctx *context) VertexAttrib4fv(dst Attrib, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttrib4fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttrib4fv, - a0: dst.c(), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx *context) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.VertexAttribPointer(%v, %v, %v, %v, %v, %v) %v", dst, size, ty, normalized, stride, offset, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnVertexAttribPointer, - a0: dst.c(), - a1: uintptr(size), - a2: ty.c(), - a3: glBoolean(normalized), - a4: uintptr(stride), - a5: uintptr(offset), - }, - blocking: true}) -} - -func (ctx *context) Viewport(x, y, width, height int) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Viewport(%v, %v, %v, %v) %v", x, y, width, height, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnViewport, - a0: uintptr(x), - a1: uintptr(y), - a2: uintptr(width), - a3: uintptr(height), - }, - blocking: true}) -} - -func (ctx context3) UniformMatrix2x3fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix2x3fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix2x3fv, - a0: dst.c(), - a1: uintptr(len(src) / 6), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix3x2fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix3x2fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix3x2fv, - a0: dst.c(), - a1: uintptr(len(src) / 6), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix2x4fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix2x4fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix2x4fv, - a0: dst.c(), - a1: uintptr(len(src) / 8), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix4x2fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix4x2fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix4x2fv, - a0: dst.c(), - a1: uintptr(len(src) / 8), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix3x4fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix3x4fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix3x4fv, - a0: dst.c(), - a1: uintptr(len(src) / 12), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) UniformMatrix4x3fv(dst Uniform, src []float32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.UniformMatrix4x3fv(%v, len(%d)) %v", dst, len(src), errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniformMatrix4x3fv, - a0: dst.c(), - a1: uintptr(len(src) / 12), - }, - parg: unsafe.Pointer(&src[0]), - blocking: true, - }) -} - -func (ctx context3) BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.BlitFramebuffer(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v) %v", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnBlitFramebuffer, - a0: uintptr(srcX0), - a1: uintptr(srcY0), - a2: uintptr(srcX1), - a3: uintptr(srcY1), - a4: uintptr(dstX0), - a5: uintptr(dstY0), - a6: uintptr(dstX1), - a7: uintptr(dstY1), - a8: uintptr(mask), - a9: filter.c(), - }, - blocking: true}) -} - -func (ctx context3) Uniform1ui(dst Uniform, v uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform1ui(%v, %v) %v", dst, v, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform1ui, - a0: dst.c(), - a1: uintptr(v), - }, - blocking: true}) -} - -func (ctx context3) Uniform2ui(dst Uniform, v0, v1 uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform2ui(%v, %v, %v) %v", dst, v0, v1, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform2ui, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - }, - blocking: true}) -} - -func (ctx context3) Uniform3ui(dst Uniform, v0, v1, v2 uint) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform3ui(%v, %v, %v, %v) %v", dst, v0, v1, v2, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform3ui, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - }, - blocking: true}) -} - -func (ctx context3) Uniform4ui(dst Uniform, v0, v1, v2, v3 uint32) { - defer func() { - errstr := ctx.errDrain() - log.Printf("gl.Uniform4ui(%v, %v, %v, %v, %v) %v", dst, v0, v1, v2, v3, errstr) - }() - ctx.enqueueDebug(call{ - args: fnargs{ - fn: glfnUniform4ui, - a0: dst.c(), - a1: uintptr(v0), - a2: uintptr(v1), - a3: uintptr(v2), - a4: uintptr(v3), - }, - blocking: true}) -} diff --git a/vendor/golang.org/x/mobile/gl/interface.go b/vendor/golang.org/x/mobile/gl/interface.go deleted file mode 100644 index 189c29e..0000000 --- a/vendor/golang.org/x/mobile/gl/interface.go +++ /dev/null @@ -1,889 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gl - -// Context is an OpenGL ES context. -// -// A Context has a method for every GL function supported by ES 2 or later. -// In a program compiled with ES 3 support, a Context is also a Context3. -// For example, a program can: -// -// func f(glctx gl.Context) { -// glctx.(gl.Context3).BlitFramebuffer(...) -// } -// -// Calls are not safe for concurrent use. However calls can be made from -// any goroutine, the gl package removes the notion of thread-local -// context. -// -// Contexts are independent. Two contexts can be used concurrently. -type Context interface { - // ActiveTexture sets the active texture unit. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glActiveTexture.xhtml - ActiveTexture(texture Enum) - - // AttachShader attaches a shader to a program. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glAttachShader.xhtml - AttachShader(p Program, s Shader) - - // BindAttribLocation binds a vertex attribute index with a named - // variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindAttribLocation.xhtml - BindAttribLocation(p Program, a Attrib, name string) - - // BindBuffer binds a buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindBuffer.xhtml - BindBuffer(target Enum, b Buffer) - - // BindFramebuffer binds a framebuffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindFramebuffer.xhtml - BindFramebuffer(target Enum, fb Framebuffer) - - // BindRenderbuffer binds a render buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindRenderbuffer.xhtml - BindRenderbuffer(target Enum, rb Renderbuffer) - - // BindTexture binds a texture. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindTexture.xhtml - BindTexture(target Enum, t Texture) - - // BindVertexArray binds a vertex array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindVertexArray.xhtml - BindVertexArray(rb VertexArray) - - // BlendColor sets the blend color. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendColor.xhtml - BlendColor(red, green, blue, alpha float32) - - // BlendEquation sets both RGB and alpha blend equations. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquation.xhtml - BlendEquation(mode Enum) - - // BlendEquationSeparate sets RGB and alpha blend equations separately. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquationSeparate.xhtml - BlendEquationSeparate(modeRGB, modeAlpha Enum) - - // BlendFunc sets the pixel blending factors. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFunc.xhtml - BlendFunc(sfactor, dfactor Enum) - - // BlendFunc sets the pixel RGB and alpha blending factors separately. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFuncSeparate.xhtml - BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) - - // BufferData creates a new data store for the bound buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml - BufferData(target Enum, src []byte, usage Enum) - - // BufferInit creates a new uninitialized data store for the bound buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml - BufferInit(target Enum, size int, usage Enum) - - // BufferSubData sets some of data in the bound buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferSubData.xhtml - BufferSubData(target Enum, offset int, data []byte) - - // CheckFramebufferStatus reports the completeness status of the - // active framebuffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCheckFramebufferStatus.xhtml - CheckFramebufferStatus(target Enum) Enum - - // Clear clears the window. - // - // The behavior of Clear is influenced by the pixel ownership test, - // the scissor test, dithering, and the buffer writemasks. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glClear.xhtml - Clear(mask Enum) - - // ClearColor specifies the RGBA values used to clear color buffers. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearColor.xhtml - ClearColor(red, green, blue, alpha float32) - - // ClearDepthf sets the depth value used to clear the depth buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearDepthf.xhtml - ClearDepthf(d float32) - - // ClearStencil sets the index used to clear the stencil buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearStencil.xhtml - ClearStencil(s int) - - // ColorMask specifies whether color components in the framebuffer - // can be written. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glColorMask.xhtml - ColorMask(red, green, blue, alpha bool) - - // CompileShader compiles the source code of s. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompileShader.xhtml - CompileShader(s Shader) - - // CompressedTexImage2D writes a compressed 2D texture. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexImage2D.xhtml - CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) - - // CompressedTexSubImage2D writes a subregion of a compressed 2D texture. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexSubImage2D.xhtml - CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) - - // CopyTexImage2D writes a 2D texture from the current framebuffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexImage2D.xhtml - CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) - - // CopyTexSubImage2D writes a 2D texture subregion from the - // current framebuffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexSubImage2D.xhtml - CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) - - // CreateBuffer creates a buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenBuffers.xhtml - CreateBuffer() Buffer - - // CreateFramebuffer creates a framebuffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenFramebuffers.xhtml - CreateFramebuffer() Framebuffer - - // CreateProgram creates a new empty program object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateProgram.xhtml - CreateProgram() Program - - // CreateRenderbuffer create a renderbuffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenRenderbuffers.xhtml - CreateRenderbuffer() Renderbuffer - - // CreateShader creates a new empty shader object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateShader.xhtml - CreateShader(ty Enum) Shader - - // CreateTexture creates a texture object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenTextures.xhtml - CreateTexture() Texture - - // CreateTVertexArray creates a vertex array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenVertexArrays.xhtml - CreateVertexArray() VertexArray - - // CullFace specifies which polygons are candidates for culling. - // - // Valid modes: FRONT, BACK, FRONT_AND_BACK. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glCullFace.xhtml - CullFace(mode Enum) - - // DeleteBuffer deletes the given buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteBuffers.xhtml - DeleteBuffer(v Buffer) - - // DeleteFramebuffer deletes the given framebuffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteFramebuffers.xhtml - DeleteFramebuffer(v Framebuffer) - - // DeleteProgram deletes the given program object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteProgram.xhtml - DeleteProgram(p Program) - - // DeleteRenderbuffer deletes the given render buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteRenderbuffers.xhtml - DeleteRenderbuffer(v Renderbuffer) - - // DeleteShader deletes shader s. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteShader.xhtml - DeleteShader(s Shader) - - // DeleteTexture deletes the given texture object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteTextures.xhtml - DeleteTexture(v Texture) - - // DeleteVertexArray deletes the given render buffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteVertexArrays.xhtml - DeleteVertexArray(v VertexArray) - - // DepthFunc sets the function used for depth buffer comparisons. - // - // Valid fn values: - // NEVER - // LESS - // EQUAL - // LEQUAL - // GREATER - // NOTEQUAL - // GEQUAL - // ALWAYS - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthFunc.xhtml - DepthFunc(fn Enum) - - // DepthMask sets the depth buffer enabled for writing. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthMask.xhtml - DepthMask(flag bool) - - // DepthRangef sets the mapping from normalized device coordinates to - // window coordinates. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthRangef.xhtml - DepthRangef(n, f float32) - - // DetachShader detaches the shader s from the program p. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDetachShader.xhtml - DetachShader(p Program, s Shader) - - // Disable disables various GL capabilities. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisable.xhtml - Disable(cap Enum) - - // DisableVertexAttribArray disables a vertex attribute array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisableVertexAttribArray.xhtml - DisableVertexAttribArray(a Attrib) - - // DrawArrays renders geometric primitives from the bound data. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawArrays.xhtml - DrawArrays(mode Enum, first, count int) - - // DrawElements renders primitives from a bound buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawElements.xhtml - DrawElements(mode Enum, count int, ty Enum, offset int) - - // TODO(crawshaw): consider DrawElements8 / DrawElements16 / DrawElements32 - - // Enable enables various GL capabilities. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glEnable.xhtml - Enable(cap Enum) - - // EnableVertexAttribArray enables a vertex attribute array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glEnableVertexAttribArray.xhtml - EnableVertexAttribArray(a Attrib) - - // Finish blocks until the effects of all previously called GL - // commands are complete. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glFinish.xhtml - Finish() - - // Flush empties all buffers. It does not block. - // - // An OpenGL implementation may buffer network communication, - // the command stream, or data inside the graphics accelerator. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glFlush.xhtml - Flush() - - // FramebufferRenderbuffer attaches rb to the current frame buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferRenderbuffer.xhtml - FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) - - // FramebufferTexture2D attaches the t to the current frame buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferTexture2D.xhtml - FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) - - // FrontFace defines which polygons are front-facing. - // - // Valid modes: CW, CCW. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glFrontFace.xhtml - FrontFace(mode Enum) - - // GenerateMipmap generates mipmaps for the current texture. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenerateMipmap.xhtml - GenerateMipmap(target Enum) - - // GetActiveAttrib returns details about an active attribute variable. - // A value of 0 for index selects the first active attribute variable. - // Permissible values for index range from 0 to the number of active - // attribute variables minus 1. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveAttrib.xhtml - GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) - - // GetActiveUniform returns details about an active uniform variable. - // A value of 0 for index selects the first active uniform variable. - // Permissible values for index range from 0 to the number of active - // uniform variables minus 1. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveUniform.xhtml - GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) - - // GetAttachedShaders returns the shader objects attached to program p. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttachedShaders.xhtml - GetAttachedShaders(p Program) []Shader - - // GetAttribLocation returns the location of an attribute variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttribLocation.xhtml - GetAttribLocation(p Program, name string) Attrib - - // GetBooleanv returns the boolean values of parameter pname. - // - // Many boolean parameters can be queried more easily using IsEnabled. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml - GetBooleanv(dst []bool, pname Enum) - - // GetFloatv returns the float values of parameter pname. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml - GetFloatv(dst []float32, pname Enum) - - // GetIntegerv returns the int values of parameter pname. - // - // Single values may be queried more easily using GetInteger. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml - GetIntegerv(dst []int32, pname Enum) - - // GetInteger returns the int value of parameter pname. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml - GetInteger(pname Enum) int - - // GetBufferParameteri returns a parameter for the active buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetBufferParameter.xhtml - GetBufferParameteri(target, value Enum) int - - // GetError returns the next error. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetError.xhtml - GetError() Enum - - // GetFramebufferAttachmentParameteri returns attachment parameters - // for the active framebuffer object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetFramebufferAttachmentParameteriv.xhtml - GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int - - // GetProgrami returns a parameter value for a program. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramiv.xhtml - GetProgrami(p Program, pname Enum) int - - // GetProgramInfoLog returns the information log for a program. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramInfoLog.xhtml - GetProgramInfoLog(p Program) string - - // GetRenderbufferParameteri returns a parameter value for a render buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetRenderbufferParameteriv.xhtml - GetRenderbufferParameteri(target, pname Enum) int - - // GetShaderi returns a parameter value for a shader. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderiv.xhtml - GetShaderi(s Shader, pname Enum) int - - // GetShaderInfoLog returns the information log for a shader. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderInfoLog.xhtml - GetShaderInfoLog(s Shader) string - - // GetShaderPrecisionFormat returns range and precision limits for - // shader types. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderPrecisionFormat.xhtml - GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) - - // GetShaderSource returns source code of shader s. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderSource.xhtml - GetShaderSource(s Shader) string - - // GetString reports current GL state. - // - // Valid name values: - // EXTENSIONS - // RENDERER - // SHADING_LANGUAGE_VERSION - // VENDOR - // VERSION - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetString.xhtml - GetString(pname Enum) string - - // GetTexParameterfv returns the float values of a texture parameter. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml - GetTexParameterfv(dst []float32, target, pname Enum) - - // GetTexParameteriv returns the int values of a texture parameter. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml - GetTexParameteriv(dst []int32, target, pname Enum) - - // GetUniformfv returns the float values of a uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml - GetUniformfv(dst []float32, src Uniform, p Program) - - // GetUniformiv returns the float values of a uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml - GetUniformiv(dst []int32, src Uniform, p Program) - - // GetUniformLocation returns the location of a uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniformLocation.xhtml - GetUniformLocation(p Program, name string) Uniform - - // GetVertexAttribf reads the float value of a vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml - GetVertexAttribf(src Attrib, pname Enum) float32 - - // GetVertexAttribfv reads float values of a vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml - GetVertexAttribfv(dst []float32, src Attrib, pname Enum) - - // GetVertexAttribi reads the int value of a vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml - GetVertexAttribi(src Attrib, pname Enum) int32 - - // GetVertexAttribiv reads int values of a vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml - GetVertexAttribiv(dst []int32, src Attrib, pname Enum) - - // TODO(crawshaw): glGetVertexAttribPointerv - - // Hint sets implementation-specific modes. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glHint.xhtml - Hint(target, mode Enum) - - // IsBuffer reports if b is a valid buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsBuffer.xhtml - IsBuffer(b Buffer) bool - - // IsEnabled reports if cap is an enabled capability. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsEnabled.xhtml - IsEnabled(cap Enum) bool - - // IsFramebuffer reports if fb is a valid frame buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsFramebuffer.xhtml - IsFramebuffer(fb Framebuffer) bool - - // IsProgram reports if p is a valid program object. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsProgram.xhtml - IsProgram(p Program) bool - - // IsRenderbuffer reports if rb is a valid render buffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsRenderbuffer.xhtml - IsRenderbuffer(rb Renderbuffer) bool - - // IsShader reports if s is valid shader. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsShader.xhtml - IsShader(s Shader) bool - - // IsTexture reports if t is a valid texture. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsTexture.xhtml - IsTexture(t Texture) bool - - // LineWidth specifies the width of lines. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glLineWidth.xhtml - LineWidth(width float32) - - // LinkProgram links the specified program. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glLinkProgram.xhtml - LinkProgram(p Program) - - // PixelStorei sets pixel storage parameters. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml - PixelStorei(pname Enum, param int32) - - // PolygonOffset sets the scaling factors for depth offsets. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glPolygonOffset.xhtml - PolygonOffset(factor, units float32) - - // ReadPixels returns pixel data from a buffer. - // - // In GLES 3, the source buffer is controlled with ReadBuffer. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glReadPixels.xhtml - ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) - - // ReleaseShaderCompiler frees resources allocated by the shader compiler. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glReleaseShaderCompiler.xhtml - ReleaseShaderCompiler() - - // RenderbufferStorage establishes the data storage, format, and - // dimensions of a renderbuffer object's image. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glRenderbufferStorage.xhtml - RenderbufferStorage(target, internalFormat Enum, width, height int) - - // SampleCoverage sets multisample coverage parameters. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glSampleCoverage.xhtml - SampleCoverage(value float32, invert bool) - - // Scissor defines the scissor box rectangle, in window coordinates. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glScissor.xhtml - Scissor(x, y, width, height int32) - - // TODO(crawshaw): ShaderBinary - - // ShaderSource sets the source code of s to the given source code. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glShaderSource.xhtml - ShaderSource(s Shader, src string) - - // StencilFunc sets the front and back stencil test reference value. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFunc.xhtml - StencilFunc(fn Enum, ref int, mask uint32) - - // StencilFunc sets the front or back stencil test reference value. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFuncSeparate.xhtml - StencilFuncSeparate(face, fn Enum, ref int, mask uint32) - - // StencilMask controls the writing of bits in the stencil planes. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMask.xhtml - StencilMask(mask uint32) - - // StencilMaskSeparate controls the writing of bits in the stencil planes. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMaskSeparate.xhtml - StencilMaskSeparate(face Enum, mask uint32) - - // StencilOp sets front and back stencil test actions. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOp.xhtml - StencilOp(fail, zfail, zpass Enum) - - // StencilOpSeparate sets front or back stencil tests. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOpSeparate.xhtml - StencilOpSeparate(face, sfail, dpfail, dppass Enum) - - // TexImage2D writes a 2D texture image. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexImage2D.xhtml - TexImage2D(target Enum, level int, internalFormat int, width, height int, format Enum, ty Enum, data []byte) - - // TexSubImage2D writes a subregion of a 2D texture image. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexSubImage2D.xhtml - TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) - - // TexParameterf sets a float texture parameter. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml - TexParameterf(target, pname Enum, param float32) - - // TexParameterfv sets a float texture parameter array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml - TexParameterfv(target, pname Enum, params []float32) - - // TexParameteri sets an integer texture parameter. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml - TexParameteri(target, pname Enum, param int) - - // TexParameteriv sets an integer texture parameter array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml - TexParameteriv(target, pname Enum, params []int32) - - // Uniform1f writes a float uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform1f(dst Uniform, v float32) - - // Uniform1fv writes a [len(src)]float uniform array. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform1fv(dst Uniform, src []float32) - - // Uniform1i writes an int uniform variable. - // - // Uniform1i and Uniform1iv are the only two functions that may be used - // to load uniform variables defined as sampler types. Loading samplers - // with any other function will result in a INVALID_OPERATION error. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform1i(dst Uniform, v int) - - // Uniform1iv writes a int uniform array of len(src) elements. - // - // Uniform1i and Uniform1iv are the only two functions that may be used - // to load uniform variables defined as sampler types. Loading samplers - // with any other function will result in a INVALID_OPERATION error. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform1iv(dst Uniform, src []int32) - - // Uniform2f writes a vec2 uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform2f(dst Uniform, v0, v1 float32) - - // Uniform2fv writes a vec2 uniform array of len(src)/2 elements. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform2fv(dst Uniform, src []float32) - - // Uniform2i writes an ivec2 uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform2i(dst Uniform, v0, v1 int) - - // Uniform2iv writes an ivec2 uniform array of len(src)/2 elements. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform2iv(dst Uniform, src []int32) - - // Uniform3f writes a vec3 uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform3f(dst Uniform, v0, v1, v2 float32) - - // Uniform3fv writes a vec3 uniform array of len(src)/3 elements. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform3fv(dst Uniform, src []float32) - - // Uniform3i writes an ivec3 uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform3i(dst Uniform, v0, v1, v2 int32) - - // Uniform3iv writes an ivec3 uniform array of len(src)/3 elements. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform3iv(dst Uniform, src []int32) - - // Uniform4f writes a vec4 uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform4f(dst Uniform, v0, v1, v2, v3 float32) - - // Uniform4fv writes a vec4 uniform array of len(src)/4 elements. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform4fv(dst Uniform, src []float32) - - // Uniform4i writes an ivec4 uniform variable. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform4i(dst Uniform, v0, v1, v2, v3 int32) - - // Uniform4i writes an ivec4 uniform array of len(src)/4 elements. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - Uniform4iv(dst Uniform, src []int32) - - // UniformMatrix2fv writes 2x2 matrices. Each matrix uses four - // float32 values, so the number of matrices written is len(src)/4. - // - // Each matrix must be supplied in column major order. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - UniformMatrix2fv(dst Uniform, src []float32) - - // UniformMatrix3fv writes 3x3 matrices. Each matrix uses nine - // float32 values, so the number of matrices written is len(src)/9. - // - // Each matrix must be supplied in column major order. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - UniformMatrix3fv(dst Uniform, src []float32) - - // UniformMatrix4fv writes 4x4 matrices. Each matrix uses 16 - // float32 values, so the number of matrices written is len(src)/16. - // - // Each matrix must be supplied in column major order. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml - UniformMatrix4fv(dst Uniform, src []float32) - - // UseProgram sets the active program. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glUseProgram.xhtml - UseProgram(p Program) - - // ValidateProgram checks to see whether the executables contained in - // program can execute given the current OpenGL state. - // - // Typically only used for debugging. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glValidateProgram.xhtml - ValidateProgram(p Program) - - // VertexAttrib1f writes a float vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib1f(dst Attrib, x float32) - - // VertexAttrib1fv writes a float vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib1fv(dst Attrib, src []float32) - - // VertexAttrib2f writes a vec2 vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib2f(dst Attrib, x, y float32) - - // VertexAttrib2fv writes a vec2 vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib2fv(dst Attrib, src []float32) - - // VertexAttrib3f writes a vec3 vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib3f(dst Attrib, x, y, z float32) - - // VertexAttrib3fv writes a vec3 vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib3fv(dst Attrib, src []float32) - - // VertexAttrib4f writes a vec4 vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib4f(dst Attrib, x, y, z, w float32) - - // VertexAttrib4fv writes a vec4 vertex attribute. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml - VertexAttrib4fv(dst Attrib, src []float32) - - // VertexAttribPointer uses a bound buffer to define vertex attribute data. - // - // Direct use of VertexAttribPointer to load data into OpenGL is not - // supported via the Go bindings. Instead, use BindBuffer with an - // ARRAY_BUFFER and then fill it using BufferData. - // - // The size argument specifies the number of components per attribute, - // between 1-4. The stride argument specifies the byte offset between - // consecutive vertex attributes. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttribPointer.xhtml - VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) - - // Viewport sets the viewport, an affine transformation that - // normalizes device coordinates to window coordinates. - // - // http://www.khronos.org/opengles/sdk/docs/man3/html/glViewport.xhtml - Viewport(x, y, width, height int) -} - -// Context3 is an OpenGL ES 3 context. -// -// When the gl package is compiled with GL ES 3 support, the produced -// Context object also implements the Context3 interface. -type Context3 interface { - Context - - // BlitFramebuffer copies a block of pixels between framebuffers. - // - // https://www.khronos.org/opengles/sdk/docs/man3/html/glBlitFramebuffer.xhtml - BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) -} - -// Worker is used by display driver code to execute OpenGL calls. -// -// Typically display driver code creates a gl.Context for an application, -// and along with it establishes a locked OS thread to execute the cgo -// calls: -// -// go func() { -// runtime.LockOSThread() -// // ... platform-specific cgo call to bind a C OpenGL context -// // into thread-local storage. -// -// glctx, worker := gl.NewContext() -// workAvailable := worker.WorkAvailable() -// go userAppCode(glctx) -// for { -// select { -// case <-workAvailable: -// worker.DoWork() -// case <-drawEvent: -// // ... platform-specific cgo call to draw screen -// } -// } -// }() -// -// This interface is an internal implementation detail and should only be used -// by the package responsible for managing the screen, such as -// golang.org/x/mobile/app. -type Worker interface { - // WorkAvailable returns a channel that communicates when DoWork should be - // called. - WorkAvailable() <-chan struct{} - - // DoWork performs any pending OpenGL calls. - DoWork() -} diff --git a/vendor/golang.org/x/mobile/gl/types_debug.go b/vendor/golang.org/x/mobile/gl/types_debug.go deleted file mode 100644 index b6dbaaa..0000000 --- a/vendor/golang.org/x/mobile/gl/types_debug.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (darwin || linux || openbsd || windows) && gldebug -// +build darwin linux openbsd windows -// +build gldebug - -package gl - -// Alternate versions of the types defined in types.go with extra -// debugging information attached. For documentation, see types.go. - -import "fmt" - -type Enum uint32 - -type Attrib struct { - Value uint - name string -} - -type Program struct { - Init bool - Value uint32 -} - -type Shader struct { - Value uint32 -} - -type Buffer struct { - Value uint32 -} - -type Framebuffer struct { - Value uint32 -} - -type Renderbuffer struct { - Value uint32 -} - -type Texture struct { - Value uint32 -} - -type Uniform struct { - Value int32 - name string -} - -type VertexArray struct { - Value uint32 -} - -func (v Attrib) c() uintptr { return uintptr(v.Value) } -func (v Enum) c() uintptr { return uintptr(v) } -func (v Program) c() uintptr { - if !v.Init { - ret := uintptr(0) - ret-- - return ret - } - return uintptr(v.Value) -} -func (v Shader) c() uintptr { return uintptr(v.Value) } -func (v Buffer) c() uintptr { return uintptr(v.Value) } -func (v Framebuffer) c() uintptr { return uintptr(v.Value) } -func (v Renderbuffer) c() uintptr { return uintptr(v.Value) } -func (v Texture) c() uintptr { return uintptr(v.Value) } -func (v Uniform) c() uintptr { return uintptr(v.Value) } -func (v VertexArray) c() uintptr { return uintptr(v.Value) } - -func (v Attrib) String() string { return fmt.Sprintf("Attrib(%d:%s)", v.Value, v.name) } -func (v Program) String() string { return fmt.Sprintf("Program(%d)", v.Value) } -func (v Shader) String() string { return fmt.Sprintf("Shader(%d)", v.Value) } -func (v Buffer) String() string { return fmt.Sprintf("Buffer(%d)", v.Value) } -func (v Framebuffer) String() string { return fmt.Sprintf("Framebuffer(%d)", v.Value) } -func (v Renderbuffer) String() string { return fmt.Sprintf("Renderbuffer(%d)", v.Value) } -func (v Texture) String() string { return fmt.Sprintf("Texture(%d)", v.Value) } -func (v Uniform) String() string { return fmt.Sprintf("Uniform(%d:%s)", v.Value, v.name) } -func (v VertexArray) String() string { return fmt.Sprintf("VertexArray(%d)", v.Value) } diff --git a/vendor/golang.org/x/mobile/gl/types_prod.go b/vendor/golang.org/x/mobile/gl/types_prod.go deleted file mode 100644 index e1c8b42..0000000 --- a/vendor/golang.org/x/mobile/gl/types_prod.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (darwin || linux || openbsd || windows) && !gldebug -// +build darwin linux openbsd windows -// +build !gldebug - -package gl - -import "fmt" - -// Enum is equivalent to GLenum, and is normally used with one of the -// constants defined in this package. -type Enum uint32 - -// Types are defined a structs so that in debug mode they can carry -// extra information, such as a string name. See typesdebug.go. - -// Attrib identifies the location of a specific attribute variable. -type Attrib struct { - Value uint -} - -// Program identifies a compiled shader program. -type Program struct { - // Init is set by CreateProgram, as some GL drivers (in particular, - // ANGLE) return true for glIsProgram(0). - Init bool - Value uint32 -} - -// Shader identifies a GLSL shader. -type Shader struct { - Value uint32 -} - -// Buffer identifies a GL buffer object. -type Buffer struct { - Value uint32 -} - -// Framebuffer identifies a GL framebuffer. -type Framebuffer struct { - Value uint32 -} - -// A Renderbuffer is a GL object that holds an image in an internal format. -type Renderbuffer struct { - Value uint32 -} - -// A Texture identifies a GL texture unit. -type Texture struct { - Value uint32 -} - -// Uniform identifies the location of a specific uniform variable. -type Uniform struct { - Value int32 -} - -// A VertexArray is a GL object that holds vertices in an internal format. -type VertexArray struct { - Value uint32 -} - -func (v Attrib) c() uintptr { return uintptr(v.Value) } -func (v Enum) c() uintptr { return uintptr(v) } -func (v Program) c() uintptr { - if !v.Init { - ret := uintptr(0) - ret-- - return ret - } - return uintptr(v.Value) -} -func (v Shader) c() uintptr { return uintptr(v.Value) } -func (v Buffer) c() uintptr { return uintptr(v.Value) } -func (v Framebuffer) c() uintptr { return uintptr(v.Value) } -func (v Renderbuffer) c() uintptr { return uintptr(v.Value) } -func (v Texture) c() uintptr { return uintptr(v.Value) } -func (v Uniform) c() uintptr { return uintptr(v.Value) } -func (v VertexArray) c() uintptr { return uintptr(v.Value) } - -func (v Attrib) String() string { return fmt.Sprintf("Attrib(%d)", v.Value) } -func (v Program) String() string { return fmt.Sprintf("Program(%d)", v.Value) } -func (v Shader) String() string { return fmt.Sprintf("Shader(%d)", v.Value) } -func (v Buffer) String() string { return fmt.Sprintf("Buffer(%d)", v.Value) } -func (v Framebuffer) String() string { return fmt.Sprintf("Framebuffer(%d)", v.Value) } -func (v Renderbuffer) String() string { return fmt.Sprintf("Renderbuffer(%d)", v.Value) } -func (v Texture) String() string { return fmt.Sprintf("Texture(%d)", v.Value) } -func (v Uniform) String() string { return fmt.Sprintf("Uniform(%d)", v.Value) } -func (v VertexArray) String() string { return fmt.Sprintf("VertexArray(%d)", v.Value) } diff --git a/vendor/golang.org/x/mobile/gl/work.c b/vendor/golang.org/x/mobile/gl/work.c deleted file mode 100644 index 605e0ba..0000000 --- a/vendor/golang.org/x/mobile/gl/work.c +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin || linux || openbsd -// +build darwin linux openbsd - -#include -#include "_cgo_export.h" -#include "work.h" - -#if defined(GL_ES_VERSION_3_0) && GL_ES_VERSION_3_0 -#else -#include -static void gles3missing() { - printf("GLES3 function is missing\n"); - exit(2); -} -static void glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } -static void glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } -static void glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } -static void glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } -static void glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } -static void glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } -static void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { gles3missing(); } -static void glUniform1ui(GLint location, GLuint v0) { gles3missing(); } -static void glUniform2ui(GLint location, GLuint v0, GLuint v1) { gles3missing(); } -static void glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { gles3missing(); } -static void glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { gles3missing(); } -static void glUniform1uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } -static void glUniform2uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } -static void glUniform3uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } -static void glUniform4uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } -static void glBindVertexArray(GLuint array) { gles3missing(); } -static void glGenVertexArrays(GLsizei n, GLuint *arrays) { gles3missing(); } -static void glDeleteVertexArrays(GLsizei n, const GLuint *arrays) { gles3missing(); } -#endif - -uintptr_t processFn(struct fnargs* args, char* parg) { - uintptr_t ret = 0; - switch (args->fn) { - case glfnUNDEFINED: - abort(); // bad glfn - break; - case glfnActiveTexture: - glActiveTexture((GLenum)args->a0); - break; - case glfnAttachShader: - glAttachShader((GLint)args->a0, (GLint)args->a1); - break; - case glfnBindAttribLocation: - glBindAttribLocation((GLint)args->a0, (GLint)args->a1, (GLchar*)args->a2); - break; - case glfnBindBuffer: - glBindBuffer((GLenum)args->a0, (GLuint)args->a1); - break; - case glfnBindFramebuffer: - glBindFramebuffer((GLenum)args->a0, (GLint)args->a1); - break; - case glfnBindRenderbuffer: - glBindRenderbuffer((GLenum)args->a0, (GLint)args->a1); - break; - case glfnBindTexture: - glBindTexture((GLenum)args->a0, (GLint)args->a1); - break; - case glfnBindVertexArray: - glBindVertexArray((GLenum)args->a0); - break; - case glfnBlendColor: - glBlendColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); - break; - case glfnBlendEquation: - glBlendEquation((GLenum)args->a0); - break; - case glfnBlendEquationSeparate: - glBlendEquationSeparate((GLenum)args->a0, (GLenum)args->a1); - break; - case glfnBlendFunc: - glBlendFunc((GLenum)args->a0, (GLenum)args->a1); - break; - case glfnBlendFuncSeparate: - glBlendFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); - break; - case glfnBlitFramebuffer: - glBlitFramebuffer((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7, (GLbitfield)args->a8, (GLenum)args->a9); - break; - case glfnBufferData: - glBufferData((GLenum)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg, (GLenum)args->a2); - break; - case glfnBufferSubData: - glBufferSubData((GLenum)args->a0, (GLint)args->a1, (GLsizeiptr)args->a2, (GLvoid*)parg); - break; - case glfnCheckFramebufferStatus: - ret = glCheckFramebufferStatus((GLenum)args->a0); - break; - case glfnClear: - glClear((GLenum)args->a0); - break; - case glfnClearColor: - glClearColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); - break; - case glfnClearDepthf: - glClearDepthf(*(GLfloat*)&args->a0); - break; - case glfnClearStencil: - glClearStencil((GLint)args->a0); - break; - case glfnColorMask: - glColorMask((GLboolean)args->a0, (GLboolean)args->a1, (GLboolean)args->a2, (GLboolean)args->a3); - break; - case glfnCompileShader: - glCompileShader((GLint)args->a0); - break; - case glfnCompressedTexImage2D: - glCompressedTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLsizeiptr)args->a6, (GLvoid*)parg); - break; - case glfnCompressedTexSubImage2D: - glCompressedTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLenum)args->a6, (GLsizeiptr)args->a7, (GLvoid*)parg); - break; - case glfnCopyTexImage2D: - glCopyTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); - break; - case glfnCopyTexSubImage2D: - glCopyTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); - break; - case glfnCreateProgram: - ret = glCreateProgram(); - break; - case glfnCreateShader: - ret = glCreateShader((GLenum)args->a0); - break; - case glfnCullFace: - glCullFace((GLenum)args->a0); - break; - case glfnDeleteBuffer: - glDeleteBuffers(1, (const GLuint*)(&args->a0)); - break; - case glfnDeleteFramebuffer: - glDeleteFramebuffers(1, (const GLuint*)(&args->a0)); - break; - case glfnDeleteProgram: - glDeleteProgram((GLint)args->a0); - break; - case glfnDeleteRenderbuffer: - glDeleteRenderbuffers(1, (const GLuint*)(&args->a0)); - break; - case glfnDeleteShader: - glDeleteShader((GLint)args->a0); - break; - case glfnDeleteTexture: - glDeleteTextures(1, (const GLuint*)(&args->a0)); - break; - case glfnDeleteVertexArray: - glDeleteVertexArrays(1, (const GLuint*)(&args->a0)); - break; - case glfnDepthFunc: - glDepthFunc((GLenum)args->a0); - break; - case glfnDepthMask: - glDepthMask((GLboolean)args->a0); - break; - case glfnDepthRangef: - glDepthRangef(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); - break; - case glfnDetachShader: - glDetachShader((GLint)args->a0, (GLint)args->a1); - break; - case glfnDisable: - glDisable((GLenum)args->a0); - break; - case glfnDisableVertexAttribArray: - glDisableVertexAttribArray((GLint)args->a0); - break; - case glfnDrawArrays: - glDrawArrays((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2); - break; - case glfnDrawElements: - glDrawElements((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (void*)args->a3); - break; - case glfnEnable: - glEnable((GLenum)args->a0); - break; - case glfnEnableVertexAttribArray: - glEnableVertexAttribArray((GLint)args->a0); - break; - case glfnFinish: - glFinish(); - break; - case glfnFlush: - glFlush(); - break; - case glfnFramebufferRenderbuffer: - glFramebufferRenderbuffer((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3); - break; - case glfnFramebufferTexture2D: - glFramebufferTexture2D((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4); - break; - case glfnFrontFace: - glFrontFace((GLenum)args->a0); - break; - case glfnGenBuffer: - glGenBuffers(1, (GLuint*)&ret); - break; - case glfnGenFramebuffer: - glGenFramebuffers(1, (GLuint*)&ret); - break; - case glfnGenRenderbuffer: - glGenRenderbuffers(1, (GLuint*)&ret); - break; - case glfnGenTexture: - glGenTextures(1, (GLuint*)&ret); - break; - case glfnGenVertexArray: - glGenVertexArrays(1, (GLuint*)&ret); - break; - case glfnGenerateMipmap: - glGenerateMipmap((GLenum)args->a0); - break; - case glfnGetActiveAttrib: - glGetActiveAttrib( - (GLuint)args->a0, - (GLuint)args->a1, - (GLsizei)args->a2, - NULL, - (GLint*)&ret, - (GLenum*)args->a3, - (GLchar*)parg); - break; - case glfnGetActiveUniform: - glGetActiveUniform( - (GLuint)args->a0, - (GLuint)args->a1, - (GLsizei)args->a2, - NULL, - (GLint*)&ret, - (GLenum*)args->a3, - (GLchar*)parg); - break; - case glfnGetAttachedShaders: - glGetAttachedShaders((GLuint)args->a0, (GLsizei)args->a1, (GLsizei*)&ret, (GLuint*)parg); - break; - case glfnGetAttribLocation: - ret = glGetAttribLocation((GLint)args->a0, (GLchar*)args->a1); - break; - case glfnGetBooleanv: - glGetBooleanv((GLenum)args->a0, (GLboolean*)parg); - break; - case glfnGetBufferParameteri: - glGetBufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); - break; - case glfnGetFloatv: - glGetFloatv((GLenum)args->a0, (GLfloat*)parg); - break; - case glfnGetIntegerv: - glGetIntegerv((GLenum)args->a0, (GLint*)parg); - break; - case glfnGetError: - ret = glGetError(); - break; - case glfnGetFramebufferAttachmentParameteriv: - glGetFramebufferAttachmentParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint*)&ret); - break; - case glfnGetProgramiv: - glGetProgramiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); - break; - case glfnGetProgramInfoLog: - glGetProgramInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); - break; - case glfnGetRenderbufferParameteriv: - glGetRenderbufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); - break; - case glfnGetShaderiv: - glGetShaderiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); - break; - case glfnGetShaderInfoLog: - glGetShaderInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); - break; - case glfnGetShaderPrecisionFormat: - glGetShaderPrecisionFormat((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg, &((GLint*)parg)[2]); - break; - case glfnGetShaderSource: - glGetShaderSource((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); - break; - case glfnGetString: - ret = (uintptr_t)glGetString((GLenum)args->a0); - break; - case glfnGetTexParameterfv: - glGetTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); - break; - case glfnGetTexParameteriv: - glGetTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); - break; - case glfnGetUniformfv: - glGetUniformfv((GLuint)args->a0, (GLint)args->a1, (GLfloat*)parg); - break; - case glfnGetUniformiv: - glGetUniformiv((GLuint)args->a0, (GLint)args->a1, (GLint*)parg); - break; - case glfnGetUniformLocation: - ret = glGetUniformLocation((GLint)args->a0, (GLchar*)args->a1); - break; - case glfnGetVertexAttribfv: - glGetVertexAttribfv((GLuint)args->a0, (GLenum)args->a1, (GLfloat*)parg); - break; - case glfnGetVertexAttribiv: - glGetVertexAttribiv((GLuint)args->a0, (GLenum)args->a1, (GLint*)parg); - break; - case glfnHint: - glHint((GLenum)args->a0, (GLenum)args->a1); - break; - case glfnIsBuffer: - ret = glIsBuffer((GLint)args->a0); - break; - case glfnIsEnabled: - ret = glIsEnabled((GLenum)args->a0); - break; - case glfnIsFramebuffer: - ret = glIsFramebuffer((GLint)args->a0); - break; - case glfnIsProgram: - ret = glIsProgram((GLint)args->a0); - break; - case glfnIsRenderbuffer: - ret = glIsRenderbuffer((GLint)args->a0); - break; - case glfnIsShader: - ret = glIsShader((GLint)args->a0); - break; - case glfnIsTexture: - ret = glIsTexture((GLint)args->a0); - break; - case glfnLineWidth: - glLineWidth(*(GLfloat*)&args->a0); - break; - case glfnLinkProgram: - glLinkProgram((GLint)args->a0); - break; - case glfnPixelStorei: - glPixelStorei((GLenum)args->a0, (GLint)args->a1); - break; - case glfnPolygonOffset: - glPolygonOffset(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); - break; - case glfnReadPixels: - glReadPixels((GLint)args->a0, (GLint)args->a1, (GLsizei)args->a2, (GLsizei)args->a3, (GLenum)args->a4, (GLenum)args->a5, (void*)parg); - break; - case glfnReleaseShaderCompiler: - glReleaseShaderCompiler(); - break; - case glfnRenderbufferStorage: - glRenderbufferStorage((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLint)args->a3); - break; - case glfnSampleCoverage: - glSampleCoverage(*(GLfloat*)&args->a0, (GLboolean)args->a1); - break; - case glfnScissor: - glScissor((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); - break; - case glfnShaderSource: -#if defined(os_ios) || defined(os_macos) - glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar *const *)args->a2, NULL); -#else - glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar **)args->a2, NULL); -#endif - break; - case glfnStencilFunc: - glStencilFunc((GLenum)args->a0, (GLint)args->a1, (GLuint)args->a2); - break; - case glfnStencilFuncSeparate: - glStencilFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLuint)args->a3); - break; - case glfnStencilMask: - glStencilMask((GLuint)args->a0); - break; - case glfnStencilMaskSeparate: - glStencilMaskSeparate((GLenum)args->a0, (GLuint)args->a1); - break; - case glfnStencilOp: - glStencilOp((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2); - break; - case glfnStencilOpSeparate: - glStencilOpSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); - break; - case glfnTexImage2D: - glTexImage2D( - (GLenum)args->a0, - (GLint)args->a1, - (GLint)args->a2, - (GLsizei)args->a3, - (GLsizei)args->a4, - 0, // border - (GLenum)args->a5, - (GLenum)args->a6, - (const GLvoid*)parg); - break; - case glfnTexSubImage2D: - glTexSubImage2D( - (GLenum)args->a0, - (GLint)args->a1, - (GLint)args->a2, - (GLint)args->a3, - (GLsizei)args->a4, - (GLsizei)args->a5, - (GLenum)args->a6, - (GLenum)args->a7, - (const GLvoid*)parg); - break; - case glfnTexParameterf: - glTexParameterf((GLenum)args->a0, (GLenum)args->a1, *(GLfloat*)&args->a2); - break; - case glfnTexParameterfv: - glTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); - break; - case glfnTexParameteri: - glTexParameteri((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2); - break; - case glfnTexParameteriv: - glTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); - break; - case glfnUniform1f: - glUniform1f((GLint)args->a0, *(GLfloat*)&args->a1); - break; - case glfnUniform1fv: - glUniform1fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform1i: - glUniform1i((GLint)args->a0, (GLint)args->a1); - break; - case glfnUniform1ui: - glUniform1ui((GLint)args->a0, (GLuint)args->a1); - break; - case glfnUniform1uiv: - glUniform1uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); - break; - case glfnUniform1iv: - glUniform1iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform2f: - glUniform2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); - break; - case glfnUniform2fv: - glUniform2fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform2i: - glUniform2i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2); - break; - case glfnUniform2ui: - glUniform2ui((GLint)args->a0, (GLuint)args->a1, (GLuint)args->a2); - break; - case glfnUniform2uiv: - glUniform2uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); - break; - case glfnUniform2iv: - glUniform2iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform3f: - glUniform3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); - break; - case glfnUniform3fv: - glUniform3fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform3i: - glUniform3i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); - break; - case glfnUniform3ui: - glUniform3ui((GLint)args->a0, (GLuint)args->a1, (GLuint)args->a2, (GLuint)args->a3); - break; - case glfnUniform3uiv: - glUniform3uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); - break; - case glfnUniform3iv: - glUniform3iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform4f: - glUniform4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); - break; - case glfnUniform4fv: - glUniform4fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniform4i: - glUniform4i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4); - break; - case glfnUniform4ui: - glUniform4ui((GLint)args->a0, (GLuint)args->a1, (GLuint)args->a2, (GLuint)args->a3, (GLuint)args->a4); - break; - case glfnUniform4uiv: - glUniform4uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); - break; - case glfnUniform4iv: - glUniform4iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); - break; - case glfnUniformMatrix2fv: - glUniformMatrix2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix3fv: - glUniformMatrix3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix4fv: - glUniformMatrix4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix2x3fv: - glUniformMatrix2x3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix3x2fv: - glUniformMatrix3x2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix2x4fv: - glUniformMatrix2x4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix4x2fv: - glUniformMatrix4x2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix3x4fv: - glUniformMatrix3x4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUniformMatrix4x3fv: - glUniformMatrix4x3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); - break; - case glfnUseProgram: - glUseProgram((GLint)args->a0); - break; - case glfnValidateProgram: - glValidateProgram((GLint)args->a0); - break; - case glfnVertexAttrib1f: - glVertexAttrib1f((GLint)args->a0, *(GLfloat*)&args->a1); - break; - case glfnVertexAttrib1fv: - glVertexAttrib1fv((GLint)args->a0, (GLfloat*)parg); - break; - case glfnVertexAttrib2f: - glVertexAttrib2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); - break; - case glfnVertexAttrib2fv: - glVertexAttrib2fv((GLint)args->a0, (GLfloat*)parg); - break; - case glfnVertexAttrib3f: - glVertexAttrib3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); - break; - case glfnVertexAttrib3fv: - glVertexAttrib3fv((GLint)args->a0, (GLfloat*)parg); - break; - case glfnVertexAttrib4f: - glVertexAttrib4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); - break; - case glfnVertexAttrib4fv: - glVertexAttrib4fv((GLint)args->a0, (GLfloat*)parg); - break; - case glfnVertexAttribPointer: - glVertexAttribPointer((GLuint)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLboolean)args->a3, (GLsizei)args->a4, (const GLvoid*)args->a5); - break; - case glfnViewport: - glViewport((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); - break; - } - return ret; -} diff --git a/vendor/golang.org/x/mobile/gl/work.go b/vendor/golang.org/x/mobile/gl/work.go deleted file mode 100644 index 65eaf9a..0000000 --- a/vendor/golang.org/x/mobile/gl/work.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin || linux || openbsd -// +build darwin linux openbsd - -package gl - -/* -#cgo ios LDFLAGS: -framework OpenGLES -#cgo darwin,!ios LDFLAGS: -framework OpenGL -#cgo linux LDFLAGS: -lGLESv2 -#cgo openbsd LDFLAGS: -L/usr/X11R6/lib/ -lGLESv2 - -#cgo android CFLAGS: -Dos_android -#cgo ios CFLAGS: -Dos_ios -#cgo darwin,!ios CFLAGS: -Dos_macos -#cgo darwin CFLAGS: -DGL_SILENCE_DEPRECATION -DGLES_SILENCE_DEPRECATION -#cgo linux CFLAGS: -Dos_linux -#cgo openbsd CFLAGS: -Dos_openbsd - -#cgo openbsd CFLAGS: -I/usr/X11R6/include/ - -#include -#include "work.h" - -uintptr_t process(struct fnargs* cargs, char* parg0, char* parg1, char* parg2, int count) { - uintptr_t ret; - - ret = processFn(&cargs[0], parg0); - if (count > 1) { - ret = processFn(&cargs[1], parg1); - } - if (count > 2) { - ret = processFn(&cargs[2], parg2); - } - - return ret; -} -*/ -import "C" - -import "unsafe" - -const workbufLen = 3 - -type context struct { - cptr uintptr - debug int32 - - workAvailable chan struct{} - - // work is a queue of calls to execute. - work chan call - - // retvalue is sent a return value when blocking calls complete. - // It is safe to use a global unbuffered channel here as calls - // cannot currently be made concurrently. - // - // TODO: the comment above about concurrent calls isn't actually true: package - // app calls package gl, but it has to do so in a separate goroutine, which - // means that its gl calls (which may be blocking) can race with other gl calls - // in the main program. We should make it safe to issue blocking gl calls - // concurrently, or get the gl calls out of package app, or both. - retvalue chan C.uintptr_t - - cargs [workbufLen]C.struct_fnargs - parg [workbufLen]*C.char -} - -func (ctx *context) WorkAvailable() <-chan struct{} { return ctx.workAvailable } - -type context3 struct { - *context -} - -// NewContext creates a cgo OpenGL context. -// -// See the Worker interface for more details on how it is used. -func NewContext() (Context, Worker) { - glctx := &context{ - workAvailable: make(chan struct{}, 1), - work: make(chan call, workbufLen), - retvalue: make(chan C.uintptr_t), - } - if C.GLES_VERSION == "GL_ES_2_0" { - return glctx, glctx - } - return context3{glctx}, glctx -} - -// Version returns a GL ES version string, either "GL_ES_2_0" or "GL_ES_3_0". -// Future versions of the gl package may return "GL_ES_3_1". -func Version() string { - return C.GLES_VERSION -} - -func (ctx *context) enqueue(c call) uintptr { - ctx.work <- c - - select { - case ctx.workAvailable <- struct{}{}: - default: - } - - if c.blocking { - return uintptr(<-ctx.retvalue) - } - return 0 -} - -func (ctx *context) DoWork() { - queue := make([]call, 0, workbufLen) - for { - // Wait until at least one piece of work is ready. - // Accumulate work until a piece is marked as blocking. - select { - case w := <-ctx.work: - queue = append(queue, w) - default: - return - } - blocking := queue[len(queue)-1].blocking - enqueue: - for len(queue) < cap(queue) && !blocking { - select { - case w := <-ctx.work: - queue = append(queue, w) - blocking = queue[len(queue)-1].blocking - default: - break enqueue - } - } - - // Process the queued GL functions. - for i, q := range queue { - ctx.cargs[i] = *(*C.struct_fnargs)(unsafe.Pointer(&q.args)) - ctx.parg[i] = (*C.char)(q.parg) - } - ret := C.process(&ctx.cargs[0], ctx.parg[0], ctx.parg[1], ctx.parg[2], C.int(len(queue))) - - // Cleanup and signal. - queue = queue[:0] - if blocking { - ctx.retvalue <- ret - } - } -} - -func init() { - if unsafe.Sizeof(C.GLint(0)) != unsafe.Sizeof(int32(0)) { - panic("GLint is not an int32") - } -} - -// cString creates C string off the Go heap. -// ret is a *char. -func (ctx *context) cString(str string) (uintptr, func()) { - ptr := unsafe.Pointer(C.CString(str)) - return uintptr(ptr), func() { C.free(ptr) } -} - -// cString creates a pointer to a C string off the Go heap. -// ret is a **char. -func (ctx *context) cStringPtr(str string) (uintptr, func()) { - s, free := ctx.cString(str) - ptr := C.malloc(C.size_t(unsafe.Sizeof((*int)(nil)))) - *(*uintptr)(ptr) = s - return uintptr(ptr), func() { - free() - C.free(ptr) - } -} diff --git a/vendor/golang.org/x/mobile/gl/work.h b/vendor/golang.org/x/mobile/gl/work.h deleted file mode 100644 index 5bc093b..0000000 --- a/vendor/golang.org/x/mobile/gl/work.h +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#ifdef os_android -// TODO(crawshaw): We could include and -// condition on __ANDROID_API__ to get GLES3 headers. However -// we also need to add -lGLESv3 to LDFLAGS, which we cannot do -// from inside an ifdef. -#include -#elif os_linux -#include // install on Ubuntu with: sudo apt-get install libegl1-mesa-dev libgles2-mesa-dev libx11-dev -#elif os_openbsd -#include -#endif - -#ifdef os_ios -#include -#endif - -#ifdef os_macos -#include -#define GL_ES_VERSION_3_0 1 -#endif - -#if defined(GL_ES_VERSION_3_0) && GL_ES_VERSION_3_0 -#define GLES_VERSION "GL_ES_3_0" -#else -#define GLES_VERSION "GL_ES_2_0" -#endif - -#include -#include - -// TODO: generate this enum from fn.go. -typedef enum { - glfnUNDEFINED, - - glfnActiveTexture, - glfnAttachShader, - glfnBindAttribLocation, - glfnBindBuffer, - glfnBindFramebuffer, - glfnBindRenderbuffer, - glfnBindTexture, - glfnBindVertexArray, - glfnBlendColor, - glfnBlendEquation, - glfnBlendEquationSeparate, - glfnBlendFunc, - glfnBlendFuncSeparate, - glfnBufferData, - glfnBufferSubData, - glfnCheckFramebufferStatus, - glfnClear, - glfnClearColor, - glfnClearDepthf, - glfnClearStencil, - glfnColorMask, - glfnCompileShader, - glfnCompressedTexImage2D, - glfnCompressedTexSubImage2D, - glfnCopyTexImage2D, - glfnCopyTexSubImage2D, - glfnCreateProgram, - glfnCreateShader, - glfnCullFace, - glfnDeleteBuffer, - glfnDeleteFramebuffer, - glfnDeleteProgram, - glfnDeleteRenderbuffer, - glfnDeleteShader, - glfnDeleteTexture, - glfnDeleteVertexArray, - glfnDepthFunc, - glfnDepthRangef, - glfnDepthMask, - glfnDetachShader, - glfnDisable, - glfnDisableVertexAttribArray, - glfnDrawArrays, - glfnDrawElements, - glfnEnable, - glfnEnableVertexAttribArray, - glfnFinish, - glfnFlush, - glfnFramebufferRenderbuffer, - glfnFramebufferTexture2D, - glfnFrontFace, - glfnGenBuffer, - glfnGenFramebuffer, - glfnGenRenderbuffer, - glfnGenTexture, - glfnGenVertexArray, - glfnGenerateMipmap, - glfnGetActiveAttrib, - glfnGetActiveUniform, - glfnGetAttachedShaders, - glfnGetAttribLocation, - glfnGetBooleanv, - glfnGetBufferParameteri, - glfnGetError, - glfnGetFloatv, - glfnGetFramebufferAttachmentParameteriv, - glfnGetIntegerv, - glfnGetProgramInfoLog, - glfnGetProgramiv, - glfnGetRenderbufferParameteriv, - glfnGetShaderInfoLog, - glfnGetShaderPrecisionFormat, - glfnGetShaderSource, - glfnGetShaderiv, - glfnGetString, - glfnGetTexParameterfv, - glfnGetTexParameteriv, - glfnGetUniformLocation, - glfnGetUniformfv, - glfnGetUniformiv, - glfnGetVertexAttribfv, - glfnGetVertexAttribiv, - glfnHint, - glfnIsBuffer, - glfnIsEnabled, - glfnIsFramebuffer, - glfnIsProgram, - glfnIsRenderbuffer, - glfnIsShader, - glfnIsTexture, - glfnLineWidth, - glfnLinkProgram, - glfnPixelStorei, - glfnPolygonOffset, - glfnReadPixels, - glfnReleaseShaderCompiler, - glfnRenderbufferStorage, - glfnSampleCoverage, - glfnScissor, - glfnShaderSource, - glfnStencilFunc, - glfnStencilFuncSeparate, - glfnStencilMask, - glfnStencilMaskSeparate, - glfnStencilOp, - glfnStencilOpSeparate, - glfnTexImage2D, - glfnTexParameterf, - glfnTexParameterfv, - glfnTexParameteri, - glfnTexParameteriv, - glfnTexSubImage2D, - glfnUniform1f, - glfnUniform1fv, - glfnUniform1i, - glfnUniform1iv, - glfnUniform2f, - glfnUniform2fv, - glfnUniform2i, - glfnUniform2iv, - glfnUniform3f, - glfnUniform3fv, - glfnUniform3i, - glfnUniform3iv, - glfnUniform4f, - glfnUniform4fv, - glfnUniform4i, - glfnUniform4iv, - glfnUniformMatrix2fv, - glfnUniformMatrix3fv, - glfnUniformMatrix4fv, - glfnUseProgram, - glfnValidateProgram, - glfnVertexAttrib1f, - glfnVertexAttrib1fv, - glfnVertexAttrib2f, - glfnVertexAttrib2fv, - glfnVertexAttrib3f, - glfnVertexAttrib3fv, - glfnVertexAttrib4f, - glfnVertexAttrib4fv, - glfnVertexAttribPointer, - glfnViewport, - - // ES 3.0 functions - glfnUniformMatrix2x3fv, - glfnUniformMatrix3x2fv, - glfnUniformMatrix2x4fv, - glfnUniformMatrix4x2fv, - glfnUniformMatrix3x4fv, - glfnUniformMatrix4x3fv, - glfnBlitFramebuffer, - glfnUniform1ui, - glfnUniform2ui, - glfnUniform3ui, - glfnUniform4ui, - glfnUniform1uiv, - glfnUniform2uiv, - glfnUniform3uiv, - glfnUniform4uiv, -} glfn; - -// TODO: generate this type from fn.go. -struct fnargs { - glfn fn; - - uintptr_t a0; - uintptr_t a1; - uintptr_t a2; - uintptr_t a3; - uintptr_t a4; - uintptr_t a5; - uintptr_t a6; - uintptr_t a7; - uintptr_t a8; - uintptr_t a9; -}; - -extern uintptr_t processFn(struct fnargs* args, char* parg); diff --git a/vendor/golang.org/x/mobile/gl/work_other.go b/vendor/golang.org/x/mobile/gl/work_other.go deleted file mode 100644 index b4b48f4..0000000 --- a/vendor/golang.org/x/mobile/gl/work_other.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (!cgo || (!darwin && !linux && !openbsd)) && !windows -// +build !cgo !darwin,!linux,!openbsd -// +build !windows - -package gl - -// This file contains stub implementations of what the other work*.go files -// provide. These stubs don't do anything, other than compile (e.g. when cgo is -// disabled). - -type context struct{} - -func (*context) enqueue(c call) uintptr { - panic("unimplemented; GOOS/CGO combination not supported") -} - -func (*context) cString(str string) (uintptr, func()) { - panic("unimplemented; GOOS/CGO combination not supported") -} - -func (*context) cStringPtr(str string) (uintptr, func()) { - panic("unimplemented; GOOS/CGO combination not supported") -} - -type context3 = context - -func NewContext() (Context, Worker) { - panic("unimplemented; GOOS/CGO combination not supported") -} - -func Version() string { - panic("unimplemented; GOOS/CGO combination not supported") -} diff --git a/vendor/golang.org/x/mobile/gl/work_windows.go b/vendor/golang.org/x/mobile/gl/work_windows.go deleted file mode 100644 index 4119ac6..0000000 --- a/vendor/golang.org/x/mobile/gl/work_windows.go +++ /dev/null @@ -1,569 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gl - -import ( - "runtime" - "syscall" - "unsafe" -) - -// context is described in work.go. -type context struct { - debug int32 - workAvailable chan struct{} - work chan call - retvalue chan uintptr - - // TODO(crawshaw): will not work with a moving collector - cStringCounter int - cStrings map[int]unsafe.Pointer -} - -func (ctx *context) WorkAvailable() <-chan struct{} { return ctx.workAvailable } - -type context3 struct { - *context -} - -func NewContext() (Context, Worker) { - if err := findDLLs(); err != nil { - panic(err) - } - glctx := &context{ - workAvailable: make(chan struct{}, 1), - work: make(chan call, 3), - retvalue: make(chan uintptr), - cStrings: make(map[int]unsafe.Pointer), - } - return glctx, glctx -} - -func (ctx *context) enqueue(c call) uintptr { - ctx.work <- c - - select { - case ctx.workAvailable <- struct{}{}: - default: - } - - if c.blocking { - return <-ctx.retvalue - } - return 0 -} - -func (ctx *context) DoWork() { - // TODO: add a work queue - for { - select { - case w := <-ctx.work: - ret := ctx.doWork(w) - if w.blocking { - ctx.retvalue <- ret - } - default: - return - } - } -} - -func (ctx *context) cString(s string) (uintptr, func()) { - buf := make([]byte, len(s)+1) - for i := 0; i < len(s); i++ { - buf[i] = s[i] - } - ret := unsafe.Pointer(&buf[0]) - id := ctx.cStringCounter - ctx.cStringCounter++ - ctx.cStrings[id] = ret - return uintptr(ret), func() { delete(ctx.cStrings, id) } -} - -func (ctx *context) cStringPtr(str string) (uintptr, func()) { - s, sfree := ctx.cString(str) - sptr := [2]uintptr{s, 0} - ret := unsafe.Pointer(&sptr[0]) - id := ctx.cStringCounter - ctx.cStringCounter++ - ctx.cStrings[id] = ret - return uintptr(ret), func() { sfree(); delete(ctx.cStrings, id) } -} - -// fixFloat copies the first four arguments into the XMM registers. -// This is for the windows/amd64 calling convention, that wants -// floating point arguments to be passed in XMM. -// -// Mercifully, type information is not required to implement -// this calling convention. In particular see the mixed int/float -// examples: -// -// https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx -// -// This means it could be fixed in syscall.Syscall. The relevant -// issue is -// -// https://golang.org/issue/6510 -func fixFloat(x0, x1, x2, x3 uintptr) - -func (ctx *context) doWork(c call) (ret uintptr) { - if runtime.GOARCH == "amd64" { - fixFloat(c.args.a0, c.args.a1, c.args.a2, c.args.a3) - } - - switch c.args.fn { - case glfnActiveTexture: - syscall.Syscall(glActiveTexture.Addr(), 1, c.args.a0, 0, 0) - case glfnAttachShader: - syscall.Syscall(glAttachShader.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBindAttribLocation: - syscall.Syscall(glBindAttribLocation.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) - case glfnBindBuffer: - syscall.Syscall(glBindBuffer.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBindFramebuffer: - syscall.Syscall(glBindFramebuffer.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBindRenderbuffer: - syscall.Syscall(glBindRenderbuffer.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBindTexture: - syscall.Syscall(glBindTexture.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBindVertexArray: - syscall.Syscall(glBindVertexArray.Addr(), 1, c.args.a0, 0, 0) - case glfnBlendColor: - syscall.Syscall6(glBlendColor.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnBlendEquation: - syscall.Syscall(glBlendEquation.Addr(), 1, c.args.a0, 0, 0) - case glfnBlendEquationSeparate: - syscall.Syscall(glBlendEquationSeparate.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBlendFunc: - syscall.Syscall(glBlendFunc.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnBlendFuncSeparate: - syscall.Syscall6(glBlendFuncSeparate.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnBufferData: - syscall.Syscall6(glBufferData.Addr(), 4, c.args.a0, c.args.a1, uintptr(c.parg), c.args.a2, 0, 0) - case glfnBufferSubData: - syscall.Syscall6(glBufferSubData.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, uintptr(c.parg), 0, 0) - case glfnCheckFramebufferStatus: - ret, _, _ = syscall.Syscall(glCheckFramebufferStatus.Addr(), 1, c.args.a0, 0, 0) - case glfnClear: - syscall.Syscall(glClear.Addr(), 1, c.args.a0, 0, 0) - case glfnClearColor: - syscall.Syscall6(glClearColor.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnClearDepthf: - syscall.Syscall6(glClearDepthf.Addr(), 1, c.args.a0, 0, 0, 0, 0, 0) - case glfnClearStencil: - syscall.Syscall(glClearStencil.Addr(), 1, c.args.a0, 0, 0) - case glfnColorMask: - syscall.Syscall6(glColorMask.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnCompileShader: - syscall.Syscall(glCompileShader.Addr(), 1, c.args.a0, 0, 0) - case glfnCompressedTexImage2D: - syscall.Syscall9(glCompressedTexImage2D.Addr(), 8, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, uintptr(c.parg), 0) - case glfnCompressedTexSubImage2D: - syscall.Syscall9(glCompressedTexSubImage2D.Addr(), 9, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, uintptr(c.parg)) - case glfnCopyTexImage2D: - syscall.Syscall9(glCopyTexImage2D.Addr(), 8, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, 0) - case glfnCopyTexSubImage2D: - syscall.Syscall9(glCopyTexSubImage2D.Addr(), 8, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, 0) - case glfnCreateProgram: - ret, _, _ = syscall.Syscall(glCreateProgram.Addr(), 0, 0, 0, 0) - case glfnCreateShader: - ret, _, _ = syscall.Syscall(glCreateShader.Addr(), 1, c.args.a0, 0, 0) - case glfnCullFace: - syscall.Syscall(glCullFace.Addr(), 1, c.args.a0, 0, 0) - case glfnDeleteBuffer: - syscall.Syscall(glDeleteBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) - case glfnDeleteFramebuffer: - syscall.Syscall(glDeleteFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) - case glfnDeleteProgram: - syscall.Syscall(glDeleteProgram.Addr(), 1, c.args.a0, 0, 0) - case glfnDeleteRenderbuffer: - syscall.Syscall(glDeleteRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) - case glfnDeleteShader: - syscall.Syscall(glDeleteShader.Addr(), 1, c.args.a0, 0, 0) - case glfnDeleteVertexArray: - syscall.Syscall(glDeleteVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) - case glfnDeleteTexture: - syscall.Syscall(glDeleteTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) - case glfnDepthFunc: - syscall.Syscall(glDepthFunc.Addr(), 1, c.args.a0, 0, 0) - case glfnDepthRangef: - syscall.Syscall6(glDepthRangef.Addr(), 2, c.args.a0, c.args.a1, 0, 0, 0, 0) - case glfnDepthMask: - syscall.Syscall(glDepthMask.Addr(), 1, c.args.a0, 0, 0) - case glfnDetachShader: - syscall.Syscall(glDetachShader.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnDisable: - syscall.Syscall(glDisable.Addr(), 1, c.args.a0, 0, 0) - case glfnDisableVertexAttribArray: - syscall.Syscall(glDisableVertexAttribArray.Addr(), 1, c.args.a0, 0, 0) - case glfnDrawArrays: - syscall.Syscall(glDrawArrays.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) - case glfnDrawElements: - syscall.Syscall6(glDrawElements.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnEnable: - syscall.Syscall(glEnable.Addr(), 1, c.args.a0, 0, 0) - case glfnEnableVertexAttribArray: - syscall.Syscall(glEnableVertexAttribArray.Addr(), 1, c.args.a0, 0, 0) - case glfnFinish: - syscall.Syscall(glFinish.Addr(), 0, 0, 0, 0) - case glfnFlush: - syscall.Syscall(glFlush.Addr(), 0, 0, 0, 0) - case glfnFramebufferRenderbuffer: - syscall.Syscall6(glFramebufferRenderbuffer.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnFramebufferTexture2D: - syscall.Syscall6(glFramebufferTexture2D.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, 0) - case glfnFrontFace: - syscall.Syscall(glFrontFace.Addr(), 1, c.args.a0, 0, 0) - case glfnGenBuffer: - syscall.Syscall(glGenBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) - case glfnGenFramebuffer: - syscall.Syscall(glGenFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) - case glfnGenRenderbuffer: - syscall.Syscall(glGenRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) - case glfnGenVertexArray: - syscall.Syscall(glGenVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) - case glfnGenTexture: - syscall.Syscall(glGenTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) - case glfnGenerateMipmap: - syscall.Syscall(glGenerateMipmap.Addr(), 1, c.args.a0, 0, 0) - case glfnGetActiveAttrib: - syscall.Syscall9(glGetActiveAttrib.Addr(), 7, c.args.a0, c.args.a1, c.args.a2, 0, uintptr(unsafe.Pointer(&ret)), c.args.a3, uintptr(c.parg), 0, 0) - case glfnGetActiveUniform: - syscall.Syscall9(glGetActiveUniform.Addr(), 7, c.args.a0, c.args.a1, c.args.a2, 0, uintptr(unsafe.Pointer(&ret)), c.args.a3, uintptr(c.parg), 0, 0) - case glfnGetAttachedShaders: - syscall.Syscall6(glGetAttachedShaders.Addr(), 4, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret)), uintptr(c.parg), 0, 0) - case glfnGetAttribLocation: - ret, _, _ = syscall.Syscall(glGetAttribLocation.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnGetBooleanv: - syscall.Syscall(glGetBooleanv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnGetBufferParameteri: - syscall.Syscall(glGetBufferParameteri.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) - case glfnGetError: - ret, _, _ = syscall.Syscall(glGetError.Addr(), 0, 0, 0, 0) - case glfnGetFloatv: - syscall.Syscall(glGetFloatv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnGetFramebufferAttachmentParameteriv: - syscall.Syscall6(glGetFramebufferAttachmentParameteriv.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, uintptr(unsafe.Pointer(&ret)), 0, 0) - case glfnGetIntegerv: - syscall.Syscall(glGetIntegerv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnGetProgramInfoLog: - syscall.Syscall6(glGetProgramInfoLog.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) - case glfnGetProgramiv: - syscall.Syscall(glGetProgramiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) - case glfnGetRenderbufferParameteriv: - syscall.Syscall(glGetRenderbufferParameteriv.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) - case glfnGetShaderInfoLog: - syscall.Syscall6(glGetShaderInfoLog.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) - case glfnGetShaderPrecisionFormat: - // c.parg is a [3]int32. The first [2]int32 of the array is one - // parameter, the final *int32 is another parameter. - syscall.Syscall6(glGetShaderPrecisionFormat.Addr(), 4, c.args.a0, c.args.a1, uintptr(c.parg), uintptr(c.parg)+2*unsafe.Sizeof(uintptr(0)), 0, 0) - case glfnGetShaderSource: - syscall.Syscall6(glGetShaderSource.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) - case glfnGetShaderiv: - syscall.Syscall(glGetShaderiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) - case glfnGetString: - ret, _, _ = syscall.Syscall(glGetString.Addr(), 1, c.args.a0, 0, 0) - case glfnGetTexParameterfv: - syscall.Syscall(glGetTexParameterfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnGetTexParameteriv: - syscall.Syscall(glGetTexParameteriv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnGetUniformLocation: - ret, _, _ = syscall.Syscall(glGetUniformLocation.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnGetUniformfv: - syscall.Syscall(glGetUniformfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnGetUniformiv: - syscall.Syscall(glGetUniformiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnGetVertexAttribfv: - syscall.Syscall(glGetVertexAttribfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnGetVertexAttribiv: - syscall.Syscall(glGetVertexAttribiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnHint: - syscall.Syscall(glHint.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnIsBuffer: - syscall.Syscall(glIsBuffer.Addr(), 1, c.args.a0, 0, 0) - case glfnIsEnabled: - syscall.Syscall(glIsEnabled.Addr(), 1, c.args.a0, 0, 0) - case glfnIsFramebuffer: - syscall.Syscall(glIsFramebuffer.Addr(), 1, c.args.a0, 0, 0) - case glfnIsProgram: - ret, _, _ = syscall.Syscall(glIsProgram.Addr(), 1, c.args.a0, 0, 0) - case glfnIsRenderbuffer: - syscall.Syscall(glIsRenderbuffer.Addr(), 1, c.args.a0, 0, 0) - case glfnIsShader: - syscall.Syscall(glIsShader.Addr(), 1, c.args.a0, 0, 0) - case glfnIsTexture: - syscall.Syscall(glIsTexture.Addr(), 1, c.args.a0, 0, 0) - case glfnLineWidth: - syscall.Syscall(glLineWidth.Addr(), 1, c.args.a0, 0, 0) - case glfnLinkProgram: - syscall.Syscall(glLinkProgram.Addr(), 1, c.args.a0, 0, 0) - case glfnPixelStorei: - syscall.Syscall(glPixelStorei.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnPolygonOffset: - syscall.Syscall6(glPolygonOffset.Addr(), 2, c.args.a0, c.args.a1, 0, 0, 0, 0) - case glfnReadPixels: - syscall.Syscall9(glReadPixels.Addr(), 7, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, uintptr(c.parg), 0, 0) - case glfnReleaseShaderCompiler: - syscall.Syscall(glReleaseShaderCompiler.Addr(), 0, 0, 0, 0) - case glfnRenderbufferStorage: - syscall.Syscall6(glRenderbufferStorage.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnSampleCoverage: - syscall.Syscall6(glSampleCoverage.Addr(), 1, c.args.a0, 0, 0, 0, 0, 0) - case glfnScissor: - syscall.Syscall6(glScissor.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnShaderSource: - syscall.Syscall6(glShaderSource.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, 0, 0, 0) - case glfnStencilFunc: - syscall.Syscall(glStencilFunc.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) - case glfnStencilFuncSeparate: - syscall.Syscall6(glStencilFuncSeparate.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnStencilMask: - syscall.Syscall(glStencilMask.Addr(), 1, c.args.a0, 0, 0) - case glfnStencilMaskSeparate: - syscall.Syscall(glStencilMaskSeparate.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnStencilOp: - syscall.Syscall(glStencilOp.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) - case glfnStencilOpSeparate: - syscall.Syscall6(glStencilOpSeparate.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnTexImage2D: - syscall.Syscall9(glTexImage2D.Addr(), 9, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, 0, c.args.a5, c.args.a6, uintptr(c.parg)) - case glfnTexParameterf: - syscall.Syscall6(glTexParameterf.Addr(), 3, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnTexParameterfv: - syscall.Syscall(glTexParameterfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnTexParameteri: - syscall.Syscall(glTexParameteri.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) - case glfnTexParameteriv: - syscall.Syscall(glTexParameteriv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnTexSubImage2D: - syscall.Syscall9(glTexSubImage2D.Addr(), 9, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, uintptr(c.parg)) - case glfnUniform1f: - syscall.Syscall6(glUniform1f.Addr(), 2, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnUniform1fv: - syscall.Syscall(glUniform1fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform1i: - syscall.Syscall(glUniform1i.Addr(), 2, c.args.a0, c.args.a1, 0) - case glfnUniform1iv: - syscall.Syscall(glUniform1iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform2f: - syscall.Syscall6(glUniform2f.Addr(), 3, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnUniform2fv: - syscall.Syscall(glUniform2fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform2i: - syscall.Syscall(glUniform2i.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) - case glfnUniform2iv: - syscall.Syscall(glUniform2iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform3f: - syscall.Syscall6(glUniform3f.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnUniform3fv: - syscall.Syscall(glUniform3fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform3i: - syscall.Syscall6(glUniform3i.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - case glfnUniform3iv: - syscall.Syscall(glUniform3iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform4f: - syscall.Syscall6(glUniform4f.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnUniform4fv: - syscall.Syscall(glUniform4fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniform4i: - syscall.Syscall6(glUniform4i.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, 0) - case glfnUniform4iv: - syscall.Syscall(glUniform4iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) - case glfnUniformMatrix2fv: - syscall.Syscall6(glUniformMatrix2fv.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) - case glfnUniformMatrix3fv: - syscall.Syscall6(glUniformMatrix3fv.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) - case glfnUniformMatrix4fv: - syscall.Syscall6(glUniformMatrix4fv.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) - case glfnUseProgram: - syscall.Syscall(glUseProgram.Addr(), 1, c.args.a0, 0, 0) - case glfnValidateProgram: - syscall.Syscall(glValidateProgram.Addr(), 1, c.args.a0, 0, 0) - case glfnVertexAttrib1f: - syscall.Syscall6(glVertexAttrib1f.Addr(), 2, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnVertexAttrib1fv: - syscall.Syscall(glVertexAttrib1fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnVertexAttrib2f: - syscall.Syscall6(glVertexAttrib2f.Addr(), 3, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnVertexAttrib2fv: - syscall.Syscall(glVertexAttrib2fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnVertexAttrib3f: - syscall.Syscall6(glVertexAttrib3f.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnVertexAttrib3fv: - syscall.Syscall(glVertexAttrib3fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnVertexAttrib4f: - syscall.Syscall6(glVertexAttrib4f.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnVertexAttrib4fv: - syscall.Syscall(glVertexAttrib4fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) - case glfnVertexAttribPointer: - syscall.Syscall6(glVertexAttribPointer.Addr(), 6, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) - case glfnViewport: - syscall.Syscall6(glViewport.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) - default: - panic("unknown GL function") - } - - return ret -} - -// Exported libraries for a Windows GUI driver. -// -// LibEGL is not used directly by the gl package, but is needed by any -// driver hoping to use OpenGL ES. -// -// LibD3DCompiler is needed by libglesv2.dll for compiling shaders. -var ( - LibGLESv2 = syscall.NewLazyDLL("libglesv2.dll") - LibEGL = syscall.NewLazyDLL("libegl.dll") - LibD3DCompiler = syscall.NewLazyDLL("d3dcompiler_47.dll") -) - -var ( - libGLESv2 = LibGLESv2 - glActiveTexture = libGLESv2.NewProc("glActiveTexture") - glAttachShader = libGLESv2.NewProc("glAttachShader") - glBindAttribLocation = libGLESv2.NewProc("glBindAttribLocation") - glBindBuffer = libGLESv2.NewProc("glBindBuffer") - glBindFramebuffer = libGLESv2.NewProc("glBindFramebuffer") - glBindRenderbuffer = libGLESv2.NewProc("glBindRenderbuffer") - glBindTexture = libGLESv2.NewProc("glBindTexture") - glBindVertexArray = libGLESv2.NewProc("glBindVertexArray") - glBlendColor = libGLESv2.NewProc("glBlendColor") - glBlendEquation = libGLESv2.NewProc("glBlendEquation") - glBlendEquationSeparate = libGLESv2.NewProc("glBlendEquationSeparate") - glBlendFunc = libGLESv2.NewProc("glBlendFunc") - glBlendFuncSeparate = libGLESv2.NewProc("glBlendFuncSeparate") - glBufferData = libGLESv2.NewProc("glBufferData") - glBufferSubData = libGLESv2.NewProc("glBufferSubData") - glCheckFramebufferStatus = libGLESv2.NewProc("glCheckFramebufferStatus") - glClear = libGLESv2.NewProc("glClear") - glClearColor = libGLESv2.NewProc("glClearColor") - glClearDepthf = libGLESv2.NewProc("glClearDepthf") - glClearStencil = libGLESv2.NewProc("glClearStencil") - glColorMask = libGLESv2.NewProc("glColorMask") - glCompileShader = libGLESv2.NewProc("glCompileShader") - glCompressedTexImage2D = libGLESv2.NewProc("glCompressedTexImage2D") - glCompressedTexSubImage2D = libGLESv2.NewProc("glCompressedTexSubImage2D") - glCopyTexImage2D = libGLESv2.NewProc("glCopyTexImage2D") - glCopyTexSubImage2D = libGLESv2.NewProc("glCopyTexSubImage2D") - glCreateProgram = libGLESv2.NewProc("glCreateProgram") - glCreateShader = libGLESv2.NewProc("glCreateShader") - glCullFace = libGLESv2.NewProc("glCullFace") - glDeleteBuffers = libGLESv2.NewProc("glDeleteBuffers") - glDeleteFramebuffers = libGLESv2.NewProc("glDeleteFramebuffers") - glDeleteProgram = libGLESv2.NewProc("glDeleteProgram") - glDeleteRenderbuffers = libGLESv2.NewProc("glDeleteRenderbuffers") - glDeleteShader = libGLESv2.NewProc("glDeleteShader") - glDeleteTextures = libGLESv2.NewProc("glDeleteTextures") - glDeleteVertexArrays = libGLESv2.NewProc("glDeleteVertexArrays") - glDepthFunc = libGLESv2.NewProc("glDepthFunc") - glDepthRangef = libGLESv2.NewProc("glDepthRangef") - glDepthMask = libGLESv2.NewProc("glDepthMask") - glDetachShader = libGLESv2.NewProc("glDetachShader") - glDisable = libGLESv2.NewProc("glDisable") - glDisableVertexAttribArray = libGLESv2.NewProc("glDisableVertexAttribArray") - glDrawArrays = libGLESv2.NewProc("glDrawArrays") - glDrawElements = libGLESv2.NewProc("glDrawElements") - glEnable = libGLESv2.NewProc("glEnable") - glEnableVertexAttribArray = libGLESv2.NewProc("glEnableVertexAttribArray") - glFinish = libGLESv2.NewProc("glFinish") - glFlush = libGLESv2.NewProc("glFlush") - glFramebufferRenderbuffer = libGLESv2.NewProc("glFramebufferRenderbuffer") - glFramebufferTexture2D = libGLESv2.NewProc("glFramebufferTexture2D") - glFrontFace = libGLESv2.NewProc("glFrontFace") - glGenBuffers = libGLESv2.NewProc("glGenBuffers") - glGenFramebuffers = libGLESv2.NewProc("glGenFramebuffers") - glGenRenderbuffers = libGLESv2.NewProc("glGenRenderbuffers") - glGenTextures = libGLESv2.NewProc("glGenTextures") - glGenVertexArrays = libGLESv2.NewProc("glGenVertexArrays") - glGenerateMipmap = libGLESv2.NewProc("glGenerateMipmap") - glGetActiveAttrib = libGLESv2.NewProc("glGetActiveAttrib") - glGetActiveUniform = libGLESv2.NewProc("glGetActiveUniform") - glGetAttachedShaders = libGLESv2.NewProc("glGetAttachedShaders") - glGetAttribLocation = libGLESv2.NewProc("glGetAttribLocation") - glGetBooleanv = libGLESv2.NewProc("glGetBooleanv") - glGetBufferParameteri = libGLESv2.NewProc("glGetBufferParameteri") - glGetError = libGLESv2.NewProc("glGetError") - glGetFloatv = libGLESv2.NewProc("glGetFloatv") - glGetFramebufferAttachmentParameteriv = libGLESv2.NewProc("glGetFramebufferAttachmentParameteriv") - glGetIntegerv = libGLESv2.NewProc("glGetIntegerv") - glGetProgramInfoLog = libGLESv2.NewProc("glGetProgramInfoLog") - glGetProgramiv = libGLESv2.NewProc("glGetProgramiv") - glGetRenderbufferParameteriv = libGLESv2.NewProc("glGetRenderbufferParameteriv") - glGetShaderInfoLog = libGLESv2.NewProc("glGetShaderInfoLog") - glGetShaderPrecisionFormat = libGLESv2.NewProc("glGetShaderPrecisionFormat") - glGetShaderSource = libGLESv2.NewProc("glGetShaderSource") - glGetShaderiv = libGLESv2.NewProc("glGetShaderiv") - glGetString = libGLESv2.NewProc("glGetString") - glGetTexParameterfv = libGLESv2.NewProc("glGetTexParameterfv") - glGetTexParameteriv = libGLESv2.NewProc("glGetTexParameteriv") - glGetUniformLocation = libGLESv2.NewProc("glGetUniformLocation") - glGetUniformfv = libGLESv2.NewProc("glGetUniformfv") - glGetUniformiv = libGLESv2.NewProc("glGetUniformiv") - glGetVertexAttribfv = libGLESv2.NewProc("glGetVertexAttribfv") - glGetVertexAttribiv = libGLESv2.NewProc("glGetVertexAttribiv") - glHint = libGLESv2.NewProc("glHint") - glIsBuffer = libGLESv2.NewProc("glIsBuffer") - glIsEnabled = libGLESv2.NewProc("glIsEnabled") - glIsFramebuffer = libGLESv2.NewProc("glIsFramebuffer") - glIsProgram = libGLESv2.NewProc("glIsProgram") - glIsRenderbuffer = libGLESv2.NewProc("glIsRenderbuffer") - glIsShader = libGLESv2.NewProc("glIsShader") - glIsTexture = libGLESv2.NewProc("glIsTexture") - glLineWidth = libGLESv2.NewProc("glLineWidth") - glLinkProgram = libGLESv2.NewProc("glLinkProgram") - glPixelStorei = libGLESv2.NewProc("glPixelStorei") - glPolygonOffset = libGLESv2.NewProc("glPolygonOffset") - glReadPixels = libGLESv2.NewProc("glReadPixels") - glReleaseShaderCompiler = libGLESv2.NewProc("glReleaseShaderCompiler") - glRenderbufferStorage = libGLESv2.NewProc("glRenderbufferStorage") - glSampleCoverage = libGLESv2.NewProc("glSampleCoverage") - glScissor = libGLESv2.NewProc("glScissor") - glShaderSource = libGLESv2.NewProc("glShaderSource") - glStencilFunc = libGLESv2.NewProc("glStencilFunc") - glStencilFuncSeparate = libGLESv2.NewProc("glStencilFuncSeparate") - glStencilMask = libGLESv2.NewProc("glStencilMask") - glStencilMaskSeparate = libGLESv2.NewProc("glStencilMaskSeparate") - glStencilOp = libGLESv2.NewProc("glStencilOp") - glStencilOpSeparate = libGLESv2.NewProc("glStencilOpSeparate") - glTexImage2D = libGLESv2.NewProc("glTexImage2D") - glTexParameterf = libGLESv2.NewProc("glTexParameterf") - glTexParameterfv = libGLESv2.NewProc("glTexParameterfv") - glTexParameteri = libGLESv2.NewProc("glTexParameteri") - glTexParameteriv = libGLESv2.NewProc("glTexParameteriv") - glTexSubImage2D = libGLESv2.NewProc("glTexSubImage2D") - glUniform1f = libGLESv2.NewProc("glUniform1f") - glUniform1fv = libGLESv2.NewProc("glUniform1fv") - glUniform1i = libGLESv2.NewProc("glUniform1i") - glUniform1iv = libGLESv2.NewProc("glUniform1iv") - glUniform2f = libGLESv2.NewProc("glUniform2f") - glUniform2fv = libGLESv2.NewProc("glUniform2fv") - glUniform2i = libGLESv2.NewProc("glUniform2i") - glUniform2iv = libGLESv2.NewProc("glUniform2iv") - glUniform3f = libGLESv2.NewProc("glUniform3f") - glUniform3fv = libGLESv2.NewProc("glUniform3fv") - glUniform3i = libGLESv2.NewProc("glUniform3i") - glUniform3iv = libGLESv2.NewProc("glUniform3iv") - glUniform4f = libGLESv2.NewProc("glUniform4f") - glUniform4fv = libGLESv2.NewProc("glUniform4fv") - glUniform4i = libGLESv2.NewProc("glUniform4i") - glUniform4iv = libGLESv2.NewProc("glUniform4iv") - glUniformMatrix2fv = libGLESv2.NewProc("glUniformMatrix2fv") - glUniformMatrix3fv = libGLESv2.NewProc("glUniformMatrix3fv") - glUniformMatrix4fv = libGLESv2.NewProc("glUniformMatrix4fv") - glUseProgram = libGLESv2.NewProc("glUseProgram") - glValidateProgram = libGLESv2.NewProc("glValidateProgram") - glVertexAttrib1f = libGLESv2.NewProc("glVertexAttrib1f") - glVertexAttrib1fv = libGLESv2.NewProc("glVertexAttrib1fv") - glVertexAttrib2f = libGLESv2.NewProc("glVertexAttrib2f") - glVertexAttrib2fv = libGLESv2.NewProc("glVertexAttrib2fv") - glVertexAttrib3f = libGLESv2.NewProc("glVertexAttrib3f") - glVertexAttrib3fv = libGLESv2.NewProc("glVertexAttrib3fv") - glVertexAttrib4f = libGLESv2.NewProc("glVertexAttrib4f") - glVertexAttrib4fv = libGLESv2.NewProc("glVertexAttrib4fv") - glVertexAttribPointer = libGLESv2.NewProc("glVertexAttribPointer") - glViewport = libGLESv2.NewProc("glViewport") -) diff --git a/vendor/golang.org/x/mobile/gl/work_windows_386.s b/vendor/golang.org/x/mobile/gl/work_windows_386.s deleted file mode 100644 index c80e98a..0000000 --- a/vendor/golang.org/x/mobile/gl/work_windows_386.s +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -// fixFloat is unnecessary for windows/386 -TEXT ·fixFloat(SB),NOSPLIT,$0-16 - RET diff --git a/vendor/golang.org/x/mobile/gl/work_windows_amd64.s b/vendor/golang.org/x/mobile/gl/work_windows_amd64.s deleted file mode 100644 index e74ac5c..0000000 --- a/vendor/golang.org/x/mobile/gl/work_windows_amd64.s +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -TEXT ·fixFloat(SB),NOSPLIT,$0-32 - MOVQ x0+0(FP), X0 - MOVQ x1+8(FP), X1 - MOVQ x2+16(FP), X2 - MOVQ x3+24(FP), X3 - RET diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/ctx_android.go b/vendor/golang.org/x/mobile/internal/mobileinit/ctx_android.go deleted file mode 100644 index b58881a..0000000 --- a/vendor/golang.org/x/mobile/internal/mobileinit/ctx_android.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mobileinit - -/* -#include -#include - -static char* lockJNI(JavaVM *vm, uintptr_t* envp, int* attachedp) { - JNIEnv* env; - - if (vm == NULL) { - return "no current JVM"; - } - - *attachedp = 0; - switch ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6)) { - case JNI_OK: - break; - case JNI_EDETACHED: - if ((*vm)->AttachCurrentThread(vm, &env, 0) != 0) { - return "cannot attach to JVM"; - } - *attachedp = 1; - break; - case JNI_EVERSION: - return "bad JNI version"; - default: - return "unknown JNI error from GetEnv"; - } - - *envp = (uintptr_t)env; - return NULL; -} - -static char* checkException(uintptr_t jnienv) { - jthrowable exc; - JNIEnv* env = (JNIEnv*)jnienv; - - if (!(*env)->ExceptionCheck(env)) { - return NULL; - } - - exc = (*env)->ExceptionOccurred(env); - (*env)->ExceptionClear(env); - - jclass clazz = (*env)->FindClass(env, "java/lang/Throwable"); - jmethodID toString = (*env)->GetMethodID(env, clazz, "toString", "()Ljava/lang/String;"); - jobject msgStr = (*env)->CallObjectMethod(env, exc, toString); - return (char*)(*env)->GetStringUTFChars(env, msgStr, 0); -} - -static void unlockJNI(JavaVM *vm) { - (*vm)->DetachCurrentThread(vm); -} -*/ -import "C" - -import ( - "errors" - "runtime" - "unsafe" -) - -// currentVM is stored to initialize other cgo packages. -// -// As all the Go packages in a program form a single shared library, -// there can only be one JNI_OnLoad function for initialization. In -// OpenJDK there is JNI_GetCreatedJavaVMs, but this is not available -// on android. -var currentVM *C.JavaVM - -// currentCtx is Android's android.context.Context. May be NULL. -var currentCtx C.jobject - -// SetCurrentContext populates the global Context object with the specified -// current JavaVM instance (vm) and android.context.Context object (ctx). -// The android.context.Context object must be a global reference. -func SetCurrentContext(vm unsafe.Pointer, ctx uintptr) { - currentVM = (*C.JavaVM)(vm) - currentCtx = (C.jobject)(ctx) -} - -// RunOnJVM runs fn on a new goroutine locked to an OS thread with a JNIEnv. -// -// RunOnJVM blocks until the call to fn is complete. Any Java -// exception or failure to attach to the JVM is returned as an error. -// -// The function fn takes vm, the current JavaVM*, -// env, the current JNIEnv*, and -// ctx, a jobject representing the global android.context.Context. -func RunOnJVM(fn func(vm, env, ctx uintptr) error) error { - errch := make(chan error) - go func() { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - env := C.uintptr_t(0) - attached := C.int(0) - if errStr := C.lockJNI(currentVM, &env, &attached); errStr != nil { - errch <- errors.New(C.GoString(errStr)) - return - } - if attached != 0 { - defer C.unlockJNI(currentVM) - } - - vm := uintptr(unsafe.Pointer(currentVM)) - if err := fn(vm, uintptr(env), uintptr(currentCtx)); err != nil { - errch <- err - return - } - - if exc := C.checkException(env); exc != nil { - errch <- errors.New(C.GoString(exc)) - C.free(unsafe.Pointer(exc)) - return - } - errch <- nil - }() - return <-errch -} diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit.go b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit.go deleted file mode 100644 index 65c0912..0000000 --- a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package mobileinit contains common initialization logic for mobile platforms -// that is relevant to both all-Go apps and gobind-based apps. -// -// Long-term, some code in this package should consider moving into Go stdlib. -package mobileinit - -import "C" diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_android.go b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_android.go deleted file mode 100644 index cd73f43..0000000 --- a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_android.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mobileinit - -/* -To view the log output run: -adb logcat GoLog:I *:S -*/ - -// Android redirects stdout and stderr to /dev/null. -// As these are common debugging utilities in Go, -// we redirect them to logcat. -// -// Unfortunately, logcat is line oriented, so we must buffer. - -/* -#cgo LDFLAGS: -landroid -llog - -#include -#include -#include -*/ -import "C" - -import ( - "bufio" - "log" - "os" - "syscall" - "unsafe" -) - -var ( - ctag = C.CString("GoLog") - // Store the writer end of the redirected stderr and stdout - // so that they are not garbage collected and closed. - stderr, stdout *os.File -) - -type infoWriter struct{} - -func (infoWriter) Write(p []byte) (n int, err error) { - cstr := C.CString(string(p)) - C.__android_log_write(C.ANDROID_LOG_INFO, ctag, cstr) - C.free(unsafe.Pointer(cstr)) - return len(p), nil -} - -func lineLog(f *os.File, priority C.int) { - const logSize = 1024 // matches android/log.h. - r := bufio.NewReaderSize(f, logSize) - for { - line, _, err := r.ReadLine() - str := string(line) - if err != nil { - str += " " + err.Error() - } - cstr := C.CString(str) - C.__android_log_write(priority, ctag, cstr) - C.free(unsafe.Pointer(cstr)) - if err != nil { - break - } - } -} - -func init() { - log.SetOutput(infoWriter{}) - // android logcat includes all of log.LstdFlags - log.SetFlags(log.Flags() &^ log.LstdFlags) - - r, w, err := os.Pipe() - if err != nil { - panic(err) - } - stderr = w - if err := syscall.Dup3(int(w.Fd()), int(os.Stderr.Fd()), 0); err != nil { - panic(err) - } - go lineLog(r, C.ANDROID_LOG_ERROR) - - r, w, err = os.Pipe() - if err != nil { - panic(err) - } - stdout = w - if err := syscall.Dup3(int(w.Fd()), int(os.Stdout.Fd()), 0); err != nil { - panic(err) - } - go lineLog(r, C.ANDROID_LOG_INFO) -} diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_ios.go b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_ios.go deleted file mode 100644 index d41b228..0000000 --- a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_ios.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mobileinit - -import ( - "io" - "log" - "os" - "unsafe" -) - -/* -#include -#include - -os_log_t create_os_log() { - return os_log_create("org.golang.mobile", "os_log"); -} - -void os_log_wrap(os_log_t log, const char *str) { - os_log(log, "%s", str); -} -*/ -import "C" - -type osWriter struct { - w C.os_log_t -} - -func (o osWriter) Write(p []byte) (n int, err error) { - cstr := C.CString(string(p)) - C.os_log_wrap(o.w, cstr) - C.free(unsafe.Pointer(cstr)) - return len(p), nil -} - -func init() { - log.SetOutput(io.MultiWriter(os.Stderr, osWriter{C.create_os_log()})) -} diff --git a/vendor/golang.org/x/mod/semver/semver.go b/vendor/golang.org/x/mod/semver/semver.go index 9a2dfd3..a30a22b 100644 --- a/vendor/golang.org/x/mod/semver/semver.go +++ b/vendor/golang.org/x/mod/semver/semver.go @@ -140,7 +140,7 @@ func Compare(v, w string) int { // Max canonicalizes its arguments and then returns the version string // that compares greater. // -// Deprecated: use [Compare] instead. In most cases, returning a canonicalized +// Deprecated: use Compare instead. In most cases, returning a canonicalized // version is not expected or desired. func Max(v, w string) string { v = Canonical(v) @@ -151,7 +151,7 @@ func Max(v, w string) string { return w } -// ByVersion implements [sort.Interface] for sorting semantic version strings. +// ByVersion implements sort.Interface for sorting semantic version strings. type ByVersion []string func (vs ByVersion) Len() int { return len(vs) } @@ -164,7 +164,7 @@ func (vs ByVersion) Less(i, j int) bool { return vs[i] < vs[j] } -// Sort sorts a list of semantic version strings using [ByVersion]. +// Sort sorts a list of semantic version strings using ByVersion. func Sort(list []string) { sort.Sort(ByVersion(list)) } diff --git a/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile new file mode 100644 index 0000000..8512245 --- /dev/null +++ b/vendor/golang.org/x/net/http2/Dockerfile @@ -0,0 +1,51 @@ +# +# This Dockerfile builds a recent curl with HTTP/2 client support, using +# a recent nghttp2 build. +# +# See the Makefile for how to tag it. If Docker and that image is found, the +# Go tests use this curl binary for integration tests. +# + +FROM ubuntu:trusty + +RUN apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y git-core build-essential wget + +RUN apt-get install -y --no-install-recommends \ + autotools-dev libtool pkg-config zlib1g-dev \ + libcunit1-dev libssl-dev libxml2-dev libevent-dev \ + automake autoconf + +# The list of packages nghttp2 recommends for h2load: +RUN apt-get install -y --no-install-recommends make binutils \ + autoconf automake autotools-dev \ + libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \ + libev-dev libevent-dev libjansson-dev libjemalloc-dev \ + cython python3.4-dev python-setuptools + +# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached: +ENV NGHTTP2_VER 895da9a +RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git + +WORKDIR /root/nghttp2 +RUN git reset --hard $NGHTTP2_VER +RUN autoreconf -i +RUN automake +RUN autoconf +RUN ./configure +RUN make +RUN make install + +WORKDIR /root +RUN wget https://curl.se/download/curl-7.45.0.tar.gz +RUN tar -zxvf curl-7.45.0.tar.gz +WORKDIR /root/curl-7.45.0 +RUN ./configure --with-ssl --with-nghttp2=/usr/local +RUN make +RUN make install +RUN ldconfig + +CMD ["-h"] +ENTRYPOINT ["/usr/local/bin/curl"] + diff --git a/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile new file mode 100644 index 0000000..55fd826 --- /dev/null +++ b/vendor/golang.org/x/net/http2/Makefile @@ -0,0 +1,3 @@ +curlimage: + docker build -t gohttp2/curl . + diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 02c88b6..033b6e6 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -581,11 +581,9 @@ type serverConn struct { advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client curClientStreams uint32 // number of open streams initiated by the client curPushedStreams uint32 // number of open streams initiated by server push - curHandlers uint32 // number of running handler goroutines maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes streams map[uint32]*stream - unstartedHandlers []unstartedHandler initialStreamSendWindowSize int32 maxFrameSize int32 peerMaxHeaderListSize uint32 // zero means unknown (default) @@ -983,8 +981,6 @@ func (sc *serverConn) serve() { return case gracefulShutdownMsg: sc.startGracefulShutdownInternal() - case handlerDoneMsg: - sc.handlerDone() default: panic("unknown timer") } @@ -1016,6 +1012,14 @@ func (sc *serverConn) serve() { } } +func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) { + select { + case <-sc.doneServing: + case <-sharedCh: + close(privateCh) + } +} + type serverMessage int // Message values sent to serveMsgCh. @@ -1024,7 +1028,6 @@ var ( idleTimerMsg = new(serverMessage) shutdownTimerMsg = new(serverMessage) gracefulShutdownMsg = new(serverMessage) - handlerDoneMsg = new(serverMessage) ) func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) } @@ -1897,11 +1900,9 @@ func (st *stream) copyTrailersToHandlerRequest() { // onReadTimeout is run on its own goroutine (from time.AfterFunc) // when the stream's ReadTimeout has fired. func (st *stream) onReadTimeout() { - if st.body != nil { - // Wrap the ErrDeadlineExceeded to avoid callers depending on us - // returning the bare error. - st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded)) - } + // Wrap the ErrDeadlineExceeded to avoid callers depending on us + // returning the bare error. + st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded)) } // onWriteTimeout is run on its own goroutine (from time.AfterFunc) @@ -2019,10 +2020,13 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { // (in Go 1.8), though. That's a more sane option anyway. if sc.hs.ReadTimeout != 0 { sc.conn.SetReadDeadline(time.Time{}) - st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout) + if st.body != nil { + st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout) + } } - return sc.scheduleHandler(id, rw, req, handler) + go sc.runHandler(rw, req, handler) + return nil } func (sc *serverConn) upgradeRequest(req *http.Request) { @@ -2042,10 +2046,6 @@ func (sc *serverConn) upgradeRequest(req *http.Request) { sc.conn.SetReadDeadline(time.Time{}) } - // This is the first request on the connection, - // so start the handler directly rather than going - // through scheduleHandler. - sc.curHandlers++ go sc.runHandler(rw, req, sc.handler.ServeHTTP) } @@ -2286,62 +2286,8 @@ func (sc *serverConn) newResponseWriter(st *stream, req *http.Request) *response return &responseWriter{rws: rws} } -type unstartedHandler struct { - streamID uint32 - rw *responseWriter - req *http.Request - handler func(http.ResponseWriter, *http.Request) -} - -// scheduleHandler starts a handler goroutine, -// or schedules one to start as soon as an existing handler finishes. -func (sc *serverConn) scheduleHandler(streamID uint32, rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) error { - sc.serveG.check() - maxHandlers := sc.advMaxStreams - if sc.curHandlers < maxHandlers { - sc.curHandlers++ - go sc.runHandler(rw, req, handler) - return nil - } - if len(sc.unstartedHandlers) > int(4*sc.advMaxStreams) { - return sc.countError("too_many_early_resets", ConnectionError(ErrCodeEnhanceYourCalm)) - } - sc.unstartedHandlers = append(sc.unstartedHandlers, unstartedHandler{ - streamID: streamID, - rw: rw, - req: req, - handler: handler, - }) - return nil -} - -func (sc *serverConn) handlerDone() { - sc.serveG.check() - sc.curHandlers-- - i := 0 - maxHandlers := sc.advMaxStreams - for ; i < len(sc.unstartedHandlers); i++ { - u := sc.unstartedHandlers[i] - if sc.streams[u.streamID] == nil { - // This stream was reset before its goroutine had a chance to start. - continue - } - if sc.curHandlers >= maxHandlers { - break - } - sc.curHandlers++ - go sc.runHandler(u.rw, u.req, u.handler) - sc.unstartedHandlers[i] = unstartedHandler{} // don't retain references - } - sc.unstartedHandlers = sc.unstartedHandlers[i:] - if len(sc.unstartedHandlers) == 0 { - sc.unstartedHandlers = nil - } -} - // Run on its own goroutine. func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) { - defer sc.sendServeMsg(handlerDoneMsg) didPanic := true defer func() { rw.rws.stream.cancelCtx() diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 4515b22..b0d482f 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -291,7 +291,8 @@ func (t *Transport) initConnPool() { // HTTP/2 server. type ClientConn struct { t *Transport - tconn net.Conn // usually *tls.Conn, except specialized impls + tconn net.Conn // usually *tls.Conn, except specialized impls + tconnClosed bool tlsState *tls.ConnectionState // nil only for specialized impls reused uint32 // whether conn is being reused; atomic singleUse bool // whether being used for a single http.Request diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index b18efb7..948a3ee 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -4,6 +4,9 @@ // Package errgroup provides synchronization, error propagation, and Context // cancelation for groups of goroutines working on subtasks of a common task. +// +// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks +// returning errors. package errgroup import ( diff --git a/vendor/golang.org/x/sync/errgroup/go120.go b/vendor/golang.org/x/sync/errgroup/go120.go index 7d419d3..f93c740 100644 --- a/vendor/golang.org/x/sync/errgroup/go120.go +++ b/vendor/golang.org/x/sync/errgroup/go120.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.20 -// +build go1.20 package errgroup diff --git a/vendor/golang.org/x/sync/errgroup/pre_go120.go b/vendor/golang.org/x/sync/errgroup/pre_go120.go index 1795c18..88ce334 100644 --- a/vendor/golang.org/x/sync/errgroup/pre_go120.go +++ b/vendor/golang.org/x/sync/errgroup/pre_go120.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.20 -// +build !go1.20 package errgroup diff --git a/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go b/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go index c9b6993..73687de 100644 --- a/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go +++ b/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.5 -// +build go1.5 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/pwd_plan9.go b/vendor/golang.org/x/sys/plan9/pwd_plan9.go index 98bf56b..fb94582 100644 --- a/vendor/golang.org/x/sys/plan9/pwd_plan9.go +++ b/vendor/golang.org/x/sys/plan9/pwd_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.5 -// +build !go1.5 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/race.go b/vendor/golang.org/x/sys/plan9/race.go index 62377d2..c02d9ed 100644 --- a/vendor/golang.org/x/sys/plan9/race.go +++ b/vendor/golang.org/x/sys/plan9/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 && race -// +build plan9,race package plan9 diff --git a/vendor/golang.org/x/sys/plan9/race0.go b/vendor/golang.org/x/sys/plan9/race0.go index f8da308..7b15e15 100644 --- a/vendor/golang.org/x/sys/plan9/race0.go +++ b/vendor/golang.org/x/sys/plan9/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 && !race -// +build plan9,!race package plan9 diff --git a/vendor/golang.org/x/sys/plan9/str.go b/vendor/golang.org/x/sys/plan9/str.go index 55fa8d0..ba3e8ff 100644 --- a/vendor/golang.org/x/sys/plan9/str.go +++ b/vendor/golang.org/x/sys/plan9/str.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/syscall.go b/vendor/golang.org/x/sys/plan9/syscall.go index 67e5b01..d631fd6 100644 --- a/vendor/golang.org/x/sys/plan9/syscall.go +++ b/vendor/golang.org/x/sys/plan9/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 // Package plan9 contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go index 3f40b9b..f780d5c 100644 --- a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build plan9 && 386 -// +build plan9,386 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go index 0e6a96a..7de6106 100644 --- a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build plan9 && amd64 -// +build plan9,amd64 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go index 244c501..ea85780 100644 --- a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build plan9 && arm -// +build plan9,arm package plan9 diff --git a/vendor/golang.org/x/sys/unix/aliases.go b/vendor/golang.org/x/sys/unix/aliases.go index abc89c1..e7d3df4 100644 --- a/vendor/golang.org/x/sys/unix/aliases.go +++ b/vendor/golang.org/x/sys/unix/aliases.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9 -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos -// +build go1.9 package unix diff --git a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s index db9171c..269e173 100644 --- a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s +++ b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_386.s b/vendor/golang.org/x/sys/unix/asm_bsd_386.s index e0fcd9b..a4fcef0 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_386.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_386.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (freebsd || netbsd || openbsd) && gc -// +build freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s index 2b99c34..1e63615 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc -// +build darwin dragonfly freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_arm.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s index d702d4a..6496c31 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (freebsd || netbsd || openbsd) && gc -// +build freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s index fe36a73..4fd1f54 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s b/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s index e5b9a84..42f7eb9 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s b/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s index d560019..f890266 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_386.s b/vendor/golang.org/x/sys/unix/asm_linux_386.s index 8fd101d..3b47348 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_386.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_386.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s index 7ed38e4..67e29f3 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/vendor/golang.org/x/sys/unix/asm_linux_arm.s index 8ef1d51..d6ae269 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_arm.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s index 98ae027..01e5e25 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && arm64 && gc -// +build linux -// +build arm64 -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_loong64.s b/vendor/golang.org/x/sys/unix/asm_linux_loong64.s index 5653572..2abf12f 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_loong64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_loong64.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && loong64 && gc -// +build linux -// +build loong64 -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s index 21231d2..f84bae7 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) && gc -// +build linux -// +build mips64 mips64le -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s index 6783b26..f08f628 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) && gc -// +build linux -// +build mips mipsle -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s index 19d4989..bdfc024 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) && gc -// +build linux -// +build ppc64 ppc64le -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s b/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s index e42eb81..2e8c996 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && gc -// +build riscv64 -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s index c46aab3..2c394b1 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && s390x && gc -// +build linux -// +build s390x -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s b/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s index 5e7a116..fab586a 100644 --- a/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s +++ b/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s index f8c5394..f949ec5 100644 --- a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s index 3b54e18..2f67ba8 100644 --- a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s +++ b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x && gc -// +build zos -// +build s390x -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/cap_freebsd.go b/vendor/golang.org/x/sys/unix/cap_freebsd.go index 0b7c6ad..a086578 100644 --- a/vendor/golang.org/x/sys/unix/cap_freebsd.go +++ b/vendor/golang.org/x/sys/unix/cap_freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd -// +build freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/constants.go b/vendor/golang.org/x/sys/unix/constants.go index 394a396..6fb7cb7 100644 --- a/vendor/golang.org/x/sys/unix/constants.go +++ b/vendor/golang.org/x/sys/unix/constants.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/dev_aix_ppc.go b/vendor/golang.org/x/sys/unix/dev_aix_ppc.go index 65a9985..d785134 100644 --- a/vendor/golang.org/x/sys/unix/dev_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/dev_aix_ppc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc -// +build aix,ppc // Functions to access/create device major and minor numbers matching the // encoding used by AIX. diff --git a/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go b/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go index 8fc08ad..623a5e6 100644 --- a/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc64 -// +build aix,ppc64 // Functions to access/create device major and minor numbers matching the // encoding used AIX. diff --git a/vendor/golang.org/x/sys/unix/dev_zos.go b/vendor/golang.org/x/sys/unix/dev_zos.go index a388e59..bb6a64f 100644 --- a/vendor/golang.org/x/sys/unix/dev_zos.go +++ b/vendor/golang.org/x/sys/unix/dev_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x // Functions to access/create device major and minor numbers matching the // encoding used by z/OS. diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go index 2499f97..1ebf117 100644 --- a/vendor/golang.org/x/sys/unix/dirent.go +++ b/vendor/golang.org/x/sys/unix/dirent.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/endian_big.go b/vendor/golang.org/x/sys/unix/endian_big.go index a520265..1095fd3 100644 --- a/vendor/golang.org/x/sys/unix/endian_big.go +++ b/vendor/golang.org/x/sys/unix/endian_big.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64 -// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/endian_little.go b/vendor/golang.org/x/sys/unix/endian_little.go index b0f2bc4..b9f0e27 100644 --- a/vendor/golang.org/x/sys/unix/endian_little.go +++ b/vendor/golang.org/x/sys/unix/endian_little.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh -// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh package unix diff --git a/vendor/golang.org/x/sys/unix/env_unix.go b/vendor/golang.org/x/sys/unix/env_unix.go index 29ccc4d..a96da71 100644 --- a/vendor/golang.org/x/sys/unix/env_unix.go +++ b/vendor/golang.org/x/sys/unix/env_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos // Unix environment variables. diff --git a/vendor/golang.org/x/sys/unix/epoll_zos.go b/vendor/golang.org/x/sys/unix/epoll_zos.go index cedaf7e..7753fdd 100644 --- a/vendor/golang.org/x/sys/unix/epoll_zos.go +++ b/vendor/golang.org/x/sys/unix/epoll_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/fcntl.go b/vendor/golang.org/x/sys/unix/fcntl.go index e9b9912..6200876 100644 --- a/vendor/golang.org/x/sys/unix/fcntl.go +++ b/vendor/golang.org/x/sys/unix/fcntl.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd +//go:build dragonfly || freebsd || linux || netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go index 29d4480..13b4acd 100644 --- a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go +++ b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc) -// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/fdset.go b/vendor/golang.org/x/sys/unix/fdset.go index a8068f9..9e83d18 100644 --- a/vendor/golang.org/x/sys/unix/fdset.go +++ b/vendor/golang.org/x/sys/unix/fdset.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/fstatfs_zos.go b/vendor/golang.org/x/sys/unix/fstatfs_zos.go index e377cc9..c8bde60 100644 --- a/vendor/golang.org/x/sys/unix/fstatfs_zos.go +++ b/vendor/golang.org/x/sys/unix/fstatfs_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/gccgo.go b/vendor/golang.org/x/sys/unix/gccgo.go index b06f52d..aca5721 100644 --- a/vendor/golang.org/x/sys/unix/gccgo.go +++ b/vendor/golang.org/x/sys/unix/gccgo.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo && !aix && !hurd -// +build gccgo,!aix,!hurd package unix diff --git a/vendor/golang.org/x/sys/unix/gccgo_c.c b/vendor/golang.org/x/sys/unix/gccgo_c.c index f98a1c5..d468b7b 100644 --- a/vendor/golang.org/x/sys/unix/gccgo_c.c +++ b/vendor/golang.org/x/sys/unix/gccgo_c.c @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo && !aix && !hurd -// +build gccgo,!aix,!hurd #include #include diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go index e60e49a..972d61b 100644 --- a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo && linux && amd64 -// +build gccgo,linux,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/ifreq_linux.go b/vendor/golang.org/x/sys/unix/ifreq_linux.go index 15721a5..848840a 100644 --- a/vendor/golang.org/x/sys/unix/ifreq_linux.go +++ b/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package unix diff --git a/vendor/golang.org/x/sys/unix/ioctl_linux.go b/vendor/golang.org/x/sys/unix/ioctl_linux.go index 0d12c08..dbe680e 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -231,3 +231,8 @@ func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) { func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error { return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value)) } + +// IoctlLoopConfigure configures all loop device parameters in a single step +func IoctlLoopConfigure(fd int, value *LoopConfig) error { + return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value)) +} diff --git a/vendor/golang.org/x/sys/unix/ioctl_signed.go b/vendor/golang.org/x/sys/unix/ioctl_signed.go index 7def958..5b0759b 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_signed.go +++ b/vendor/golang.org/x/sys/unix/ioctl_signed.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || solaris -// +build aix solaris package unix diff --git a/vendor/golang.org/x/sys/unix/ioctl_unsigned.go b/vendor/golang.org/x/sys/unix/ioctl_unsigned.go index 649913d..20f470b 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_unsigned.go +++ b/vendor/golang.org/x/sys/unix/ioctl_unsigned.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd -// +build darwin dragonfly freebsd hurd linux netbsd openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ioctl_zos.go b/vendor/golang.org/x/sys/unix/ioctl_zos.go index cdc21bf..c8b2a75 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_zos.go +++ b/vendor/golang.org/x/sys/unix/ioctl_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 47fa6a7..fdcaa97 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -248,6 +248,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -283,10 +284,6 @@ struct ltchars { #include #endif -#ifndef MSG_FASTOPEN -#define MSG_FASTOPEN 0x20000000 -#endif - #ifndef PTRACE_GETREGS #define PTRACE_GETREGS 0xc #endif @@ -295,14 +292,6 @@ struct ltchars { #define PTRACE_SETREGS 0xd #endif -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - -#ifndef SOL_SMC -#define SOL_SMC 286 -#endif - #ifdef SOL_BLUETOOTH // SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h // but it is already in bluetooth_linux.go @@ -319,10 +308,23 @@ struct ltchars { #undef TIPC_WAIT_FOREVER #define TIPC_WAIT_FOREVER 0xffffffff -// Copied from linux/l2tp.h -// Including linux/l2tp.h here causes conflicts between linux/in.h -// and netinet/in.h included via net/route.h above. -#define IPPROTO_L2TP 115 +// Copied from linux/netfilter/nf_nat.h +// Including linux/netfilter/nf_nat.h here causes conflicts between linux/in.h +// and netinet/in.h. +#define NF_NAT_RANGE_MAP_IPS (1 << 0) +#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1) +#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2) +#define NF_NAT_RANGE_PERSISTENT (1 << 3) +#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4) +#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5) +#define NF_NAT_RANGE_NETMAP (1 << 6) +#define NF_NAT_RANGE_PROTO_RANDOM_ALL \ + (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY) +#define NF_NAT_RANGE_MASK \ + (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \ + NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \ + NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \ + NF_NAT_RANGE_NETMAP) // Copied from linux/hid.h. // Keep in sync with the size of the referenced fields. @@ -519,6 +521,7 @@ ccflags="$@" $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || + $2 == "LOOP_CONFIGURE" || $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ || @@ -560,7 +563,7 @@ ccflags="$@" $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || $2 ~ /^CLONE_[A-Z_]+/ || - $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ && + $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+|BPF_F_LINK)$/ && $2 ~ /^(BPF|DLT)_/ || $2 ~ /^AUDIT_/ || $2 ~ /^(CLOCK|TIMER)_/ || @@ -581,7 +584,7 @@ ccflags="$@" $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || $2 ~ /^KEYCTL_/ || $2 ~ /^PERF_/ || - $2 ~ /^SECCOMP_MODE_/ || + $2 ~ /^SECCOMP_/ || $2 ~ /^SEEK_/ || $2 ~ /^SCHED_/ || $2 ~ /^SPLICE_/ || @@ -602,6 +605,9 @@ ccflags="$@" $2 ~ /^FSOPT_/ || $2 ~ /^WDIO[CFS]_/ || $2 ~ /^NFN/ || + $2 !~ /^NFT_META_IIFTYPE/ && + $2 ~ /^NFT_/ || + $2 ~ /^NF_NAT_/ || $2 ~ /^XDP_/ || $2 ~ /^RWF_/ || $2 ~ /^(HDIO|WIN|SMART)_/ || @@ -663,7 +669,6 @@ echo '// mkerrors.sh' "$@" echo '// Code generated by the command above; see README.md. DO NOT EDIT.' echo echo "//go:build ${GOARCH} && ${GOOS}" -echo "// +build ${GOARCH},${GOOS}" echo go tool cgo -godefs -- "$@" _const.go >_error.out cat _error.out | grep -vf _error.grep | grep -vf _signal.grep diff --git a/vendor/golang.org/x/sys/unix/mmap_nomremap.go b/vendor/golang.org/x/sys/unix/mmap_nomremap.go index ca05136..4b68e59 100644 --- a/vendor/golang.org/x/sys/unix/mmap_nomremap.go +++ b/vendor/golang.org/x/sys/unix/mmap_nomremap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || openbsd || solaris -// +build aix darwin dragonfly freebsd openbsd solaris package unix diff --git a/vendor/golang.org/x/sys/unix/mremap.go b/vendor/golang.org/x/sys/unix/mremap.go index fa93d0a..fd45fe5 100644 --- a/vendor/golang.org/x/sys/unix/mremap.go +++ b/vendor/golang.org/x/sys/unix/mremap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux || netbsd -// +build linux netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/pagesize_unix.go b/vendor/golang.org/x/sys/unix/pagesize_unix.go index 53f1b4c..4d0a343 100644 --- a/vendor/golang.org/x/sys/unix/pagesize_unix.go +++ b/vendor/golang.org/x/sys/unix/pagesize_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // For Unix, get the pagesize from the runtime. diff --git a/vendor/golang.org/x/sys/unix/pledge_openbsd.go b/vendor/golang.org/x/sys/unix/pledge_openbsd.go index eb48294..6a09af5 100644 --- a/vendor/golang.org/x/sys/unix/pledge_openbsd.go +++ b/vendor/golang.org/x/sys/unix/pledge_openbsd.go @@ -8,54 +8,31 @@ import ( "errors" "fmt" "strconv" - "syscall" - "unsafe" ) // Pledge implements the pledge syscall. // -// The pledge syscall does not accept execpromises on OpenBSD releases -// before 6.3. -// -// execpromises must be empty when Pledge is called on OpenBSD -// releases predating 6.3, otherwise an error will be returned. +// This changes both the promises and execpromises; use PledgePromises or +// PledgeExecpromises to only change the promises or execpromises +// respectively. // // For more information see pledge(2). func Pledge(promises, execpromises string) error { - maj, min, err := majmin() - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - err = pledgeAvailable(maj, min, execpromises) + pptr, err := BytePtrFromString(promises) if err != nil { return err } - pptr, err := syscall.BytePtrFromString(promises) + exptr, err := BytePtrFromString(execpromises) if err != nil { return err } - // This variable will hold either a nil unsafe.Pointer or - // an unsafe.Pointer to a string (execpromises). - var expr unsafe.Pointer - - // If we're running on OpenBSD > 6.2, pass execpromises to the syscall. - if maj > 6 || (maj == 6 && min > 2) { - exptr, err := syscall.BytePtrFromString(execpromises) - if err != nil { - return err - } - expr = unsafe.Pointer(exptr) - } - - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) - if e != 0 { - return e - } - - return nil + return pledge(pptr, exptr) } // PledgePromises implements the pledge syscall. @@ -64,30 +41,16 @@ func Pledge(promises, execpromises string) error { // // For more information see pledge(2). func PledgePromises(promises string) error { - maj, min, err := majmin() - if err != nil { - return err - } - - err = pledgeAvailable(maj, min, "") - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - // This variable holds the execpromises and is always nil. - var expr unsafe.Pointer - - pptr, err := syscall.BytePtrFromString(promises) + pptr, err := BytePtrFromString(promises) if err != nil { return err } - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) - if e != 0 { - return e - } - - return nil + return pledge(pptr, nil) } // PledgeExecpromises implements the pledge syscall. @@ -96,30 +59,16 @@ func PledgePromises(promises string) error { // // For more information see pledge(2). func PledgeExecpromises(execpromises string) error { - maj, min, err := majmin() - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - err = pledgeAvailable(maj, min, execpromises) + exptr, err := BytePtrFromString(execpromises) if err != nil { return err } - // This variable holds the promises and is always nil. - var pptr unsafe.Pointer - - exptr, err := syscall.BytePtrFromString(execpromises) - if err != nil { - return err - } - - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0) - if e != 0 { - return e - } - - return nil + return pledge(nil, exptr) } // majmin returns major and minor version number for an OpenBSD system. @@ -147,16 +96,15 @@ func majmin() (major int, minor int, err error) { // pledgeAvailable checks for availability of the pledge(2) syscall // based on the running OpenBSD version. -func pledgeAvailable(maj, min int, execpromises string) error { - // If OpenBSD <= 5.9, pledge is not available. - if (maj == 5 && min != 9) || maj < 5 { - return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min) +func pledgeAvailable() error { + maj, min, err := majmin() + if err != nil { + return err } - // If OpenBSD <= 6.2 and execpromises is not empty, - // return an error - execpromises is not available before 6.3 - if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" { - return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min) + // Require OpenBSD 6.4 as a minimum. + if maj < 6 || (maj == 6 && min <= 3) { + return fmt.Errorf("cannot call Pledge on OpenBSD %d.%d", maj, min) } return nil diff --git a/vendor/golang.org/x/sys/unix/ptrace_darwin.go b/vendor/golang.org/x/sys/unix/ptrace_darwin.go index 463c3ef..3f0975f 100644 --- a/vendor/golang.org/x/sys/unix/ptrace_darwin.go +++ b/vendor/golang.org/x/sys/unix/ptrace_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package unix diff --git a/vendor/golang.org/x/sys/unix/ptrace_ios.go b/vendor/golang.org/x/sys/unix/ptrace_ios.go index ed0509a..a4d35db 100644 --- a/vendor/golang.org/x/sys/unix/ptrace_ios.go +++ b/vendor/golang.org/x/sys/unix/ptrace_ios.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ios -// +build ios package unix diff --git a/vendor/golang.org/x/sys/unix/race.go b/vendor/golang.org/x/sys/unix/race.go index 6f6c5fe..714d2aa 100644 --- a/vendor/golang.org/x/sys/unix/race.go +++ b/vendor/golang.org/x/sys/unix/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin && race) || (linux && race) || (freebsd && race) -// +build darwin,race linux,race freebsd,race package unix diff --git a/vendor/golang.org/x/sys/unix/race0.go b/vendor/golang.org/x/sys/unix/race0.go index 706e132..4a9f663 100644 --- a/vendor/golang.org/x/sys/unix/race0.go +++ b/vendor/golang.org/x/sys/unix/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos -// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly zos package unix diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdents.go b/vendor/golang.org/x/sys/unix/readdirent_getdents.go index 4d62575..dbd2b6c 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdents.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdents.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || dragonfly || freebsd || linux || netbsd || openbsd -// +build aix dragonfly freebsd linux netbsd openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go index 2a4ba47..130398b 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin -// +build darwin package unix diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go index 3865943..c3a62db 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos // Socket control messages diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go index 0840fe4..4a1eab3 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/syscall.go b/vendor/golang.org/x/sys/unix/syscall.go index 63e8c83..5ea74da 100644 --- a/vendor/golang.org/x/sys/unix/syscall.go +++ b/vendor/golang.org/x/sys/unix/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos // Package unix contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go index e94e6cd..67ce6ce 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix // Aix system calls. // This file is compiled as ordinary Go code, @@ -107,7 +106,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go index f2871fa..1fdaa47 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc -// +build aix,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go index 75718ec..c87f9a9 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc64 -// +build aix,ppc64 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_bsd.go b/vendor/golang.org/x/sys/unix/syscall_bsd.go index 4217de5..a00c3e5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd // BSD system call wrappers shared by *BSD based systems // including OS X (Darwin) and FreeBSD. Like the other @@ -317,7 +316,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { if err != nil { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go index b37310c..0eaecf5 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && darwin -// +build amd64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go index d51ec99..f36c670 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && darwin -// +build arm64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go index 53c9664..16dc699 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && go1.12 -// +build darwin,go1.12 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go index 4e2d321..14bab6b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && dragonfly -// +build amd64,dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go index b8da510..3967bca 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && freebsd -// +build 386,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go index 47155c4..eff19ad 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && freebsd -// +build amd64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go index 0893209..4f24b51 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && freebsd -// +build arm,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go index d151a0d..ac30759 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && freebsd -// +build arm64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go index d5cd64b..aab725c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && freebsd -// +build riscv64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd.go b/vendor/golang.org/x/sys/unix/syscall_hurd.go index 381fd46..ba46651 100644 --- a/vendor/golang.org/x/sys/unix/syscall_hurd.go +++ b/vendor/golang.org/x/sys/unix/syscall_hurd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build hurd -// +build hurd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd_386.go b/vendor/golang.org/x/sys/unix/syscall_hurd_386.go index 7cf54a3..df89f9e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_hurd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_hurd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && hurd -// +build 386,hurd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_illumos.go b/vendor/golang.org/x/sys/unix/syscall_illumos.go index 87db5a6..a863f70 100644 --- a/vendor/golang.org/x/sys/unix/syscall_illumos.go +++ b/vendor/golang.org/x/sys/unix/syscall_illumos.go @@ -5,7 +5,6 @@ // illumos system calls not present on Solaris. //go:build amd64 && illumos -// +build amd64,illumos package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index fb4e502..0f85e29 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -61,15 +61,23 @@ func FanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname string) ( } //sys fchmodat(dirfd int, path string, mode uint32) (err error) - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - // Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior - // and check the flags. Otherwise the mode would be applied to the symlink - // destination which is not what the user expects. - if flags&^AT_SYMLINK_NOFOLLOW != 0 { - return EINVAL - } else if flags&AT_SYMLINK_NOFOLLOW != 0 { - return EOPNOTSUPP +//sys fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) error { + // Linux fchmodat doesn't support the flags parameter, but fchmodat2 does. + // Try fchmodat2 if flags are specified. + if flags != 0 { + err := fchmodat2(dirfd, path, mode, flags) + if err == ENOSYS { + // fchmodat2 isn't available. If the flags are known to be valid, + // return EOPNOTSUPP to indicate that fchmodat doesn't support them. + if flags&^(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 { + return EINVAL + } else if flags&(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 { + return EOPNOTSUPP + } + } + return err } return fchmodat(dirfd, path, mode) } @@ -417,7 +425,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -1301,7 +1310,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { return "", err } } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } func GetsockoptTpacketStats(fd, level, opt int) (*TpacketStats, error) { @@ -2482,3 +2491,5 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { } return attr, nil } + +//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index c7d9945..506dafa 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && linux -// +build 386,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go b/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go index 08086ac..38d5564 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (386 || amd64 || mips || mipsle || mips64 || mipsle || ppc64 || ppc64le || ppc || s390x || sparc64) -// +build linux -// +build 386 amd64 mips mipsle mips64 mipsle ppc64 ppc64le ppc s390x sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 70601ce..d557cf8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux -// +build amd64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go index 8b0f0f3..facdb83 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux && gc -// +build amd64,linux,gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index da29864..cd2dd79 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && linux -// +build arm,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index f526668..cf2ee6c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && linux -// +build arm64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc.go index 2b1168d..ffc4c2b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gc -// +build linux,gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go index 9843fb4..9ebfdcf 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gc && 386 -// +build linux,gc,386 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go index a6008fc..5f2b57c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && gc && linux -// +build arm,gc,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go index 7740af2..d1a3ad8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gccgo && 386 -// +build linux,gccgo,386 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go index e16a122..f2f6742 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gccgo && arm -// +build linux,gccgo,arm package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go index f6ab02e..3d0e984 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build loong64 && linux -// +build loong64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 93fe59d..70963a9 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index aae7f0f..c218ebd 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index 66eff19..e6c4850 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && ppc -// +build linux,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 806aa25..7286a9a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 5e6ceee..6f5a288 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && linux -// +build riscv64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index 2f89e8f..66f3121 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x && linux -// +build s390x,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index 7ca064a..11d1f16 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build sparc64 && linux -// +build sparc64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go index 5199d28..7a5eb57 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && netbsd -// +build 386,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go index 70a9c52..62d8957 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && netbsd -// +build amd64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go index 3eb5942..ce6a068 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && netbsd -// +build arm,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go index fc6ccfd..d46d689 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && netbsd -// +build arm64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 6f34479..b25343c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -137,18 +137,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e } func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { - var _p0 unsafe.Pointer + var bufptr *Statfs_t var bufsize uintptr if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) + bufptr = &buf[0] bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } - r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = e1 - } - return + return getfsstat(bufptr, bufsize, flags) } //sysnb getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) @@ -171,6 +166,20 @@ func Getresgid() (rgid, egid, sgid int) { //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys fcntl(fd int, cmd int, arg int) (n int, err error) +//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) = SYS_FCNTL + +// FcntlInt performs a fcntl syscall on fd with the provided command and argument. +func FcntlInt(fd uintptr, cmd, arg int) (int, error) { + return fcntl(int(fd), cmd, arg) +} + +// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. +func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { + _, err := fcntlPtr(int(fd), cmd, unsafe.Pointer(lk)) + return err +} + //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { @@ -326,4 +335,7 @@ func Uname(uname *Utsname) error { //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) //sys munmap(addr uintptr, length uintptr) (err error) +//sys getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) +//sys pledge(promises *byte, execpromises *byte) (err error) +//sys unveil(path *byte, flags *byte) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go index 6baabcd..9ddc89f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go index bab2536..70a3c96 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go index 8eed3c4..265caa8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go index 483dde9..ac4fda1 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go index 04aa43f..0a451e6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd -// +build openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go index c279613..30a308c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go index 23199a7..ea95433 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index b99cfa1..21974af 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -128,7 +128,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -157,7 +158,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { if err != nil { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } const ImplementsGetwd = true diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go index 0bd25ef..e02d8ce 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && solaris -// +build amd64,solaris package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix.go b/vendor/golang.org/x/sys/unix/syscall_unix.go index f6eda27..77081de 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_gc.go b/vendor/golang.org/x/sys/unix/syscall_unix_gc.go index b6919ca..05c95bc 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix_gc.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || dragonfly || freebsd || (linux && !ppc64 && !ppc64le) || netbsd || openbsd || solaris) && gc -// +build darwin dragonfly freebsd linux,!ppc64,!ppc64le netbsd openbsd solaris -// +build gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go index f6f707a..23f39b7 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64le || ppc64) && gc -// +build linux -// +build ppc64le ppc64 -// +build gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index 4596d04..b473038 100644 --- a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix @@ -1105,7 +1104,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { diff --git a/vendor/golang.org/x/sys/unix/sysvshm_linux.go b/vendor/golang.org/x/sys/unix/sysvshm_linux.go index 2c3a443..4fcd38d 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_linux.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package unix diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/vendor/golang.org/x/sys/unix/sysvshm_unix.go index 5bb41d1..79a84f1 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_unix.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin && !ios) || linux -// +build darwin,!ios linux package unix diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go index 71bddef..9eb0db6 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package unix diff --git a/vendor/golang.org/x/sys/unix/timestruct.go b/vendor/golang.org/x/sys/unix/timestruct.go index 616b1b2..7997b19 100644 --- a/vendor/golang.org/x/sys/unix/timestruct.go +++ b/vendor/golang.org/x/sys/unix/timestruct.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/unveil_openbsd.go b/vendor/golang.org/x/sys/unix/unveil_openbsd.go index 168d5ae..cb7e598 100644 --- a/vendor/golang.org/x/sys/unix/unveil_openbsd.go +++ b/vendor/golang.org/x/sys/unix/unveil_openbsd.go @@ -4,39 +4,48 @@ package unix -import ( - "syscall" - "unsafe" -) +import "fmt" // Unveil implements the unveil syscall. // For more information see unveil(2). // Note that the special case of blocking further // unveil calls is handled by UnveilBlock. func Unveil(path string, flags string) error { - pathPtr, err := syscall.BytePtrFromString(path) - if err != nil { + if err := supportsUnveil(); err != nil { return err } - flagsPtr, err := syscall.BytePtrFromString(flags) + pathPtr, err := BytePtrFromString(path) if err != nil { return err } - _, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(unsafe.Pointer(pathPtr)), uintptr(unsafe.Pointer(flagsPtr)), 0) - if e != 0 { - return e + flagsPtr, err := BytePtrFromString(flags) + if err != nil { + return err } - return nil + return unveil(pathPtr, flagsPtr) } // UnveilBlock blocks future unveil calls. // For more information see unveil(2). func UnveilBlock() error { - // Both pointers must be nil. - var pathUnsafe, flagsUnsafe unsafe.Pointer - _, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(pathUnsafe), uintptr(flagsUnsafe), 0) - if e != 0 { - return e + if err := supportsUnveil(); err != nil { + return err } + return unveil(nil, nil) +} + +// supportsUnveil checks for availability of the unveil(2) system call based +// on the running OpenBSD version. +func supportsUnveil() error { + maj, min, err := majmin() + if err != nil { + return err + } + + // unveil is not available before 6.4 + if maj < 6 || (maj == 6 && min <= 3) { + return fmt.Errorf("cannot call Unveil on OpenBSD %d.%d", maj, min) + } + return nil } diff --git a/vendor/golang.org/x/sys/unix/xattr_bsd.go b/vendor/golang.org/x/sys/unix/xattr_bsd.go index f5f8e9f..e168793 100644 --- a/vendor/golang.org/x/sys/unix/xattr_bsd.go +++ b/vendor/golang.org/x/sys/unix/xattr_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd || netbsd -// +build freebsd netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go index ca9799b..2fb219d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && aix -// +build ppc,aix // Created by cgo -godefs - DO NOT EDIT // cgo -godefs -- -maix32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go index 200c8c2..b0e6f5c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && aix -// +build ppc64,aix // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -maix64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index 1430076..e40fa85 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index ab044a7..bb02aa6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index 17bba0e..c0e0f86 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index f8c2c51..6c69239 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go index 96310c3..dd9163f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go index 777b69d..493a2a7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go index c557ac2..8b437b3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go index 341b4d9..67c02dd 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && freebsd -// +build riscv64,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index f9c7f47..36bf839 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1,7 +1,6 @@ // Code generated by mkmerge; DO NOT EDIT. //go:build linux -// +build linux package unix @@ -481,10 +480,13 @@ const ( BPF_FROM_BE = 0x8 BPF_FROM_LE = 0x0 BPF_FS_MAGIC = 0xcafe4a11 + BPF_F_AFTER = 0x10 BPF_F_ALLOW_MULTI = 0x2 BPF_F_ALLOW_OVERRIDE = 0x1 BPF_F_ANY_ALIGNMENT = 0x2 - BPF_F_KPROBE_MULTI_RETURN = 0x1 + BPF_F_BEFORE = 0x8 + BPF_F_ID = 0x20 + BPF_F_NETFILTER_IP_DEFRAG = 0x1 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REPLACE = 0x4 BPF_F_SLEEPABLE = 0x10 @@ -521,6 +523,7 @@ const ( BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 BPF_MEM = 0x60 + BPF_MEMSX = 0x80 BPF_MEMWORDS = 0x10 BPF_MINOR_VERSION = 0x1 BPF_MISC = 0x7 @@ -776,6 +779,8 @@ const ( DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" DEVLINK_GENL_NAME = "devlink" DEVLINK_GENL_VERSION = 0x1 + DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO = 0x4 + DEVLINK_PORT_FN_CAP_IPSEC_PACKET = 0x8 DEVLINK_PORT_FN_CAP_MIGRATABLE = 0x2 DEVLINK_PORT_FN_CAP_ROCE = 0x1 DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 @@ -1698,6 +1703,7 @@ const ( KEXEC_ON_CRASH = 0x1 KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 + KEXEC_UPDATE_ELFCOREHDR = 0x4 KEYCTL_ASSUME_AUTHORITY = 0x10 KEYCTL_CAPABILITIES = 0x1f KEYCTL_CAPS0_BIG_KEY = 0x10 @@ -1779,6 +1785,8 @@ const ( LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20 LANDLOCK_ACCESS_FS_TRUNCATE = 0x4000 LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2 + LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 + LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 LINUX_REBOOT_CMD_CAD_OFF = 0x0 LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef @@ -1795,6 +1803,7 @@ const ( LOCK_SH = 0x1 LOCK_UN = 0x8 LOOP_CLR_FD = 0x4c01 + LOOP_CONFIGURE = 0x4c0a LOOP_CTL_ADD = 0x4c80 LOOP_CTL_GET_FREE = 0x4c82 LOOP_CTL_REMOVE = 0x4c81 @@ -2120,6 +2129,60 @@ const ( NFNL_SUBSYS_QUEUE = 0x3 NFNL_SUBSYS_ULOG = 0x4 NFS_SUPER_MAGIC = 0x6969 + NFT_CHAIN_FLAGS = 0x7 + NFT_CHAIN_MAXNAMELEN = 0x100 + NFT_CT_MAX = 0x17 + NFT_DATA_RESERVED_MASK = 0xffffff00 + NFT_DATA_VALUE_MAXLEN = 0x40 + NFT_EXTHDR_OP_MAX = 0x4 + NFT_FIB_RESULT_MAX = 0x3 + NFT_INNER_MASK = 0xf + NFT_LOGLEVEL_MAX = 0x8 + NFT_NAME_MAXLEN = 0x100 + NFT_NG_MAX = 0x1 + NFT_OBJECT_CONNLIMIT = 0x5 + NFT_OBJECT_COUNTER = 0x1 + NFT_OBJECT_CT_EXPECT = 0x9 + NFT_OBJECT_CT_HELPER = 0x3 + NFT_OBJECT_CT_TIMEOUT = 0x7 + NFT_OBJECT_LIMIT = 0x4 + NFT_OBJECT_MAX = 0xa + NFT_OBJECT_QUOTA = 0x2 + NFT_OBJECT_SECMARK = 0x8 + NFT_OBJECT_SYNPROXY = 0xa + NFT_OBJECT_TUNNEL = 0x6 + NFT_OBJECT_UNSPEC = 0x0 + NFT_OBJ_MAXNAMELEN = 0x100 + NFT_OSF_MAXGENRELEN = 0x10 + NFT_QUEUE_FLAG_BYPASS = 0x1 + NFT_QUEUE_FLAG_CPU_FANOUT = 0x2 + NFT_QUEUE_FLAG_MASK = 0x3 + NFT_REG32_COUNT = 0x10 + NFT_REG32_SIZE = 0x4 + NFT_REG_MAX = 0x4 + NFT_REG_SIZE = 0x10 + NFT_REJECT_ICMPX_MAX = 0x3 + NFT_RT_MAX = 0x4 + NFT_SECMARK_CTX_MAXLEN = 0x100 + NFT_SET_MAXNAMELEN = 0x100 + NFT_SOCKET_MAX = 0x3 + NFT_TABLE_F_MASK = 0x3 + NFT_TABLE_MAXNAMELEN = 0x100 + NFT_TRACETYPE_MAX = 0x3 + NFT_TUNNEL_F_MASK = 0x7 + NFT_TUNNEL_MAX = 0x1 + NFT_TUNNEL_MODE_MAX = 0x2 + NFT_USERDATA_MAXLEN = 0x100 + NFT_XFRM_KEY_MAX = 0x6 + NF_NAT_RANGE_MAP_IPS = 0x1 + NF_NAT_RANGE_MASK = 0x7f + NF_NAT_RANGE_NETMAP = 0x40 + NF_NAT_RANGE_PERSISTENT = 0x8 + NF_NAT_RANGE_PROTO_OFFSET = 0x20 + NF_NAT_RANGE_PROTO_RANDOM = 0x4 + NF_NAT_RANGE_PROTO_RANDOM_ALL = 0x14 + NF_NAT_RANGE_PROTO_RANDOM_FULLY = 0x10 + NF_NAT_RANGE_PROTO_SPECIFIED = 0x2 NILFS_SUPER_MAGIC = 0x3434 NL0 = 0x0 NL1 = 0x100 @@ -2275,6 +2338,7 @@ const ( PERF_MEM_LVLNUM_PMEM = 0xe PERF_MEM_LVLNUM_RAM = 0xd PERF_MEM_LVLNUM_SHIFT = 0x21 + PERF_MEM_LVLNUM_UNC = 0x8 PERF_MEM_LVL_HIT = 0x2 PERF_MEM_LVL_IO = 0x1000 PERF_MEM_LVL_L1 = 0x8 @@ -2403,6 +2467,7 @@ const ( PR_MCE_KILL_GET = 0x22 PR_MCE_KILL_LATE = 0x0 PR_MCE_KILL_SET = 0x1 + PR_MDWE_NO_INHERIT = 0x2 PR_MDWE_REFUSE_EXEC_GAIN = 0x1 PR_MPX_DISABLE_MANAGEMENT = 0x2c PR_MPX_ENABLE_MANAGEMENT = 0x2b @@ -2607,8 +2672,9 @@ const ( RTAX_FEATURES = 0xc RTAX_FEATURE_ALLFRAG = 0x8 RTAX_FEATURE_ECN = 0x1 - RTAX_FEATURE_MASK = 0xf + RTAX_FEATURE_MASK = 0x1f RTAX_FEATURE_SACK = 0x2 + RTAX_FEATURE_TCP_USEC_TS = 0x10 RTAX_FEATURE_TIMESTAMP = 0x4 RTAX_HOPLIMIT = 0xa RTAX_INITCWND = 0xb @@ -2851,9 +2917,38 @@ const ( SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x1d SC_LOG_FLUSH = 0x100000 + SECCOMP_ADDFD_FLAG_SEND = 0x2 + SECCOMP_ADDFD_FLAG_SETFD = 0x1 + SECCOMP_FILTER_FLAG_LOG = 0x2 + SECCOMP_FILTER_FLAG_NEW_LISTENER = 0x8 + SECCOMP_FILTER_FLAG_SPEC_ALLOW = 0x4 + SECCOMP_FILTER_FLAG_TSYNC = 0x1 + SECCOMP_FILTER_FLAG_TSYNC_ESRCH = 0x10 + SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV = 0x20 + SECCOMP_GET_ACTION_AVAIL = 0x2 + SECCOMP_GET_NOTIF_SIZES = 0x3 + SECCOMP_IOCTL_NOTIF_RECV = 0xc0502100 + SECCOMP_IOCTL_NOTIF_SEND = 0xc0182101 + SECCOMP_IOC_MAGIC = '!' SECCOMP_MODE_DISABLED = 0x0 SECCOMP_MODE_FILTER = 0x2 SECCOMP_MODE_STRICT = 0x1 + SECCOMP_RET_ACTION = 0x7fff0000 + SECCOMP_RET_ACTION_FULL = 0xffff0000 + SECCOMP_RET_ALLOW = 0x7fff0000 + SECCOMP_RET_DATA = 0xffff + SECCOMP_RET_ERRNO = 0x50000 + SECCOMP_RET_KILL = 0x0 + SECCOMP_RET_KILL_PROCESS = 0x80000000 + SECCOMP_RET_KILL_THREAD = 0x0 + SECCOMP_RET_LOG = 0x7ffc0000 + SECCOMP_RET_TRACE = 0x7ff00000 + SECCOMP_RET_TRAP = 0x30000 + SECCOMP_RET_USER_NOTIF = 0x7fc00000 + SECCOMP_SET_MODE_FILTER = 0x1 + SECCOMP_SET_MODE_STRICT = 0x0 + SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP = 0x1 + SECCOMP_USER_NOTIF_FLAG_CONTINUE = 0x1 SECRETMEM_MAGIC = 0x5345434d SECURITYFS_MAGIC = 0x73636673 SEEK_CUR = 0x1 @@ -3013,6 +3108,7 @@ const ( SOL_TIPC = 0x10f SOL_TLS = 0x11a SOL_UDP = 0x11 + SOL_VSOCK = 0x11f SOL_X25 = 0x106 SOL_XDP = 0x11b SOMAXCONN = 0x1000 @@ -3461,6 +3557,7 @@ const ( XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 + XDP_PKT_CONTD = 0x1 XDP_RING_NEED_WAKEUP = 0x1 XDP_RX_RING = 0x2 XDP_SHARED_UMEM = 0x1 @@ -3473,6 +3570,7 @@ const ( XDP_UMEM_REG = 0x4 XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1 XDP_USE_NEED_WAKEUP = 0x8 + XDP_USE_SG = 0x10 XDP_ZEROCOPY = 0x4 XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 30aee00..42ff8c3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux -// +build 386,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/386/include -m32 _const.go @@ -282,6 +281,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 8ebfa51..dca4360 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/amd64/include -m64 _const.go @@ -283,6 +282,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 271a21c..5cca668 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux -// +build arm,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/arm/include _const.go @@ -289,6 +288,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 910c330..d8cae6d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/arm64/include -fsigned-char _const.go @@ -279,6 +278,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index a640798..28e39af 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux -// +build loong64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/loong64/include _const.go @@ -119,6 +118,7 @@ const ( IXOFF = 0x1000 IXON = 0x400 LASX_CTX_MAGIC = 0x41535801 + LBT_CTX_MAGIC = 0x42540001 LSX_CTX_MAGIC = 0x53580001 MAP_ANON = 0x20 MAP_ANONYMOUS = 0x20 @@ -275,6 +275,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 0d5925d..cd66e92 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux -// +build mips,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mips/include _const.go @@ -282,6 +281,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index d72a00e..c1595eb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux -// +build mips64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mips64/include _const.go @@ -282,6 +281,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 02ba129..ee9456b 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux -// +build mips64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mips64le/include _const.go @@ -282,6 +281,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 8daa6dd..8cfca81 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux -// +build mipsle,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mipsle/include _const.go @@ -282,6 +281,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x80 SIOCATMARK = 0x40047307 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 63c8fa2..60b0deb 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux -// +build ppc,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/ppc/include _const.go @@ -337,6 +336,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 930799e..f90aa72 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/ppc64/include _const.go @@ -341,6 +340,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 8605a7d..ba9e015 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/ppc64le/include _const.go @@ -341,6 +340,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 95a016f..07cdfd6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux -// +build riscv64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/riscv64/include _const.go @@ -228,6 +227,9 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTRACE_GETFDPIC = 0x21 + PTRACE_GETFDPIC_EXEC = 0x0 + PTRACE_GETFDPIC_INTERP = 0x1 RLIMIT_AS = 0x9 RLIMIT_MEMLOCK = 0x8 RLIMIT_NOFILE = 0x7 @@ -270,6 +272,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 1ae0108..2f1dd21 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux -// +build s390x,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/s390x/include -fsigned-char _const.go @@ -345,6 +344,9 @@ const ( SCM_TIMESTAMPNS = 0x23 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 SFD_CLOEXEC = 0x80000 SFD_NONBLOCK = 0x800 SIOCATMARK = 0x8905 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 1bb7c63..f40519d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux -// +build sparc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/sparc64/include _const.go @@ -336,6 +335,9 @@ const ( SCM_TIMESTAMPNS = 0x21 SCM_TXTIME = 0x3f SCM_WIFI_STATUS = 0x25 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x80082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x80082104 SFD_CLOEXEC = 0x400000 SFD_NONBLOCK = 0x4000 SF_FP = 0x38 diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go index 72f7420..130085d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go index 8d4eb0c..84769a1 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go index 9eef974..602ded0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -marm _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go index 3b62ba1..efc0406 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go index af20e47..5a6500f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index 6015fcb..a5aeeb9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go index 8d44955..0e9748a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go index ae16fe7..4f4449a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go index 03d90fe..76a363f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go index 8e2c51b..43ca0cd 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go index 13d4030..b1b8bb2 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go index 1afee6a..d2ddd31 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && solaris -// +build amd64,solaris // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go index fc7d050..4dfd2e0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x // Hand edited based on zerrors_linux_s390x.go // TODO: auto-generate. diff --git a/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go b/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go index 97f20ca..586317c 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("arm", "arm64"). DO NOT EDIT. //go:build linux && (arm || arm64) -// +build linux -// +build arm arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go b/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go index 0b5f794..d7c881b 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("mips", "mips64"). DO NOT EDIT. //go:build linux && (mips || mips64) -// +build linux -// +build mips mips64 package unix diff --git a/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go b/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go index 2807f7e..2d2de5d 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("mipsle", "mips64le"). DO NOT EDIT. //go:build linux && (mipsle || mips64le) -// +build linux -// +build mipsle mips64le package unix diff --git a/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go b/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go index 281ea64..5adc79f 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("386", "amd64"). DO NOT EDIT. //go:build linux && (386 || amd64) -// +build linux -// +build 386 amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go index d1d1d23..6ea64a3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc -// +build aix,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go index f99a18a..99ee439 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc64 -// +build aix,ppc64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go index c4d50ae..b68a783 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc64 && gc -// +build aix,ppc64,gc package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go index 6903d3b..0a87450 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc64 && gccgo -// +build aix,ppc64,gccgo package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 1cad561..ccb02f2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build darwin && amd64 -// +build darwin,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index b18edbd..1b40b99 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build darwin && arm64 -// +build darwin,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index 0c67df6..aad65fc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build dragonfly && amd64 -// +build dragonfly,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go index e6e05d1..c009639 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && 386 -// +build freebsd,386 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index 7508acc..7664df7 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && amd64 -// +build freebsd,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index 7b56aea..ae09918 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && arm -// +build freebsd,arm package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go index cc623dc..11fd5d4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && arm64 -// +build freebsd,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go index 5818491..c3d2d65 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && riscv64 -// +build freebsd,riscv64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go index 6be25cd..c698cbc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build illumos && amd64 -// +build illumos,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 1ff3aec..1488d27 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -1,7 +1,6 @@ // Code generated by mkmerge; DO NOT EDIT. //go:build linux -// +build linux package unix @@ -38,6 +37,21 @@ func fchmodat(dirfd int, path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT2, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ioctl(fd int, req uint, arg uintptr) (err error) { _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { @@ -2195,3 +2209,13 @@ func schedGetattr(pid int, attr *SchedAttr, size uint, flags uint) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) { + _, _, e1 := Syscall6(SYS_CACHESTAT, uintptr(fd), uintptr(unsafe.Pointer(crange)), uintptr(unsafe.Pointer(cstat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index 07b549c..4def3e9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && 386 -// +build linux,386 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 5f481bf..fef2bc8 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && amd64 -// +build linux,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 824cd52..a9fd76a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && arm -// +build linux,arm package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index e77aecf..4600650 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && arm64 -// +build linux,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go index 806ffd1..c8987d2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && loong64 -// +build linux,loong64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 961a3af..921f430 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips -// +build linux,mips package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index ed05005..44f0678 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips64 -// +build linux,mips64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index d365b71..e7fa0ab 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips64le -// +build linux,mips64le package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index c3f1b8b..8c51256 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mipsle -// +build linux,mipsle package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go index a6574cf..7392fd4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc -// +build linux,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index f409902..4118043 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc64 -// +build linux,ppc64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 9dfcc29..40c6ce7 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc64le -// +build linux,ppc64le package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index 0ab4f2e..2cfe34a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && riscv64 -// +build linux,riscv64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 6cde322..61e6f07 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && s390x -// +build linux,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 5253d65..834b842 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && sparc64 -// +build linux,sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 2df3c5b..e91ebc1 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && 386 -// +build netbsd,386 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index a60556b..be28bab 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && amd64 -// +build netbsd,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 9f78891..fb587e8 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && arm -// +build netbsd,arm package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go index 82a4cb2..d576438 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && arm64 -// +build netbsd,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 66b3b64..9dc4241 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && 386 -// +build openbsd,386 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s index 3dcacd3..41b5617 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $4 DATA ·libc_sysctl_trampoline_addr(SB)/4, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fcntl_trampoline_addr(SB)/4, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $4 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $4 DATA ·libc_munmap_trampoline_addr(SB)/4, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getfsstat_trampoline_addr(SB)/4, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4 DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index c5c4cc1..0d3a075 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && amd64 -// +build openbsd,amd64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s index 2763620..4019a65 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 93bfbb3..c39f777 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && arm -// +build openbsd,arm package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s index c922314..ac4af24 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $4 DATA ·libc_sysctl_trampoline_addr(SB)/4, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fcntl_trampoline_addr(SB)/4, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $4 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $4 DATA ·libc_munmap_trampoline_addr(SB)/4, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getfsstat_trampoline_addr(SB)/4, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4 DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index a107b8f..57571d0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && arm64 -// +build openbsd,arm64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s index a6bc32c..f77d532 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go index c427de5..e62963e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && mips64 -// +build openbsd,mips64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s index b4e7bce..fae140b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go index 60c1a99..0083135 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && ppc64 -// +build openbsd,ppc64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s index ca3f766..9d1e0ff 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s @@ -213,6 +213,12 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fcntl(SB) + RET +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_ppoll(SB) RET @@ -801,8 +807,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getfsstat(SB) + RET +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_utimensat(SB) RET GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pledge(SB) + RET +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_unveil(SB) + RET +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go index 52eba36..79029ed 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && riscv64 -// +build openbsd,riscv64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,31 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s index 477a7d5..da115f9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index b401894..829b87f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build solaris && amd64 -// +build solaris,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go index 1d8fe1d..94f0112 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go index 55e0484..3a58ae8 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go index d2243cf..dcb7a0e 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go index 82dc51b..db5a7bf 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go index cbdda1a..7be575a 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go index f55eae1..d6e3174 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go index e440544..ee97157 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go index a0db82f..35c3b91 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go index f8298ff..5edda76 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go index 5eb433b..0dc9e8b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go index 703675c..308ddf3 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go index 4e0d961..418664e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go index 01636b8..34d0b86 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go index ad99bc1..b71cf45 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go index 89dcc42..e32df1c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go index ee37aaa..15ad611 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && freebsd -// +build riscv64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 9862853..0cc3ce4 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux -// +build 386,linux package unix @@ -448,4 +447,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 8901f0f..856d92d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux package unix @@ -370,4 +369,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 6902c37..8d46709 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux -// +build arm,linux package unix @@ -412,4 +411,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index a6d3dff..edc1732 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux package unix @@ -315,4 +314,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index b18f3f7..445eba2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux -// +build loong64,linux package unix @@ -309,4 +308,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 0302e5e..adba01b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux -// +build mips,linux package unix @@ -432,4 +431,9 @@ const ( SYS_FUTEX_WAITV = 4449 SYS_SET_MEMPOLICY_HOME_NODE = 4450 SYS_CACHESTAT = 4451 + SYS_FCHMODAT2 = 4452 + SYS_MAP_SHADOW_STACK = 4453 + SYS_FUTEX_WAKE = 4454 + SYS_FUTEX_WAIT = 4455 + SYS_FUTEX_REQUEUE = 4456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 6693ba4..014c4e9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux -// +build mips64,linux package unix @@ -362,4 +361,9 @@ const ( SYS_FUTEX_WAITV = 5449 SYS_SET_MEMPOLICY_HOME_NODE = 5450 SYS_CACHESTAT = 5451 + SYS_FCHMODAT2 = 5452 + SYS_MAP_SHADOW_STACK = 5453 + SYS_FUTEX_WAKE = 5454 + SYS_FUTEX_WAIT = 5455 + SYS_FUTEX_REQUEUE = 5456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index fd93f49..ccc97d7 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux -// +build mips64le,linux package unix @@ -362,4 +361,9 @@ const ( SYS_FUTEX_WAITV = 5449 SYS_SET_MEMPOLICY_HOME_NODE = 5450 SYS_CACHESTAT = 5451 + SYS_FCHMODAT2 = 5452 + SYS_MAP_SHADOW_STACK = 5453 + SYS_FUTEX_WAKE = 5454 + SYS_FUTEX_WAIT = 5455 + SYS_FUTEX_REQUEUE = 5456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 760ddca..ec2b64a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux -// +build mipsle,linux package unix @@ -432,4 +431,9 @@ const ( SYS_FUTEX_WAITV = 4449 SYS_SET_MEMPOLICY_HOME_NODE = 4450 SYS_CACHESTAT = 4451 + SYS_FCHMODAT2 = 4452 + SYS_MAP_SHADOW_STACK = 4453 + SYS_FUTEX_WAKE = 4454 + SYS_FUTEX_WAIT = 4455 + SYS_FUTEX_REQUEUE = 4456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index cff2b25..21a839e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux -// +build ppc,linux package unix @@ -439,4 +438,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index a4b2405..c11121e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux package unix @@ -411,4 +410,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index aca54b4..909b631 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux package unix @@ -411,4 +410,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 9d1738d..e49bed1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux -// +build riscv64,linux package unix @@ -316,4 +315,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 022878d..66017d2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux -// +build s390x,linux package unix @@ -377,4 +376,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 4100a76..47bab18 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux -// +build sparc64,linux package unix @@ -390,4 +389,9 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 + SYS_FUTEX_WAKE = 454 + SYS_FUTEX_WAIT = 455 + SYS_FUTEX_REQUEUE = 456 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go index 3a6699e..b2aa8cd 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go index 5677cd4..524a1b1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go index e784cb6..d59b943 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go index bd4952e..31e771d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go index 5977338..9fd77c6 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go index 16af291..af10af2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go index f59b18a..cc2028a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go index 721ef59..c06dd44 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go index 01c43a0..9ddbf3e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go index f258cfa..19a6ee4 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go index 07919e0..05192a7 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go index 073daad..b2e3085 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go index 7a8161c..3e6d57c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && aix -// +build ppc,aix package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go index 07ed733..3a219bd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && aix -// +build ppc64,aix package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 690cefc..091d107 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 5bffc10..28ff4ef 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index d0ba8e9..30e405b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 29dc483..6cbd094 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index 0a89b28..7c03b6e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index c8666bb..422107e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index 88fb48a..505a12a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go index 698dc97..cc986c7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && freebsd -// +build riscv64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 18aa70b..dc0c955 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -1,7 +1,6 @@ // Code generated by mkmerge; DO NOT EDIT. //go:build linux -// +build linux package unix @@ -175,7 +174,8 @@ type FscryptPolicyV2 struct { Contents_encryption_mode uint8 Filenames_encryption_mode uint8 Flags uint8 - _ [4]uint8 + Log2_data_unit_size uint8 + _ [3]uint8 Master_key_identifier [16]uint8 } @@ -456,60 +456,63 @@ type Ucred struct { } type TCPInfo struct { - State uint8 - Ca_state uint8 - Retransmits uint8 - Probes uint8 - Backoff uint8 - Options uint8 - Rto uint32 - Ato uint32 - Snd_mss uint32 - Rcv_mss uint32 - Unacked uint32 - Sacked uint32 - Lost uint32 - Retrans uint32 - Fackets uint32 - Last_data_sent uint32 - Last_ack_sent uint32 - Last_data_recv uint32 - Last_ack_recv uint32 - Pmtu uint32 - Rcv_ssthresh uint32 - Rtt uint32 - Rttvar uint32 - Snd_ssthresh uint32 - Snd_cwnd uint32 - Advmss uint32 - Reordering uint32 - Rcv_rtt uint32 - Rcv_space uint32 - Total_retrans uint32 - Pacing_rate uint64 - Max_pacing_rate uint64 - Bytes_acked uint64 - Bytes_received uint64 - Segs_out uint32 - Segs_in uint32 - Notsent_bytes uint32 - Min_rtt uint32 - Data_segs_in uint32 - Data_segs_out uint32 - Delivery_rate uint64 - Busy_time uint64 - Rwnd_limited uint64 - Sndbuf_limited uint64 - Delivered uint32 - Delivered_ce uint32 - Bytes_sent uint64 - Bytes_retrans uint64 - Dsack_dups uint32 - Reord_seen uint32 - Rcv_ooopack uint32 - Snd_wnd uint32 - Rcv_wnd uint32 - Rehash uint32 + State uint8 + Ca_state uint8 + Retransmits uint8 + Probes uint8 + Backoff uint8 + Options uint8 + Rto uint32 + Ato uint32 + Snd_mss uint32 + Rcv_mss uint32 + Unacked uint32 + Sacked uint32 + Lost uint32 + Retrans uint32 + Fackets uint32 + Last_data_sent uint32 + Last_ack_sent uint32 + Last_data_recv uint32 + Last_ack_recv uint32 + Pmtu uint32 + Rcv_ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Advmss uint32 + Reordering uint32 + Rcv_rtt uint32 + Rcv_space uint32 + Total_retrans uint32 + Pacing_rate uint64 + Max_pacing_rate uint64 + Bytes_acked uint64 + Bytes_received uint64 + Segs_out uint32 + Segs_in uint32 + Notsent_bytes uint32 + Min_rtt uint32 + Data_segs_in uint32 + Data_segs_out uint32 + Delivery_rate uint64 + Busy_time uint64 + Rwnd_limited uint64 + Sndbuf_limited uint64 + Delivered uint32 + Delivered_ce uint32 + Bytes_sent uint64 + Bytes_retrans uint64 + Dsack_dups uint32 + Reord_seen uint32 + Rcv_ooopack uint32 + Snd_wnd uint32 + Rcv_wnd uint32 + Rehash uint32 + Total_rto uint16 + Total_rto_recoveries uint16 + Total_rto_time uint32 } type CanFilter struct { @@ -552,7 +555,7 @@ const ( SizeofIPv6MTUInfo = 0x20 SizeofICMPv6Filter = 0x20 SizeofUcred = 0xc - SizeofTCPInfo = 0xf0 + SizeofTCPInfo = 0xf8 SizeofCanFilter = 0x8 SizeofTCPRepairOpt = 0x8 ) @@ -2672,6 +2675,7 @@ const ( BPF_PROG_TYPE_LSM = 0x1d BPF_PROG_TYPE_SK_LOOKUP = 0x1e BPF_PROG_TYPE_SYSCALL = 0x1f + BPF_PROG_TYPE_NETFILTER = 0x20 BPF_CGROUP_INET_INGRESS = 0x0 BPF_CGROUP_INET_EGRESS = 0x1 BPF_CGROUP_INET_SOCK_CREATE = 0x2 @@ -2716,6 +2720,11 @@ const ( BPF_PERF_EVENT = 0x29 BPF_TRACE_KPROBE_MULTI = 0x2a BPF_LSM_CGROUP = 0x2b + BPF_STRUCT_OPS = 0x2c + BPF_NETFILTER = 0x2d + BPF_TCX_INGRESS = 0x2e + BPF_TCX_EGRESS = 0x2f + BPF_TRACE_UPROBE_MULTI = 0x30 BPF_LINK_TYPE_UNSPEC = 0x0 BPF_LINK_TYPE_RAW_TRACEPOINT = 0x1 BPF_LINK_TYPE_TRACING = 0x2 @@ -2726,6 +2735,18 @@ const ( BPF_LINK_TYPE_PERF_EVENT = 0x7 BPF_LINK_TYPE_KPROBE_MULTI = 0x8 BPF_LINK_TYPE_STRUCT_OPS = 0x9 + BPF_LINK_TYPE_NETFILTER = 0xa + BPF_LINK_TYPE_TCX = 0xb + BPF_LINK_TYPE_UPROBE_MULTI = 0xc + BPF_PERF_EVENT_UNSPEC = 0x0 + BPF_PERF_EVENT_UPROBE = 0x1 + BPF_PERF_EVENT_URETPROBE = 0x2 + BPF_PERF_EVENT_KPROBE = 0x3 + BPF_PERF_EVENT_KRETPROBE = 0x4 + BPF_PERF_EVENT_TRACEPOINT = 0x5 + BPF_PERF_EVENT_EVENT = 0x6 + BPF_F_KPROBE_MULTI_RETURN = 0x1 + BPF_F_UPROBE_MULTI_RETURN = 0x1 BPF_ANY = 0x0 BPF_NOEXIST = 0x1 BPF_EXIST = 0x2 @@ -2743,6 +2764,8 @@ const ( BPF_F_MMAPABLE = 0x400 BPF_F_PRESERVE_ELEMS = 0x800 BPF_F_INNER_MAP = 0x1000 + BPF_F_LINK = 0x2000 + BPF_F_PATH_FD = 0x4000 BPF_STATS_RUN_TIME = 0x0 BPF_STACK_BUILD_ID_EMPTY = 0x0 BPF_STACK_BUILD_ID_VALID = 0x1 @@ -2763,6 +2786,7 @@ const ( BPF_F_ZERO_CSUM_TX = 0x2 BPF_F_DONT_FRAGMENT = 0x4 BPF_F_SEQ_NUMBER = 0x8 + BPF_F_NO_TUNNEL_KEY = 0x10 BPF_F_TUNINFO_FLAGS = 0x10 BPF_F_INDEX_MASK = 0xffffffff BPF_F_CURRENT_CPU = 0xffffffff @@ -2779,6 +2803,8 @@ const ( BPF_F_ADJ_ROOM_ENCAP_L4_UDP = 0x10 BPF_F_ADJ_ROOM_NO_CSUM_RESET = 0x20 BPF_F_ADJ_ROOM_ENCAP_L2_ETH = 0x40 + BPF_F_ADJ_ROOM_DECAP_L3_IPV4 = 0x80 + BPF_F_ADJ_ROOM_DECAP_L3_IPV6 = 0x100 BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 0x38 BPF_F_SYSCTL_BASE_NAME = 0x1 @@ -2867,6 +2893,8 @@ const ( BPF_DEVCG_DEV_CHAR = 0x2 BPF_FIB_LOOKUP_DIRECT = 0x1 BPF_FIB_LOOKUP_OUTPUT = 0x2 + BPF_FIB_LOOKUP_SKIP_NEIGH = 0x4 + BPF_FIB_LOOKUP_TBID = 0x8 BPF_FIB_LKUP_RET_SUCCESS = 0x0 BPF_FIB_LKUP_RET_BLACKHOLE = 0x1 BPF_FIB_LKUP_RET_UNREACHABLE = 0x2 @@ -2902,6 +2930,7 @@ const ( BPF_CORE_ENUMVAL_EXISTS = 0xa BPF_CORE_ENUMVAL_VALUE = 0xb BPF_CORE_TYPE_MATCHES = 0xc + BPF_F_TIMER_ABS = 0x1 ) const ( @@ -2980,6 +3009,12 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } +type LoopConfig struct { + Fd uint32 + Size uint32 + Info LoopInfo64 + _ [8]uint64 +} type TIPCSocketAddr struct { Ref uint32 @@ -3368,7 +3403,7 @@ const ( DEVLINK_PORT_FN_ATTR_STATE = 0x2 DEVLINK_PORT_FN_ATTR_OPSTATE = 0x3 DEVLINK_PORT_FN_ATTR_CAPS = 0x4 - DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x4 + DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x5 ) type FsverityDigest struct { @@ -4152,7 +4187,8 @@ const ( ) type LandlockRulesetAttr struct { - Access_fs uint64 + Access_fs uint64 + Access_net uint64 } type LandlockPathBeneathAttr struct { @@ -5103,7 +5139,7 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x1b + NL80211_FREQUENCY_ATTR_MAX = 0x1c NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc @@ -5516,7 +5552,7 @@ const ( NL80211_REGDOM_TYPE_CUSTOM_WORLD = 0x2 NL80211_REGDOM_TYPE_INTERSECTION = 0x3 NL80211_REGDOM_TYPE_WORLD = 0x1 - NL80211_REG_RULE_ATTR_MAX = 0x7 + NL80211_REG_RULE_ATTR_MAX = 0x8 NL80211_REKEY_DATA_AKM = 0x4 NL80211_REKEY_DATA_KCK = 0x2 NL80211_REKEY_DATA_KEK = 0x1 @@ -5883,3 +5919,15 @@ type SchedAttr struct { } const SizeofSchedAttr = 0x38 + +type Cachestat_t struct { + Cache uint64 + Dirty uint64 + Writeback uint64 + Evicted uint64 + Recently_evicted uint64 +} +type CachestatRange struct { + Off uint64 + Len uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 6d8acbc..438a30a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux -// +build 386,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 59293c6..adceca3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 40cfa38..eeaa00a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux -// +build arm,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 055bc42..6739aa9 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index f28affb..9920ef6 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux -// +build loong64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 9d71e7c..2923b79 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux -// +build mips,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index fd5ccd3..ce2750e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux -// +build mips64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 7704de7..3038811 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux -// +build mips64le,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index df00b87..efc6fed 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux -// +build mipsle,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 0942840..9a654b7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux -// +build ppc,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 0348743..40d358e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index bad0670..148c6ce 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 1b4c97c..72ba815 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux -// +build riscv64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index aa268d0..71e7655 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux -// +build s390x,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 444045b..4abbdb9 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux -// +build sparc64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go index 9bc4c8f..f22e794 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go index bb05f65..066a7d8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go index db40e3a..439548e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go index 1112115..16085d3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index 26eba23..afd13a3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index 5a54798..5d97f1f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index be58c4e..34871cd 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index 5233826..5911bce 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go index 605cfdb..e4f24f3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go index d6724c0..ca50a79 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go index ddfd27a..d7d7f79 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index 0400747..1416057 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && solaris -// +build amd64,solaris package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go index aec1efc..54f31be 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x // Hand edited based on ztypes_linux_s390x.go // TODO: auto-generate. diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go index a20ebea..ce2d713 100644 --- a/vendor/golang.org/x/sys/windows/aliases.go +++ b/vendor/golang.org/x/sys/windows/aliases.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && go1.9 -// +build windows,go1.9 package windows diff --git a/vendor/golang.org/x/sys/windows/empty.s b/vendor/golang.org/x/sys/windows/empty.s index fdbbbcd..ba64cac 100644 --- a/vendor/golang.org/x/sys/windows/empty.s +++ b/vendor/golang.org/x/sys/windows/empty.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.12 -// +build !go1.12 // This file is here to allow bodyless functions with go:linkname for Go 1.11 // and earlier (see https://golang.org/issue/23311). diff --git a/vendor/golang.org/x/sys/windows/env_windows.go b/vendor/golang.org/x/sys/windows/env_windows.go index b8ad192..d4577a4 100644 --- a/vendor/golang.org/x/sys/windows/env_windows.go +++ b/vendor/golang.org/x/sys/windows/env_windows.go @@ -37,14 +37,17 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) { return nil, err } defer DestroyEnvironmentBlock(block) - blockp := unsafe.Pointer(block) - for { - entry := UTF16PtrToString((*uint16)(blockp)) - if len(entry) == 0 { - break + size := unsafe.Sizeof(*block) + for *block != 0 { + // find NUL terminator + end := unsafe.Pointer(block) + for *(*uint16)(end) != 0 { + end = unsafe.Add(end, size) } - env = append(env, entry) - blockp = unsafe.Add(blockp, 2*(len(entry)+1)) + + entry := unsafe.Slice(block, (uintptr(end)-uintptr(unsafe.Pointer(block)))/size) + env = append(env, UTF16ToString(entry)) + block = (*uint16)(unsafe.Add(end, size)) } return env, nil } diff --git a/vendor/golang.org/x/sys/windows/eventlog.go b/vendor/golang.org/x/sys/windows/eventlog.go index 2cd6064..6c36695 100644 --- a/vendor/golang.org/x/sys/windows/eventlog.go +++ b/vendor/golang.org/x/sys/windows/eventlog.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/mksyscall.go b/vendor/golang.org/x/sys/windows/mksyscall.go index 8563f79..dbcdb09 100644 --- a/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/vendor/golang.org/x/sys/windows/mksyscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build generate -// +build generate package windows diff --git a/vendor/golang.org/x/sys/windows/race.go b/vendor/golang.org/x/sys/windows/race.go index 9196b08..0f1bdc3 100644 --- a/vendor/golang.org/x/sys/windows/race.go +++ b/vendor/golang.org/x/sys/windows/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && race -// +build windows,race package windows diff --git a/vendor/golang.org/x/sys/windows/race0.go b/vendor/golang.org/x/sys/windows/race0.go index 7bae481..0c78da7 100644 --- a/vendor/golang.org/x/sys/windows/race0.go +++ b/vendor/golang.org/x/sys/windows/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && !race -// +build windows,!race package windows diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index c44a1b9..a9dc630 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/str.go b/vendor/golang.org/x/sys/windows/str.go index 4fc0143..6a4f9ce 100644 --- a/vendor/golang.org/x/sys/windows/str.go +++ b/vendor/golang.org/x/sys/windows/str.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/syscall.go b/vendor/golang.org/x/sys/windows/syscall.go index 8732cdb..e85ed6b 100644 --- a/vendor/golang.org/x/sys/windows/syscall.go +++ b/vendor/golang.org/x/sys/windows/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows // Package windows contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 35cfc57..6395a03 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -125,8 +125,7 @@ func UTF16PtrToString(p *uint16) string { for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ { ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p)) } - - return string(utf16.Decode(unsafe.Slice(p, n))) + return UTF16ToString(unsafe.Slice(p, n)) } func Getpagesize() int { return 4096 } @@ -155,6 +154,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW //sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW //sys SetDefaultDllDirectories(directoryFlags uint32) (err error) +//sys AddDllDirectory(path *uint16) (cookie uintptr, err error) = kernel32.AddDllDirectory +//sys RemoveDllDirectory(cookie uintptr) (err error) = kernel32.RemoveDllDirectory //sys SetDllDirectory(path string) (err error) = kernel32.SetDllDirectoryW //sys GetVersion() (ver uint32, err error) //sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW @@ -192,6 +193,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW //sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW //sys SetEndOfFile(handle Handle) (err error) +//sys SetFileValidData(handle Handle, validDataLength int64) (err error) //sys GetSystemTimeAsFileTime(time *Filetime) //sys GetSystemTimePreciseAsFileTime(time *Filetime) //sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff] @@ -233,6 +235,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys getTickCount64() (ms uint64) = kernel32.GetTickCount64 +//sys GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) //sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) //sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW //sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW @@ -969,7 +972,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { if n > 0 { sl += int32(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index b88dc7c..359780f 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -1094,7 +1094,33 @@ const ( SOMAXCONN = 0x7fffffff - TCP_NODELAY = 1 + TCP_NODELAY = 1 + TCP_EXPEDITED_1122 = 2 + TCP_KEEPALIVE = 3 + TCP_MAXSEG = 4 + TCP_MAXRT = 5 + TCP_STDURG = 6 + TCP_NOURG = 7 + TCP_ATMARK = 8 + TCP_NOSYNRETRIES = 9 + TCP_TIMESTAMPS = 10 + TCP_OFFLOAD_PREFERENCE = 11 + TCP_CONGESTION_ALGORITHM = 12 + TCP_DELAY_FIN_ACK = 13 + TCP_MAXRTMS = 14 + TCP_FASTOPEN = 15 + TCP_KEEPCNT = 16 + TCP_KEEPIDLE = TCP_KEEPALIVE + TCP_KEEPINTVL = 17 + TCP_FAIL_CONNECT_ON_ICMP_ERROR = 18 + TCP_ICMP_ERROR_INFO = 19 + + UDP_NOCHECKSUM = 1 + UDP_SEND_MSG_SIZE = 2 + UDP_RECV_MAX_COALESCED_SIZE = 3 + UDP_CHECKSUM_COVERAGE = 20 + + UDP_COALESCED_INFO = 3 SHUT_RD = 0 SHUT_WR = 1 diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 8b1688d..e8791c8 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -184,6 +184,7 @@ var ( procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx") procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procAddDllDirectory = modkernel32.NewProc("AddDllDirectory") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") procCancelIo = modkernel32.NewProc("CancelIo") procCancelIoEx = modkernel32.NewProc("CancelIoEx") @@ -253,6 +254,7 @@ var ( procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetFileTime = modkernel32.NewProc("GetFileTime") procGetFileType = modkernel32.NewProc("GetFileType") procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") @@ -329,6 +331,7 @@ var ( procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory") procReleaseMutex = modkernel32.NewProc("ReleaseMutex") procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procRemoveDllDirectory = modkernel32.NewProc("RemoveDllDirectory") procResetEvent = modkernel32.NewProc("ResetEvent") procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole") procResumeThread = modkernel32.NewProc("ResumeThread") @@ -339,6 +342,7 @@ var ( procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories") procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW") procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") + procSetFileValidData = modkernel32.NewProc("SetFileValidData") procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") procSetErrorMode = modkernel32.NewProc("SetErrorMode") procSetEvent = modkernel32.NewProc("SetEvent") @@ -1604,6 +1608,15 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) { return } +func AddDllDirectory(path *uint16) (cookie uintptr, err error) { + r0, _, e1 := syscall.Syscall(procAddDllDirectory.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + cookie = uintptr(r0) + if cookie == 0 { + err = errnoErr(e1) + } + return +} + func AssignProcessToJobObject(job Handle, process Handle) (err error) { r1, _, e1 := syscall.Syscall(procAssignProcessToJobObject.Addr(), 2, uintptr(job), uintptr(process), 0) if r1 == 0 { @@ -2185,6 +2198,14 @@ func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, return } +func GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetFileType(filehandle Handle) (n uint32, err error) { r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) n = uint32(r0) @@ -2870,6 +2891,14 @@ func RemoveDirectory(path *uint16) (err error) { return } +func RemoveDllDirectory(cookie uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procRemoveDllDirectory.Addr(), 1, uintptr(cookie), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func ResetEvent(event Handle) (err error) { r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(event), 0, 0) if r1 == 0 { @@ -2960,6 +2989,14 @@ func SetEndOfFile(handle Handle) (err error) { return } +func SetFileValidData(handle Handle, validDataLength int64) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) if r1 == 0 { diff --git a/vendor/golang.org/x/term/term_unix.go b/vendor/golang.org/x/term/term_unix.go index 62c2b3f..1ad0ddf 100644 --- a/vendor/golang.org/x/term/term_unix.go +++ b/vendor/golang.org/x/term/term_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package term diff --git a/vendor/golang.org/x/term/term_unix_bsd.go b/vendor/golang.org/x/term/term_unix_bsd.go index 853b3d6..9dbf546 100644 --- a/vendor/golang.org/x/term/term_unix_bsd.go +++ b/vendor/golang.org/x/term/term_unix_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package term diff --git a/vendor/golang.org/x/term/term_unix_other.go b/vendor/golang.org/x/term/term_unix_other.go index 1e8955c..1b36de7 100644 --- a/vendor/golang.org/x/term/term_unix_other.go +++ b/vendor/golang.org/x/term/term_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || linux || solaris || zos -// +build aix linux solaris zos package term diff --git a/vendor/golang.org/x/term/term_unsupported.go b/vendor/golang.org/x/term/term_unsupported.go index f1df850..3c409e5 100644 --- a/vendor/golang.org/x/term/term_unsupported.go +++ b/vendor/golang.org/x/term/term_unsupported.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !zos && !windows && !solaris && !plan9 -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!zos,!windows,!solaris,!plan9 package term diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index 0bc7a7d..f960640 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -171,10 +171,15 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, ID: http2.SettingMaxFrameSize, Val: http2MaxFrameLen, }} - if config.MaxStreams != math.MaxUint32 { + // TODO(zhaoq): Have a better way to signal "no limit" because 0 is + // permitted in the HTTP2 spec. + maxStreams := config.MaxStreams + if maxStreams == 0 { + maxStreams = math.MaxUint32 + } else { isettings = append(isettings, http2.Setting{ ID: http2.SettingMaxConcurrentStreams, - Val: config.MaxStreams, + Val: maxStreams, }) } dynamicWindow := true @@ -253,7 +258,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, framer: framer, readerDone: make(chan struct{}), writerDone: make(chan struct{}), - maxStreams: config.MaxStreams, + maxStreams: maxStreams, inTapHandle: config.InTapHandle, fc: &trInFlow{limit: uint32(icwz)}, state: reachable, diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index b44c7e8..e076ec7 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -115,6 +115,12 @@ type serviceInfo struct { mdata interface{} } +type serverWorkerData struct { + st transport.ServerTransport + wg *sync.WaitGroup + stream *transport.Stream +} + // Server is a gRPC server to serve RPC requests. type Server struct { opts serverOptions @@ -139,7 +145,7 @@ type Server struct { channelzID *channelz.Identifier czData *channelzData - serverWorkerChannel chan func() + serverWorkerChannel chan *serverWorkerData } type serverOptions struct { @@ -172,7 +178,6 @@ type serverOptions struct { } var defaultServerOptions = serverOptions{ - maxConcurrentStreams: math.MaxUint32, maxReceiveMessageSize: defaultServerMaxReceiveMessageSize, maxSendMessageSize: defaultServerMaxSendMessageSize, connectionTimeout: 120 * time.Second, @@ -384,9 +389,6 @@ func MaxSendMsgSize(m int) ServerOption { // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number // of concurrent streams to each ServerTransport. func MaxConcurrentStreams(n uint32) ServerOption { - if n == 0 { - n = math.MaxUint32 - } return newFuncServerOption(func(o *serverOptions) { o.maxConcurrentStreams = n }) @@ -588,19 +590,24 @@ const serverWorkerResetThreshold = 1 << 16 // [1] https://github.com/golang/go/issues/18138 func (s *Server) serverWorker() { for completed := 0; completed < serverWorkerResetThreshold; completed++ { - f, ok := <-s.serverWorkerChannel + data, ok := <-s.serverWorkerChannel if !ok { return } - f() + s.handleSingleStream(data) } go s.serverWorker() } +func (s *Server) handleSingleStream(data *serverWorkerData) { + defer data.wg.Done() + s.handleStream(data.st, data.stream, s.traceInfo(data.st, data.stream)) +} + // initServerWorkers creates worker goroutines and a channel to process incoming // connections to reduce the time spent overall on runtime.morestack. func (s *Server) initServerWorkers() { - s.serverWorkerChannel = make(chan func()) + s.serverWorkerChannel = make(chan *serverWorkerData) for i := uint32(0); i < s.opts.numServerWorkers; i++ { go s.serverWorker() } @@ -959,26 +966,21 @@ func (s *Server) serveStreams(st transport.ServerTransport) { defer st.Close(errors.New("finished serving streams for the server transport")) var wg sync.WaitGroup - streamQuota := newHandlerQuota(s.opts.maxConcurrentStreams) st.HandleStreams(func(stream *transport.Stream) { wg.Add(1) - - streamQuota.acquire() - f := func() { - defer streamQuota.release() - defer wg.Done() - s.handleStream(st, stream, s.traceInfo(st, stream)) - } - if s.opts.numServerWorkers > 0 { + data := &serverWorkerData{st: st, wg: &wg, stream: stream} select { - case s.serverWorkerChannel <- f: + case s.serverWorkerChannel <- data: return default: // If all stream workers are busy, fallback to the default code path. } } - go f() + go func() { + defer wg.Done() + s.handleStream(st, stream, s.traceInfo(st, stream)) + }() }, func(ctx context.Context, method string) context.Context { if !EnableTracing { return ctx @@ -2073,32 +2075,3 @@ func validateSendCompressor(name, clientCompressors string) error { } return fmt.Errorf("client does not support compressor %q", name) } - -// atomicSemaphore implements a blocking, counting semaphore. acquire should be -// called synchronously; release may be called asynchronously. -type atomicSemaphore struct { - n int64 // accessed atomically - wait chan struct{} -} - -func (q *atomicSemaphore) acquire() { - if atomic.AddInt64(&q.n, -1) < 0 { - // We ran out of quota. Block until a release happens. - <-q.wait - } -} - -func (q *atomicSemaphore) release() { - // N.B. the "<= 0" check below should allow for this to work with multiple - // concurrent calls to acquire, but also note that with synchronous calls to - // acquire, as our system does, n will never be less than -1. There are - // fairness issues (queuing) to consider if this was to be generalized. - if atomic.AddInt64(&q.n, -1) <= 0 { - // An acquire was waiting on us. Unblock it. - q.wait <- struct{}{} - } -} - -func newHandlerQuota(n uint32) *atomicSemaphore { - return &atomicSemaphore{n: int64(n), wait: make(chan struct{}, 1)} -} diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 12a5a9d..353cfd5 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.57.1" +const Version = "1.57.0" diff --git a/vendor/modules.txt b/vendor/modules.txt index f59f3a1..c6e2516 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,4 +1,4 @@ -# capnproto.org/go/capnp/v3 v3.0.0-alpha-29 +# capnproto.org/go/capnp/v3 v3.0.0-alpha-29 => capnproto.org/go/capnp/v3 v3.0.0-alpha.29 ## explicit; go 1.19 capnproto.org/go/capnp/v3 capnproto.org/go/capnp/v3/encoding/text @@ -11,7 +11,7 @@ capnproto.org/go/capnp/v3/internal/str capnproto.org/go/capnp/v3/internal/strquote capnproto.org/go/capnp/v3/packed capnproto.org/go/capnp/v3/schemas -# github.com/anhoder/foxful-cli v0.1.4 +# github.com/anhoder/foxful-cli v0.3.3 ## explicit; go 1.20 github.com/anhoder/foxful-cli/model github.com/anhoder/foxful-cli/util @@ -53,34 +53,31 @@ github.com/charmbracelet/bubbles/cursor github.com/charmbracelet/bubbles/key github.com/charmbracelet/bubbles/runeutil github.com/charmbracelet/bubbles/textinput -# github.com/charmbracelet/bubbletea v0.24.2 => github.com/go-musicfox/bubbletea v0.24.1 -## explicit; go 1.17 +# github.com/charmbracelet/bubbletea v0.25.0 => github.com/go-musicfox/bubbletea v0.25.0-foxful +## explicit; go 1.18 github.com/charmbracelet/bubbletea # github.com/charmbracelet/lipgloss v0.8.0 ## explicit; go 1.17 github.com/charmbracelet/lipgloss -# github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 -## explicit; go 1.13 -github.com/containerd/console -# github.com/ebitengine/purego v0.4.0 +# github.com/ebitengine/oto/v3 v3.1.0 +## explicit; go 1.18 +github.com/ebitengine/oto/v3 +github.com/ebitengine/oto/v3/internal/mux +github.com/ebitengine/oto/v3/internal/oboe +# github.com/ebitengine/purego v0.7.0 ## explicit; go 1.18 github.com/ebitengine/purego -github.com/ebitengine/purego/internal/abi github.com/ebitengine/purego/internal/cgo github.com/ebitengine/purego/internal/fakecgo github.com/ebitengine/purego/internal/strings github.com/ebitengine/purego/objc -# github.com/faiface/beep v1.1.0 => github.com/go-musicfox/beep v1.2.4 -## explicit; go 1.14 -github.com/faiface/beep -github.com/faiface/beep/effects -github.com/faiface/beep/mp3 -github.com/faiface/beep/speaker -github.com/faiface/beep/vorbis +# github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f +## explicit; go 1.16 +github.com/erikgeiser/coninput # github.com/fogleman/ease v0.0.0-20170301025033-8da417bf1776 ## explicit github.com/fogleman/ease -# github.com/go-musicfox/notificator v0.1.0 +# github.com/go-musicfox/notificator v0.1.2 ## explicit; go 1.16 github.com/go-musicfox/notificator # github.com/godbus/dbus/v5 v5.1.0 @@ -99,22 +96,21 @@ github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/timestamp -# github.com/google/uuid v1.3.1 +# github.com/google/uuid v1.3.0 ## explicit github.com/google/uuid -# github.com/gookit/color v1.5.3 -## explicit; go 1.18 +# github.com/gookit/color v1.5.2 +## explicit; go 1.16 github.com/gookit/color # github.com/gookit/gcli/v2 v2.3.4 => github.com/anhoder/gcli/v2 v2.3.5 ## explicit; go 1.12 github.com/gookit/gcli/v2 github.com/gookit/gcli/v2/helper github.com/gookit/gcli/v2/progress -# github.com/gookit/goutil v0.6.10 +# github.com/gookit/goutil v0.6.7 ## explicit; go 1.18 github.com/gookit/goutil github.com/gookit/goutil/arrutil -github.com/gookit/goutil/basefn github.com/gookit/goutil/byteutil github.com/gookit/goutil/cliutil/cmdline github.com/gookit/goutil/comdef @@ -130,7 +126,6 @@ github.com/gookit/goutil/stdutil github.com/gookit/goutil/structs github.com/gookit/goutil/strutil github.com/gookit/goutil/strutil/textscan -github.com/gookit/goutil/strutil/textutil github.com/gookit/goutil/sysutil github.com/gookit/goutil/sysutil/cmdr github.com/gookit/goutil/timex @@ -138,6 +133,13 @@ github.com/gookit/goutil/timex ## explicit; go 1.18 github.com/gookit/ini/v2 github.com/gookit/ini/v2/parser +# github.com/gopxl/beep v1.4.0 => github.com/go-musicfox/beep v1.4.1 +## explicit; go 1.21 +github.com/gopxl/beep +github.com/gopxl/beep/effects +github.com/gopxl/beep/mp3 +github.com/gopxl/beep/speaker +github.com/gopxl/beep/vorbis # github.com/hajimehoshi/go-mp3 v0.3.4 => github.com/go-musicfox/go-mp3 v0.3.3 ## explicit; go 1.14 github.com/hajimehoshi/go-mp3 @@ -149,10 +151,6 @@ github.com/hajimehoshi/go-mp3/internal/huffman github.com/hajimehoshi/go-mp3/internal/imdct github.com/hajimehoshi/go-mp3/internal/maindata github.com/hajimehoshi/go-mp3/internal/sideinfo -# github.com/hajimehoshi/oto v1.0.1 => github.com/go-musicfox/oto v1.0.3 -## explicit; go 1.13 -github.com/hajimehoshi/oto -github.com/hajimehoshi/oto/internal/mux # github.com/jfreymuth/oggvorbis v1.0.5 ## explicit; go 1.15 github.com/jfreymuth/oggvorbis @@ -201,9 +199,12 @@ github.com/pkg/errors # github.com/raitonoberu/lyricsapi v0.0.0-20230113141433-eded40b42d7c ## explicit; go 1.17 github.com/raitonoberu/lyricsapi/lyrics -# github.com/rivo/uniseg v0.4.4 +# github.com/rivo/uniseg v0.4.6 ## explicit; go 1.18 github.com/rivo/uniseg +# github.com/robotn/gohook v0.41.0 +## explicit; go 1.17 +github.com/robotn/gohook # github.com/rs/cors v1.9.0 ## explicit; go 1.13 github.com/rs/cors @@ -216,6 +217,9 @@ github.com/shkh/lastfm-go # github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 ## explicit github.com/skratchdot/open-golang/open +# github.com/vcaesar/keycode v0.10.1 +## explicit; go 1.17 +github.com/vcaesar/keycode # github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e ## explicit; go 1.19 github.com/xo/terminfo @@ -225,42 +229,14 @@ github.com/zmb3/spotify/v2 # go.etcd.io/bbolt v1.3.7 ## explicit; go 1.17 go.etcd.io/bbolt -# golang.org/x/crypto v0.14.0 +# golang.org/x/crypto v0.12.0 ## explicit; go 1.17 golang.org/x/crypto/pbkdf2 golang.org/x/crypto/ssh/terminal -# golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df -## explicit; go 1.20 -# golang.org/x/exp/shiny v0.0.0-20230522175609-2e198f4a06a1 -## explicit; go 1.18 -golang.org/x/exp/shiny/driver/gldriver -golang.org/x/exp/shiny/driver/internal/drawer -golang.org/x/exp/shiny/driver/internal/errscreen -golang.org/x/exp/shiny/driver/internal/event -golang.org/x/exp/shiny/driver/internal/lifecycler -golang.org/x/exp/shiny/driver/internal/win32 -golang.org/x/exp/shiny/driver/internal/x11key -golang.org/x/exp/shiny/screen -# golang.org/x/image v0.10.0 -## explicit; go 1.12 -golang.org/x/image/math/f64 -# golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda -## explicit; go 1.17 -golang.org/x/mobile/app -golang.org/x/mobile/app/internal/callfn -golang.org/x/mobile/event/key -golang.org/x/mobile/event/lifecycle -golang.org/x/mobile/event/mouse -golang.org/x/mobile/event/paint -golang.org/x/mobile/event/size -golang.org/x/mobile/event/touch -golang.org/x/mobile/geom -golang.org/x/mobile/gl -golang.org/x/mobile/internal/mobileinit -# golang.org/x/mod v0.12.0 +# golang.org/x/mod v0.8.0 ## explicit; go 1.17 golang.org/x/mod/semver -# golang.org/x/net v0.17.0 +# golang.org/x/net v0.14.0 ## explicit; go 1.17 golang.org/x/net/context golang.org/x/net/http/httpguts @@ -273,17 +249,17 @@ golang.org/x/net/trace ## explicit; go 1.17 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sync v0.3.0 -## explicit; go 1.17 +# golang.org/x/sync v0.6.0 +## explicit; go 1.18 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.13.0 -## explicit; go 1.17 +# golang.org/x/sys v0.17.0 +## explicit; go 1.18 golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.13.0 -## explicit; go 1.17 +# golang.org/x/term v0.17.0 +## explicit; go 1.18 golang.org/x/term # golang.org/x/text v0.13.0 ## explicit; go 1.17 @@ -305,10 +281,10 @@ google.golang.org/appengine/internal/log google.golang.org/appengine/internal/remote_api google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/urlfetch -# google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d +# google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 ## explicit; go 1.19 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.57.1 +# google.golang.org/grpc v1.57.0 ## explicit; go 1.17 google.golang.org/grpc google.golang.org/grpc/attributes @@ -392,9 +368,7 @@ google.golang.org/protobuf/types/descriptorpb google.golang.org/protobuf/types/known/anypb google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/timestamppb -# zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae +# zenhack.net/go/util v0.0.0-20230607025951-8b02fee814ae => github.com/zenhack/go-util v0.0.0-20230607025951-8b02fee814ae ## explicit; go 1.19 zenhack.net/go/util/sync/mutex -# github.com/cnsilvan/UnblockNeteaseMusic v0.0.0-20230310083816-92b59c95a366 => github.com/go-musicfox/UnblockNeteaseMusic v0.1.2 -# github.com/frolovo22/tag v0.0.2 => github.com/go-musicfox/tag v1.0.2 # github.com/shkh/lastfm-go => github.com/go-musicfox/lastfm-go v0.0.2