├── .deepsource.toml
├── .github
├── FUNDING.yml
└── workflows
│ ├── codeql-analysis.yml
│ └── workflow.yml
├── .gitignore
├── .goreleaser.yml
├── LICENSE
├── README.MD
├── distributor.go
├── go.mod
├── go.sum
├── gui.go
├── images
├── demo.png
├── demo2.jpg
└── logo.svg
├── index.html
├── macos.sh
├── main.go
├── main.js
├── osc.min.js
├── osc.min.js.map
├── procmessage.go
└── winres
└── winres.json
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "javascript"
5 | enabled = true
6 |
7 | [[analyzers]]
8 | name = "go"
9 | enabled = true
10 |
11 | [analyzers.meta]
12 | import_root = "github.com/chabad360/resolume-timecode"
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [ chabad360 ]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: [ 'https://cash.app/$chabad360' ]
13 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ master ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ master ]
20 | schedule:
21 | - cron: '32 4 * * 1'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'go', 'javascript' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v2
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v1
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
52 |
53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54 | # If this step fails, then you should remove it and run the build manually (see below)
55 | - name: Autobuild
56 | uses: github/codeql-action/autobuild@v1
57 |
58 | # ℹ️ Command-line programs to run using the OS shell.
59 | # 📚 https://git.io/JvXDl
60 |
61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62 | # and modify them (or add more) to build your code if your project
63 | # uses a compiled language
64 |
65 | #- run: |
66 | # make bootstrap
67 | # make release
68 |
69 | - name: Perform CodeQL Analysis
70 | uses: github/codeql-action/analyze@v1
71 |
--------------------------------------------------------------------------------
/.github/workflows/workflow.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | goreleaser:
10 | runs-on: macos-11
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 |
17 | - name: Set up Go
18 | uses: actions/setup-go@v2
19 | with:
20 | go-version: 1.17.3
21 |
22 | - name: Install Packages
23 | run: brew install mingw-w64 upx librsvg
24 |
25 | - name: Cache
26 | uses: actions/cache@v2.1.3
27 | with:
28 | path: |
29 | ~/go
30 | ~/.cache/go-build
31 | ~/Library/Caches/go-build
32 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-${{ github.sha }}
33 | restore-keys: |
34 | ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-
35 | ${{ runner.os }}-go-
36 |
37 | - name: Run GoReleaser
38 | uses: goreleaser/goreleaser-action@v2
39 | with:
40 | version: latest
41 | args: release --rm-dist
42 | env:
43 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44 |
45 | - name: VirusTotal Scan
46 | uses: crazy-max/ghaction-virustotal@v2
47 | with:
48 | vt_api_key: ${{ secrets.VT_API_KEY }}
49 | files: |
50 | dist/windows_windows_amd64/resolume-timecode.exe
51 | dist/darwin_darwin_amd64/resolume-timecode
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .idea/
3 |
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | project_name: resolume-timecode
2 | before:
3 | hooks:
4 | - go get github.com/tc-hib/go-winres@latest
5 | - go mod download
6 | - bash -c "rsvg-convert -h 256 images/logo.svg > winres/icon.png"
7 | - bash -c "rsvg-convert -h 32 images/logo.svg > images/favicon.png"
8 | - bash -c "rsvg-convert -h 256 images/logo.svg > images/logo.png"
9 | - go-winres make --product-version=git-tag --file-version=git-tag
10 | builds:
11 | - id: darwin
12 | goos:
13 | - darwin
14 | goarch:
15 | - amd64
16 | env:
17 | - CGO_ENABLED=1
18 | flags:
19 | - -mod=readonly
20 | - -trimpath
21 | ldflags:
22 | - -s -w
23 | - -X main.version={{.Version}}
24 | - -X main.Date={{.CommitDate}}
25 | mod_timestamp: '{{ .CommitTimestamp }}'
26 | hooks:
27 | post:
28 | - upx {{ .Path }}
29 | - sh macos.sh resolume-timecode images/logo.svg "me.chabad360.resolume-timecode" {{ .Major }} {{ .Minor }}
30 | - cp {{ .Path }} resolume-timecode.app/Contents/MacOS/
31 | - id: windows
32 | goos:
33 | - windows
34 | goarch:
35 | - amd64
36 | env:
37 | - CGO_ENABLED=1
38 | - CC=x86_64-w64-mingw32-gcc
39 | - CXX=x86_64-w64-mingw32-g++
40 | flags:
41 | - -mod=readonly
42 | - -trimpath
43 | ldflags:
44 | - -s -w
45 | - -X main.version={{.Version}}
46 | - -X main.Date={{.CommitDate}}
47 | - -H=windowsgui
48 | mod_timestamp: '{{ .CommitTimestamp }}'
49 | hooks:
50 | post: upx {{ .Path }}
51 | checksum:
52 | name_template: 'checksums.txt'
53 | changelog:
54 | sort: asc
55 | filters:
56 | exclude:
57 | - '^chore:'
58 | - '^ci:'
59 | - '^docs?:'
60 | - '^tests?:'
61 | release:
62 | github:
63 | owner: chabad360
64 | name: resolume-timecode
65 | draft: true
66 | prerelease: auto
67 | archives:
68 | - id: darwin
69 | builds:
70 | - darwin
71 | format: zip
72 | wrap_in_directory: true
73 | replacements:
74 | darwin: macOS
75 | files:
76 | - LICENSE
77 | - README.MD
78 | - resolume-timecode.app
79 | - id: windows
80 | builds:
81 | - windows
82 | format: zip
83 | wrap_in_directory: true
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Resolume-Timecode Displays time remaining on the chosen clip in Resolume.
2 | Copyright (C) 2021 Mendel Greenberg (chabad360)
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 |
2 |

3 |
Resolume Timecode Monitor
4 |
View the time left for a playing clip on multiple devices.
5 |
6 |
7 | |
|
|
8 | |:-----------------------------------------------------:|:-------------------------------------------------------:|
9 | | _The client interface._ | _The server end of things._ |
10 |
11 | ## How to use
12 |
13 | 1. Download the [latest release](https://github.com/chabad360/resolume-timecode/releases)
14 | 2. Open the app and verify that all the information in there is set correctly.
15 | 3. Click _Start Server_
16 | 4. Open your web browser to the location specified by the application.
17 | 5. Start playing a clip in Resolume.
18 | 6. Profit.
19 |
20 | > Note: The precision should be within a few hundred milliseconds (usually 50ms), if it feels off double check that the clip length
21 | (in the status bar on the bottom) is correct. If it isn't, just click the reset button.
22 |
23 | ### How to set the `Path` field
24 |
25 | | Clip to use | Example path |
26 | |:---------------|:--------------------------------|
27 | | Selected Clip | `/composition/selectedclip` |
28 | | Specific Clip | `/composition/layers/1/clips/1` |
29 | | Selected Layer | `/composition/selectedlayer` |
30 | | Specific Layer | `/composition/layers/1` |
31 |
32 | > Note: using a layer will cause the layer's name to be shown on the client instead of the clip name
33 | > (I'm not sure if there is a way to fix that).
34 |
35 | ## Motivation
36 |
37 | When using Resolume for events where longer clips were being played, I found it annoying that the only way to find out
38 | the remaining time was to ask the guy in front of the laptop. So I decided to fix that.
39 |
40 | ## How it works
41 |
42 | Resolume outputs the position of the clip head through OSC, by calculating how much time it took between the one message
43 | and the previous one, it's possible to calculate how long the clip is, and therefore how much time is left.
44 | Due to certain inconsistencies in the way this information is outputted, it's not as simple as it sounds.
45 |
46 | For the exact algorithm, check [procmessage.go](https://github.com/chabad360/resolume-timecode/blob/master/procmessage.go)
47 | (specifically, [`procPos()`](https://github.com/chabad360/resolume-timecode/blob/master/procmessage.go#L97)).
48 |
49 | Anyway, because we're running in a browser, we can't actually interact with OSC (as it works over UDP),
50 | so this application also acts a proxy, running the algorithm on the messages and sending the timecode to the client.
51 |
52 | ## Known Issues
53 |
54 | - Uses around 60-70mb of RAM. Sorry, can't do much about that, at least it's better than an electron app.
55 |
56 | ## Building
57 |
58 | Because this is based on [fyne](https://fyne.io) it requires the use of _cgo_, so make sure you have a C compiler installed on your system.
59 |
60 | Just clone the repo and run `go build github.com/chabad360/resolume-timecode`.
61 |
--------------------------------------------------------------------------------
/distributor.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/chabad360/go-osc/osc"
5 | "sync"
6 | )
7 |
8 | type Distributor struct {
9 | l map[string]chan []byte
10 | m sync.RWMutex
11 | b *osc.Bundle
12 | bM sync.Mutex
13 | }
14 |
15 | func (d *Distributor) Listen(key string) <-chan []byte {
16 | ch := make(chan []byte)
17 | d.m.Lock()
18 |
19 | if och, ok := d.l[key]; ok {
20 | close(och)
21 | }
22 |
23 | d.l[key] = ch
24 | d.m.Unlock()
25 | return ch
26 | }
27 |
28 | func (d *Distributor) Close(key string) {
29 | d.m.Lock()
30 |
31 | if och, ok := d.l[key]; ok {
32 | close(och)
33 | }
34 |
35 | delete(d.l, key)
36 | d.m.Unlock()
37 | }
38 |
39 | func (d *Distributor) Publish(m *osc.Message) {
40 | d.bM.Lock()
41 |
42 | if d.b == nil {
43 | d.b = &osc.Bundle{Timetag: osc.NewImmediateTimetag()}
44 | }
45 |
46 | d.b.Elements = append(d.b.Elements, m)
47 |
48 | d.bM.Unlock()
49 | }
50 |
51 | func (d *Distributor) Send() {
52 | d.bM.Lock()
53 |
54 | b, err := d.b.MarshalBinary()
55 | if err != nil {
56 | panic(err)
57 | }
58 |
59 | d.b = nil
60 |
61 | d.publish(b)
62 | d.bM.Unlock()
63 | }
64 |
65 | func (d *Distributor) publish(v []byte) {
66 | d.m.RLock()
67 |
68 | for _, ch := range d.l {
69 | select {
70 | case ch <- v:
71 | default:
72 | }
73 | }
74 | d.m.RUnlock()
75 | }
76 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/chabad360/resolume-timecode
2 |
3 | go 1.17
4 |
5 | require (
6 | fyne.io/fyne/v2 v2.1.4
7 | github.com/chabad360/go-osc v0.0.0-20220217020417-1229c4fc60a5
8 | nhooyr.io/websocket v1.8.7
9 | )
10 |
11 | require (
12 | fyne.io/systray v1.9.1-0.20220318224641-d5779bfb17d1 // indirect
13 | github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 // indirect
14 | github.com/davecgh/go-spew v1.1.1 // indirect
15 | github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect
16 | github.com/fsnotify/fsnotify v1.5.1 // indirect
17 | github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect
18 | github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 // indirect
19 | github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
20 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec // indirect
21 | github.com/godbus/dbus/v5 v5.1.0 // indirect
22 | github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect
23 | github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60 // indirect
24 | github.com/klauspost/compress v1.13.6 // indirect
25 | github.com/pmezard/go-difflib v1.0.0 // indirect
26 | github.com/srwiley/oksvg v0.0.0-20211104221756-aeb4ca2c1505 // indirect
27 | github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780 // indirect
28 | github.com/stretchr/testify v1.7.0 // indirect
29 | github.com/yuin/goldmark v1.4.4 // indirect
30 | golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
31 | golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee // indirect
32 | golang.org/x/net v0.0.0-20211116231205-47ca1ff31462 // indirect
33 | golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c // indirect
34 | golang.org/x/text v0.3.7 // indirect
35 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
36 | honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect
37 | )
38 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
16 | cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
17 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
18 | cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
19 | cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
20 | cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
21 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
22 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
23 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
24 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
25 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
26 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
27 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
28 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
29 | cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
30 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
31 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
32 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
33 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
34 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
35 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
36 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
37 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
38 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
39 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
40 | fyne.io/systray v1.9.1-0.20220318224641-d5779bfb17d1 h1:+WSQpU5D3NIpeWKzbIn0D7+OtVbOz7A2e92ezFWacmc=
41 | fyne.io/systray v1.9.1-0.20220318224641-d5779bfb17d1/go.mod h1:N4ZU0i34X+n8soFRlBNkmJTunw9wD+9jIP19fSZpjSI=
42 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
43 | github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
44 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
45 | github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA=
46 | github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
47 | github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
48 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
49 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
50 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
51 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
52 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
53 | github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
54 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
55 | github.com/chabad360/go-osc v0.0.0-20220217020417-1229c4fc60a5 h1:TflojXcP1trvcO79pbZfZGqBYhNnSC9hC4saFFhWBzc=
56 | github.com/chabad360/go-osc v0.0.0-20220217020417-1229c4fc60a5/go.mod h1:SxhoJ/QyHpv+WPTqoLtIhjKZMIy0x3QQRdwQ6Ug3nk4=
57 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
58 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
59 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
60 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
61 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
62 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
63 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
64 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
65 | github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
66 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
67 | github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
68 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
69 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
70 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
71 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
72 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
73 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
74 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
75 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
76 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
77 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
78 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
79 | github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA=
80 | github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUvMTGHnXf/6OExw/Dz2ivDj48nVg7Lg8=
81 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
82 | github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
83 | github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
84 | github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJytaD+SsXkPU0asQ+guQEIg1BJGX4=
85 | github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg=
86 | github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 h1:+31CdF/okdokeFNoy9L/2PccG3JFidQT3ev64/r4pYU=
87 | github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E=
88 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
89 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
90 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
91 | github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
92 | github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
93 | github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk=
94 | github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
95 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
96 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
97 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
98 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
99 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec h1:3FLiRYO6PlQFDpUU7OEFlWgjGD1jnBIVSJ5SYRWk+9c=
100 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
101 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
102 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
103 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
104 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
105 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
106 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
107 | github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
108 | github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
109 | github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
110 | github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
111 | github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
112 | github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
113 | github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
114 | github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
115 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
116 | github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
117 | github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
118 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
119 | github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
120 | github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
121 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
122 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
123 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
124 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
125 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
126 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
127 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
128 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
129 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
130 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
131 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
132 | github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
133 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
134 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
135 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
136 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
137 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
138 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
139 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
140 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
141 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
142 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
143 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
144 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
145 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
146 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
147 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
148 | github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
149 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
150 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
151 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
152 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
153 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
154 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
155 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
156 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
157 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
158 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
159 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
160 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
161 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
162 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
163 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
164 | github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
165 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
166 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
167 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
168 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
169 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
170 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
171 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
172 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
173 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
174 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
175 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
176 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
177 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
178 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
179 | github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
180 | github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
181 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
182 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
183 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
184 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
185 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
186 | github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60 h1:btMZK5oA0NpSAOOE7zRfq2UEuPC9apJ2UBackURyaTU=
187 | github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60/go.mod h1:cz9oNYuRUWGdHmLF2IodMLkAhcPtXeULvcBNagUrxTI=
188 | github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
189 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
190 | github.com/goxjs/gl v0.0.0-20210104184919-e3fafc6f8f2a/go.mod h1:dy/f2gjY09hwVfIyATps4G2ai7/hLwLkc5TrPqONuXY=
191 | github.com/goxjs/glfw v0.0.0-20191126052801-d2efb5f20838/go.mod h1:oS8P8gVOT4ywTcjV6wZlOU4GuVFQ8F5328KY3MJ79CY=
192 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
193 | github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
194 | github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
195 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
196 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
197 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
198 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
199 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
200 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
201 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
202 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
203 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
204 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
205 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
206 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
207 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
208 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
209 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
210 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
211 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
212 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
213 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
214 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
215 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
216 | github.com/jackmordaunt/icns/v2 v2.1.3/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI=
217 | github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
218 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
219 | github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
220 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
221 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
222 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
223 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
224 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
225 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
226 | github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
227 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
228 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
229 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
230 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
231 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
232 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
233 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
234 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
235 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
236 | github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
237 | github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
238 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
239 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
240 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
241 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
242 | github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
243 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
244 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
245 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
246 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
247 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
248 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
249 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
250 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
251 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
252 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
253 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
254 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
255 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
256 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
257 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
258 | github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
259 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
260 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
261 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
262 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
263 | github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
264 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
265 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
266 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
267 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
268 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
269 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
270 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
271 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
272 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
273 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
274 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
275 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
276 | github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
277 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
278 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
279 | github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
280 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
281 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
282 | github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
283 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
284 | github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
285 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
286 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
287 | github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
288 | github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
289 | github.com/srwiley/oksvg v0.0.0-20211104221756-aeb4ca2c1505 h1:fWb9FJAdmiORr+NEeaadjEXp6C2qGAjdd7icfppTskE=
290 | github.com/srwiley/oksvg v0.0.0-20211104221756-aeb4ca2c1505/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
291 | github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
292 | github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780 h1:oDMiXaTMyBEuZMU53atpxqYsSB3U1CHkeAu2zr6wTeY=
293 | github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
294 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
295 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
296 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
297 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
298 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
299 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
300 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
301 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
302 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
303 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
304 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
305 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
306 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
307 | github.com/urfave/cli/v2 v2.4.0/go.mod h1:NX9W0zmTvedE5oDoOMs2RTC8RvdK98NTYZE5LbaEYPg=
308 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
309 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
310 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
311 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
312 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
313 | github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
314 | github.com/yuin/goldmark v1.4.4 h1:zNWRjYUW32G9KirMXYHQHVNFkXvMI7LpgNW2AgYAoIs=
315 | github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
316 | go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
317 | go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
318 | go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
319 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
320 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
321 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
322 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
323 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
324 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
325 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
326 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
327 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
328 | go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
329 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
330 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
331 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
332 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
333 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
334 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
335 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
336 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
337 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
338 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
339 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
340 | golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
341 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
342 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
343 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
344 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
345 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
346 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
347 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
348 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
349 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
350 | golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
351 | golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
352 | golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
353 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
354 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
355 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
356 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
357 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
358 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
359 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
360 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
361 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
362 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
363 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
364 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
365 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
366 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
367 | golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee h1:/tShaw8UTf0XzI8DOZwQHzC7d6Vi3EtrBnftiZ4vAvU=
368 | golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
369 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
370 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
371 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
372 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
373 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
374 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
375 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
376 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
377 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
378 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
379 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
380 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
381 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
382 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
383 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
384 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
385 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
386 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
387 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
388 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
389 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
390 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
391 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
392 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
393 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
394 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
395 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
396 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
397 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
398 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
399 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
400 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
401 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
402 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
403 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
404 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
405 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
406 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
407 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
408 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
409 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
410 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
411 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
412 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
413 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
414 | golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
415 | golang.org/x/net v0.0.0-20211116231205-47ca1ff31462 h1:2vmJlzGKvQ7e/X9XT0XydeWDxmqx8DnegiIMRT+5ssI=
416 | golang.org/x/net v0.0.0-20211116231205-47ca1ff31462/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
417 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
418 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
419 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
420 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
421 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
422 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
423 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
424 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
425 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
426 | golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
427 | golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
428 | golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
429 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
430 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
431 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
432 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
433 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
434 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
435 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
436 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
437 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
438 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
439 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
440 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
441 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
442 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
443 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
444 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
445 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
446 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
447 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
448 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
449 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
450 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
451 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
452 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
453 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
454 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
455 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
456 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
457 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
458 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
459 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
460 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
461 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
462 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
463 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
464 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
465 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
466 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
467 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
468 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
469 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
470 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
471 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
472 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
473 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
474 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
475 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
476 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
477 | golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
478 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
479 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
480 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
481 | golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
482 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
483 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
484 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
485 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
486 | golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
487 | golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c h1:DHcbWVXeY+0Y8HHKR+rbLwnoh2F4tNCY7rTiHJ30RmA=
488 | golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
489 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
490 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
491 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
492 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
493 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
494 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
495 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
496 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
497 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
498 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
499 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
500 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
501 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
502 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
503 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
504 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
505 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
506 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
507 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
508 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
509 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
510 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
511 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
512 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
513 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
514 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
515 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
516 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
517 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
518 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
519 | golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
520 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
521 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
522 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
523 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
524 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
525 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
526 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
527 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
528 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
529 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
530 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
531 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
532 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
533 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
534 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
535 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
536 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
537 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
538 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
539 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
540 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
541 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
542 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
543 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
544 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
545 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
546 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
547 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
548 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
549 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
550 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
551 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
552 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
553 | golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
554 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
555 | golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
556 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
557 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
558 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
559 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
560 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
561 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
562 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
563 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
564 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
565 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
566 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
567 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
568 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
569 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
570 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
571 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
572 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
573 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
574 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
575 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
576 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
577 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
578 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
579 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
580 | google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
581 | google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
582 | google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
583 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
584 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
585 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
586 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
587 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
588 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
589 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
590 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
591 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
592 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
593 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
594 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
595 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
596 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
597 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
598 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
599 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
600 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
601 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
602 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
603 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
604 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
605 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
606 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
607 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
608 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
609 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
610 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
611 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
612 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
613 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
614 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
615 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
616 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
617 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
618 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
619 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
620 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
621 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
622 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
623 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
624 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
625 | google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
626 | google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
627 | google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
628 | google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
629 | google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
630 | google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
631 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
632 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
633 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
634 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
635 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
636 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
637 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
638 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
639 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
640 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
641 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
642 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
643 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
644 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
645 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
646 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
647 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
648 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
649 | google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
650 | google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
651 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
652 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
653 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
654 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
655 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
656 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
657 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
658 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
659 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
660 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
661 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
662 | google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
663 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
664 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
665 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
666 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
667 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
668 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
669 | gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
670 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
671 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
672 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
673 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
674 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
675 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
676 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
677 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
678 | honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 h1:oomkgU6VaQDsV6qZby2uz1Lap0eXmku8+2em3A/l700=
679 | honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2/go.mod h1:sUMDUKNB2ZcVjt92UnLy3cdGs+wDAcrPdV3JP6sVgA4=
680 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
681 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
682 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
683 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
684 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
685 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
686 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
687 | nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
688 | nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
689 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
690 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
691 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
692 |
--------------------------------------------------------------------------------
/gui.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | _ "embed"
5 | "errors"
6 | "fmt"
7 | "fyne.io/fyne/v2"
8 | "fyne.io/fyne/v2/container"
9 | "fyne.io/fyne/v2/data/binding"
10 | "fyne.io/fyne/v2/data/validation"
11 | "fyne.io/fyne/v2/dialog"
12 | "fyne.io/fyne/v2/theme"
13 | "fyne.io/fyne/v2/widget"
14 | "github.com/chabad360/go-osc/osc"
15 | "html/template"
16 | "runtime"
17 | )
18 |
19 | var (
20 | //go:embed images/logo.png
21 | logo []byte
22 | logoResource = fyne.NewStaticResource("logo", logo)
23 | clipLengthBinding = binding.NewString()
24 | timeLeftBinding = binding.NewString()
25 | clipNameBinding = binding.NewString()
26 | )
27 |
28 | var _ fyne.Widget = (*ValidateTabs)(nil)
29 | var _ fyne.Validatable = (*ValidateTabs)(nil)
30 |
31 | type ValidateTabs struct {
32 | *container.AppTabs
33 | f func(error)
34 | err error
35 | }
36 |
37 | func (v *ValidateTabs) Validate() error {
38 | for _, item := range v.Items {
39 | if w, ok := item.Content.(fyne.Validatable); ok {
40 | if err := w.Validate(); err != nil {
41 | //v.setValidationError(err)
42 | return err
43 | }
44 | }
45 | }
46 | return nil
47 | }
48 |
49 | func (v *ValidateTabs) SetValidationError(err error) {
50 | if err == nil && v.err == nil {
51 | return
52 | }
53 |
54 | if (err == nil && v.err != nil) || (v.err == nil && err != nil) ||
55 | err.Error() != v.err.Error() {
56 | if err == nil {
57 | for _, item := range v.Items {
58 | if w, ok := item.Content.(fyne.Validatable); ok {
59 | w.SetOnValidationChanged(func(_ error) {}) // prevent recursion
60 | e := w.Validate()
61 | w.SetOnValidationChanged(func(err error) {
62 | if err != nil {
63 | item.Icon = theme.ErrorIcon()
64 | } else {
65 | item.Icon = theme.ConfirmIcon()
66 | }
67 | v.SetValidationError(err)
68 | })
69 | if e != nil {
70 | err = e
71 | break
72 | }
73 | }
74 | }
75 | }
76 | v.err = err
77 |
78 | if v.f != nil {
79 | v.f(err)
80 | }
81 | }
82 | }
83 |
84 | func (v *ValidateTabs) SetOnValidationChanged(f func(error)) {
85 | if f != nil {
86 | v.f = f
87 | }
88 | }
89 |
90 | func NewValidateTabs(tabs ...*container.TabItem) *ValidateTabs {
91 | v := &ValidateTabs{AppTabs: container.NewAppTabs(tabs...), err: errors.New("validation failed")}
92 | for _, item := range v.Items {
93 | if w, ok := item.Content.(fyne.Validatable); ok {
94 | w.SetOnValidationChanged(func(err error) {
95 | if err != nil {
96 | item.Icon = theme.ErrorIcon()
97 | } else {
98 | item.Icon = theme.ConfirmIcon()
99 | }
100 | v.SetValidationError(err)
101 | })
102 | }
103 | }
104 | return v
105 | }
106 | func gui() {
107 | w := a.NewWindow("Timecode Monitor Server")
108 | w.SetIcon(logoResource)
109 |
110 | infoLabel := widget.NewRichTextWithText("Server Stopped")
111 | infoLabel.Wrapping = fyne.TextWrapWord
112 |
113 | timeLeftLabel := widget.NewLabelWithData(timeLeftBinding)
114 | clipLengthLabel := widget.NewLabelWithData(clipLengthBinding)
115 | clipNameLabel := widget.NewLabelWithData(clipNameBinding)
116 | clipNameLabel.Wrapping = fyne.TextTruncate
117 |
118 | resetButton := widget.NewButton("Reset Timecode", reset)
119 | resetButton.Hide()
120 |
121 | path := widget.NewSelectEntry([]string{"", "/composition/selectedclip", "/composition/layers/1/clips/1", "/composition/selectedlayer", "/composition/layers/1"})
122 | path.SetText(clipPath)
123 | path.SetPlaceHolder("Path to clip (/composition/...)")
124 | path.Validator = validation.NewRegexp(`^[^\?\,\[\]\{\}\#\s]+$`, "not a valid OSC path")
125 |
126 | oscOutput := widget.NewEntry()
127 | oscOutput.SetText(OSCOutPort)
128 | oscOutput.Validator = validation.NewRegexp(`^[0-9]+$`, "not a valid port")
129 |
130 | oscInput := widget.NewEntry()
131 | oscInput.SetText(OSCPort)
132 | oscInput.Validator = validation.NewRegexp(`^[0-9]+$`, "not a valid port")
133 |
134 | oscAddr := widget.NewEntry()
135 | oscAddr.SetText(OSCAddr)
136 | oscAddr.Validator = validation.NewRegexp(`^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, "not a valid IP address")
137 |
138 | httpPortField := widget.NewEntry()
139 | httpPortField.SetText(httpPort)
140 | httpPortField.Validator = validation.NewRegexp(`^[0-9]+$`, "not a valid port")
141 |
142 | messageField := widget.NewEntry()
143 | messageField.SetText(clientMessage)
144 |
145 | invertField := widget.NewCheck("", nil)
146 | invertField.SetChecked(!clipInvert)
147 |
148 | form := &widget.Form{
149 | Items: []*widget.FormItem{
150 | {Widget: NewValidateTabs(container.NewTabItemWithIcon("Client Settings", theme.ConfirmIcon(), &widget.Form{
151 | Items: []*widget.FormItem{
152 | {Text: "Path", Widget: path, HintText: "OSC Path for clip to listen to"},
153 | {Text: "Message to client", Widget: messageField, HintText: "A message to send to all clients"},
154 | {Text: "Use T-", Widget: invertField, HintText: "Use T- instead of T+"},
155 | },
156 | }),
157 | container.NewTabItemWithIcon("Server Settings", theme.ConfirmIcon(), &widget.Form{
158 | Items: []*widget.FormItem{
159 | {Text: "OSC Input Port", Widget: oscInput, HintText: "OSC Input port (usually 7000)"},
160 | {Text: "OSC Output Port", Widget: oscOutput, HintText: "OSC Output port (usually 7001) Note: If you have multiple services using Resolume OSC make use the correct broadcast address."},
161 | {Text: "OSC Host Address", Widget: oscAddr, HintText: "IP address of device that's running Resolume (make sure to open the OSC input port in your firewall)"},
162 | {Text: "HTTP Server Port", Widget: httpPortField, HintText: "The port to run the browser interface on"},
163 | },
164 | }),
165 | ),
166 | },
167 | },
168 | SubmitText: "Start Server",
169 | CancelText: "Stop Server",
170 | }
171 |
172 | form.OnCancel = nil
173 | form.OnSubmit = func() {
174 | clipPath = path.Text
175 | a.Preferences().SetString("clipPath", clipPath)
176 | OSCOutPort = oscOutput.Text
177 | a.Preferences().SetString("OSCOutPort", OSCOutPort)
178 | OSCPort = oscInput.Text
179 | a.Preferences().SetString("OSCPort", OSCPort)
180 | OSCAddr = oscAddr.Text
181 | a.Preferences().SetString("OSCAddr", OSCAddr)
182 | httpPort = httpPortField.Text
183 | a.Preferences().SetString("httpPort", httpPort)
184 |
185 | clientMessage = template.HTMLEscapeString(messageField.Text)
186 | broadcast.Publish(osc.NewMessage("/message", clientMessage))
187 |
188 | clipInvert = !invertField.Checked
189 | a.Preferences().SetBool("clipInvert", clipInvert)
190 | broadcast.Publish(osc.NewMessage("/tminus", !clipInvert))
191 |
192 | infoLabel.ParseMarkdown("Starting Server")
193 |
194 | if err := serverStart(); err != nil {
195 | dialog.ShowError(err, w)
196 | infoLabel.ParseMarkdown("Server Errored")
197 | return
198 | }
199 |
200 | reset()
201 |
202 | ip, err := externalIP()
203 | if err != nil {
204 | dialog.ShowError(err, w)
205 | infoLabel.ParseMarkdown("Server Errored")
206 | return
207 | }
208 |
209 | infoLabel.ParseMarkdown(fmt.Sprintf("Server Running. Open your web browser to [http://%s:%s](http://%[1]s:%[2]s/) (or any other address for this device) to view the timecode.\n", ip, httpPort))
210 | form.SubmitText = "Update Settings"
211 | oscOutput.Disable()
212 | oscInput.Disable()
213 | oscAddr.Disable()
214 | httpPortField.Disable()
215 | resetButton.Show()
216 |
217 | form.OnCancel = func() {
218 | infoLabel.ParseMarkdown("Stopping Server")
219 | resetButton.Hide()
220 | serverStop()
221 | clipNameBinding.Set("Clip Name: None")
222 | infoLabel.ParseMarkdown("Server Stopped")
223 | form.SubmitText = "Start Server"
224 | oscOutput.Enable()
225 | oscInput.Enable()
226 | oscAddr.Enable()
227 | httpPortField.Enable()
228 |
229 | form.OnCancel = nil
230 | reset()
231 |
232 | form.Refresh()
233 | runtime.GC()
234 | }
235 |
236 | form.Refresh()
237 | runtime.GC()
238 | }
239 |
240 | w.SetContent(container.NewVSplit(form,
241 | container.NewBorder(infoLabel,
242 | container.NewGridWithColumns(4, timeLeftLabel, clipLengthLabel, clipNameLabel, resetButton), nil, nil)))
243 | w.ShowAndRun()
244 | }
245 |
--------------------------------------------------------------------------------
/images/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chabad360/resolume-timecode/aac006712bfc31f0d06734260c16ac4476a72325/images/demo.png
--------------------------------------------------------------------------------
/images/demo2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chabad360/resolume-timecode/aac006712bfc31f0d06734260c16ac4476a72325/images/demo2.jpg
--------------------------------------------------------------------------------
/images/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Timecode Monitor
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
34 |
35 |
36 |
37 | Timecode Monitor
38 |
39 |
Clip Name: None
40 |
41 |
42 | - |
43 | 00 |
44 | : |
45 | 00 |
46 | : |
47 | 00 |
48 | . |
49 | 000 |
50 |
51 |
52 | |
53 | Hours |
54 | |
55 | Minutes |
56 | |
57 | Seconds |
58 | |
59 | Milliseconds |
60 |
61 |
62 |
63 |
64 |
65 | Settings
66 | Clip Length: 0.000s
67 | Server Status: Server Stopped
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Checkout this tool at chabad360/resolume-timecode
85 |
86 |
87 |
88 |
89 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/macos.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright (c) 2017 David Pennington (modified by Mendel Greenberg) LICENSE: MIT
3 |
4 | # Mac OSX .app builder
5 |
6 | function die {
7 | echo "ERROR: $1" > /dev/null 1>&2
8 | exit 1
9 | }
10 |
11 | if [ "$#" -ne 5 ]; then
12 | die "Usage: `basename $0` AppNameHere icon-file.svg com.example.app 0 1"
13 | fi
14 |
15 | APPNAME=$1
16 | ICONNAME=$2
17 | APPID=$3
18 | MAJOR=$4
19 | MINOR=$5
20 |
21 | if [ ! -f $ICONNAME ]; then
22 | die "Image file for icon not found"
23 | fi
24 |
25 | mkdir -p "$APPNAME.app/Contents/"{MacOS,Resources}
26 |
27 | cat > "$APPNAME.app/Contents/Info.plist" <
29 |
30 |
31 |
32 | CFBundleGetInfoString
33 | $APPNAME
34 | CFBundleExecutable
35 | $APPNAME
36 | CFBundleIdentifier
37 | $APPID
38 | CFBundleName
39 | $APPNAME
40 | CFBundleIconFile
41 | icon.icns
42 | CFBundleShortVersionString
43 | ${MAJOR}.${MINOR}
44 | CFBundleInfoDictionaryVersion
45 | 6.0
46 | CFBundlePackageType
47 | APPL
48 | IFMajorVersion
49 | $MAJOR
50 | IFMinorVersion
51 | $MINOR
52 | NSHighResolutionCapable
53 | NSSupportsAutomaticGraphicsSwitching
54 |
55 |
56 | END
57 |
58 | cp $ICONNAME "$APPNAME.app/Contents/Resources/"
59 | cd "$APPNAME.app/Contents/Resources/"
60 |
61 | fileName="$(basename $ICONNAME)"
62 | postfix=${fileName##*.}
63 |
64 | if [[ $postfix == 'svg' ]]; then
65 | rsvg-convert -h 1024 "$fileName" > ${fileName}.png
66 | fileName=${fileName}.png
67 | fi
68 |
69 | echo $fileName
70 |
71 | mkdir icon.iconset
72 |
73 | sips -z 16 16 "$fileName" --out icon.iconset/icon_16x16.png
74 | sips -z 32 32 "$fileName" --out icon.iconset/icon_16x16@2x.png
75 | cp icon.iconset/icon_16x16@2x.png icon.iconset/icon_32x32.png
76 | sips -z 64 64 "$fileName" --out icon.iconset/icon_32x32@2x.png
77 | sips -z 128 128 "$fileName" --out icon.iconset/icon_128x128.png
78 | sips -z 256 256 "$fileName" --out icon.iconset/icon_128x128@2x.png
79 | cp icon.iconset/icon_128x128@2x.png icon.iconset/icon_256x256.png
80 | sips -z 512 512 "$fileName" --out icon.iconset/icon_256x256@2x.png
81 | cp icon.iconset/icon_256x256@2x.png icon.iconset/icon_512x512.png
82 | sips -z 1024 1024 "$fileName" --out icon.iconset/icon_512x512@2x.png
83 |
84 | # Create .icns file
85 | iconutil -c icns icon.iconset
86 |
87 | # Cleanup
88 | rm -R icon.iconset
89 | rm $fileName
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "embed"
6 | "fmt"
7 | "net"
8 | "net/http"
9 | "runtime"
10 | "sync"
11 | "time"
12 |
13 | "fyne.io/fyne/v2/app"
14 | "github.com/chabad360/go-osc/osc"
15 | "nhooyr.io/websocket"
16 | )
17 |
18 | var (
19 | broadcast = &Distributor{
20 | l: map[string]chan []byte{},
21 | }
22 | a = app.NewWithID("me.chabad360.resolume-timecode")
23 |
24 | OSCOutPort = a.Preferences().StringWithFallback("OSCOutPort", "7001")
25 | OSCPort = a.Preferences().StringWithFallback("OSCPort", "7000")
26 | OSCAddr = a.Preferences().StringWithFallback("OSCAddr", "127.0.0.1")
27 | httpPort = a.Preferences().StringWithFallback("httpPort", "8080")
28 | clipPath = a.Preferences().StringWithFallback("clipPath", "")
29 | clientMessage = ""
30 | clipInvert = a.Preferences().BoolWithFallback("clipInvert", false)
31 |
32 | //go:embed index.html
33 | //go:embed main.js
34 | //go:embed images/favicon.png
35 | //go:embed osc.min.js
36 | //go:embed osc.min.js.map
37 | fs embed.FS
38 |
39 | m = http.NewServeMux()
40 | httpServer *http.Server
41 | oscServer *osc.Server
42 | wg sync.WaitGroup
43 | running bool
44 | message = &osc.Message{Arguments: []interface{}{"?"}}
45 | message2 = &osc.Message{Arguments: []interface{}{"?"}}
46 | t = time.Tick(time.Minute)
47 | )
48 |
49 | func main() {
50 | //pr := profile.Start(profile.MemProfile, profile.ProfilePath("."), profile.NoShutdownHook)
51 | //defer pr.Stop()
52 |
53 | m.HandleFunc("/", websocketStart)
54 | //m.HandleFunc("/", http.StripPrefix("/", http.FileServer(http.FS(fs))).ServeHTTP)
55 | m.HandleFunc("/main.js", http.StripPrefix("/", http.FileServer(http.FS(fs))).ServeHTTP)
56 | m.HandleFunc("/osc.min.js", http.StripPrefix("/", http.FileServer(http.FS(fs))).ServeHTTP)
57 | m.HandleFunc("/osc.min.js.map", http.StripPrefix("/", http.FileServer(http.FS(fs))).ServeHTTP)
58 | m.HandleFunc("/images/favicon.png", http.StripPrefix("/", http.FileServer(http.FS(fs))).ServeHTTP)
59 |
60 | gui()
61 |
62 | serverStop()
63 | }
64 |
65 | func serverStart() error {
66 | if running {
67 | return nil
68 | }
69 |
70 | oscServer = &osc.Server{Addr: ":" + OSCOutPort, Handler: handleOSC}
71 |
72 | wg.Add(1)
73 | go func() {
74 | defer wg.Done()
75 | oscServer.ListenAndServe()
76 | }()
77 |
78 | httpServer = &http.Server{Addr: ":" + httpPort, Handler: m}
79 |
80 | wg.Add(1)
81 | go func() {
82 | defer wg.Done()
83 | httpServer.ListenAndServe()
84 | }()
85 |
86 | wg.Add(1)
87 | go func() {
88 | defer wg.Done()
89 | for !running {
90 | }
91 | for running {
92 | select {
93 | case <-t:
94 | runtime.GC()
95 | default:
96 | time.Sleep(time.Millisecond * 100)
97 | }
98 | }
99 | }()
100 |
101 | wg.Add(1)
102 | go func() {
103 | defer wg.Done()
104 | for !running {
105 | }
106 | for running {
107 | time.Sleep(time.Millisecond * 110)
108 | clipLengthBinding.Set(fmt.Sprintf("Clip Length: %.3fs", clipLength))
109 | timeLeftBinding.Set(timeLeft)
110 | }
111 | timeLeftBinding.Set("00:00:00.000")
112 | clipLengthBinding.Set("Clip Length: 0.000s")
113 | }()
114 |
115 | running = true
116 | return nil
117 | }
118 |
119 | func serverStop() {
120 | if running {
121 | broadcast.Publish(osc.NewMessage("/stop"))
122 | broadcast.Send()
123 | ctx, c := context.WithTimeout(context.Background(), time.Second*3)
124 | err := httpServer.Shutdown(ctx)
125 | oscServer.Close()
126 | if err != nil {
127 | httpServer.Close()
128 | }
129 | c()
130 | running = false
131 | wg.Wait()
132 | }
133 | }
134 |
135 | // https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go
136 | func externalIP() (string, error) {
137 | isLoopback := false
138 | ifaces, err := net.Interfaces()
139 | if err != nil {
140 | return "", err
141 | }
142 | for _, iface := range ifaces {
143 | if iface.Flags&net.FlagUp == 0 {
144 | continue // interface down
145 | }
146 | if iface.Flags&net.FlagLoopback != 0 {
147 | isLoopback = true
148 | continue // loopback interface
149 | }
150 | addrs, err := iface.Addrs()
151 | if err != nil {
152 | return "", err
153 | }
154 | for _, addr := range addrs {
155 | var ip net.IP
156 | switch v := addr.(type) {
157 | case *net.IPNet:
158 | ip = v.IP
159 | case *net.IPAddr:
160 | ip = v.IP
161 | }
162 | if ip == nil || ip.IsLoopback() {
163 | isLoopback = true
164 | continue
165 | }
166 | ip = ip.To4()
167 | if ip == nil {
168 | continue // not an ipv4 address
169 | }
170 | return ip.String(), nil
171 | }
172 | }
173 | if isLoopback { // if there is nothing other than the loopback interface, then we'll use that.
174 | return "127.0.0.1", nil
175 | }
176 | return "", fmt.Errorf("no network interfaces found")
177 | }
178 |
179 | func handleOSC(packet osc.Packet, a net.Addr) {
180 | if packet != nil {
181 | switch data := packet.(type) {
182 | case *osc.Message:
183 | procMsg(data)
184 |
185 | case *osc.Bundle:
186 | for _, elem := range data.Elements {
187 | handleOSC(elem, a)
188 | }
189 | }
190 | }
191 | }
192 |
193 | func websocketStart(w http.ResponseWriter, r *http.Request) {
194 | if r.Header.Get("Upgrade") == "" {
195 | http.StripPrefix("/", http.FileServer(http.FS(fs))).ServeHTTP(w, r)
196 | return
197 | }
198 | c, err := websocket.Accept(w, r, nil)
199 | if err != nil {
200 | return
201 | }
202 | defer c.Close(websocket.StatusInternalError, "the sky is falling")
203 |
204 | ctx := c.CloseRead(context.Background())
205 |
206 | //m, _ := osc.NewMessage("/open").MarshalBinary()
207 | //if c.Write(ctx, websocket.MessageBinary, m) != nil {
208 | // return
209 | //}
210 |
211 | b, _ := osc.NewBundle(osc.NewMessage("/message", clientMessage), osc.NewMessage("/name", clipName), osc.NewMessage("/tminus", !clipInvert)).MarshalBinary()
212 | if c.Write(ctx, websocket.MessageBinary, b) != nil {
213 | return
214 | }
215 |
216 | l := broadcast.Listen(r.RemoteAddr)
217 | defer broadcast.Close(r.RemoteAddr)
218 |
219 | for {
220 | select {
221 | case <-ctx.Done():
222 | c.Close(websocket.StatusNormalClosure, "")
223 | return
224 | case m := <-l:
225 | if c.Write(ctx, websocket.MessageBinary, m) != nil {
226 | //log.Println(err)
227 | return
228 | }
229 | }
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | // import OSC from "./osc.min.js";
2 |
3 | function main(){
4 | "use strict";
5 |
6 | const plugin = new OSC.WebsocketClientPlugin({ host: location.hostname, port: location.port });
7 | const osc = new OSC({ plugin: plugin });
8 |
9 | osc.on('open', () => {statusLabel.innerHTML = "Server Running";});
10 | osc.on('/name', (message) => procName(message));
11 | osc.on('/message', (message) => procMsg(message));
12 | osc.on('/time', (message) => procTime(message));
13 | osc.on('/refresh', () => location.reload());
14 | osc.on('/connect', () => reset());
15 | osc.on('/stop', () => plugin.close());
16 | osc.on('/tminus', (message) => procTminus(message));
17 | osc.on('close', () => close());
18 |
19 | const timecodeHours = document.getElementById("timecode-hours");
20 | const timecodeMinutes = document.getElementById("timecode-minutes");
21 | const timecodeSeconds = document.getElementById("timecode-seconds");
22 | const timecodeMS = document.getElementById("timecode-ms");
23 | const timecodeMinus = document.getElementsByClassName("minus");
24 | const timecodeClipName = document.getElementById("clipname");
25 | const table = document.getElementById("table");
26 | const tableBorder = document.getElementById("tableborder");
27 | const clipLength = document.getElementById("ms");
28 | const statusLabel = document.getElementById("status");
29 | const message = document.getElementById("msg");
30 |
31 | reset();
32 | osc.open();
33 |
34 | function close() {
35 | statusLabel.innerHTML = "Server Stopped";
36 |
37 | timecodeHours.innerHTML = "00";
38 | timecodeMinutes.innerHTML = "00";
39 | timecodeSeconds.innerHTML = "00";
40 | timecodeMS.innerHTML = "000";
41 | clipLength.innerHTML = "0.000s";
42 |
43 | table.style.color = "#ff4545";
44 | tableBorder.style.borderColor = "#ff4545";
45 | }
46 |
47 | function procName(data) {
48 | timecodeClipName.innerHTML = data.args[0];
49 | }
50 |
51 | function procTminus(data) {
52 | data.args[0] === true ? timecodeMinus[0].innerHTML = "-" : timecodeMinus[0].innerHTML = '+'
53 | }
54 |
55 | function reset() {
56 | timecodeHours.innerHTML = "00";
57 | timecodeMinutes.innerHTML = "00";
58 | timecodeSeconds.innerHTML = "00";
59 | timecodeMS.innerHTML = "000";
60 | clipLength.innerHTML = "0.000s";
61 | }
62 |
63 | async function procMsg(data) {
64 | data = data.args[0];
65 | message.innerHTML = (data === "") ? "Timecode Monitor" : data;
66 | if (data === "") {
67 | return;
68 | }
69 | for (let i = 0; i < 3; i++) {
70 | message.style.color = "#ff4545";
71 | await new Promise(r => setTimeout(r, 500));
72 | message.style.color = "#FDFBF7";
73 | await new Promise(r => setTimeout(r, 500));
74 | }
75 | }
76 |
77 | function procTime(data) {
78 | clipLength.innerHTML = data.args[1];
79 |
80 | data = data.args[0].split(":");
81 | timecodeHours.innerHTML = data[0].substring(1);
82 | timecodeMinutes.innerHTML = data[1];
83 | timecodeSeconds.innerHTML = data[2].split(".")[0];
84 | timecodeMS.innerHTML = data[2].split(".")[1];
85 |
86 | if (parseInt(data[2]) <= 10 && parseInt(data[1]) < 1 && parseInt(data[0].substring(1)) < 1) {
87 | table.style.color = "#ff4545";
88 | tableBorder.style.borderColor = "#ff4545";
89 | } else {
90 | table.style.color = "#45ff45";
91 | tableBorder.style.borderColor = "#4b5457";
92 | }
93 | }
94 | }
95 |
96 | main();
--------------------------------------------------------------------------------
/osc.min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).OSC=e()}(this,(function(){"use strict";function t(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function e(e){for(var n=1;n1&&"/"===e[e.length-1]&&(e=e.slice(0,e.length-1)),e.length>1&&"/"!==e[0]&&(e="/".concat(e)),e;throw new Error("OSC prepareAddress() needs addresses of type array or string")}function j(t){if(!v(t))throw new Error("OSC prepareRegExPattern() needs strings");return t.replace(/\./g,"\\.").replace(/\(/g,"\\(").replace(/\)/g,"\\)").replace(/\{/g,"(").replace(/\}/g,")").replace(/,/g,"|").replace(/\[!/g,"[^").replace(/\?/g,".").replace(/\*/g,".*")}var x=function(){function t(){n(this,t),this.data=[],this.byteLength=0}return o(t,[{key:"add",value:function(t){if(w(t)||y(t)||E(t))return this;var e=t.pack();return this.byteLength+=e.byteLength,this.data.push(e),this}},{key:"merge",value:function(){var t=new Uint8Array(this.byteLength),e=0;return this.data.forEach((function(n){t.set(n,e),e+=n.byteLength})),t}}]),t}(),B=function(){function t(e){n(this,t),this.value=e,this.offset=0}return o(t,[{key:"pack",value:function(t,e){if(!t||!e)throw new Error("OSC Atomic cant't be packed without given method or byteLength");var n=new Uint8Array(e),r=new DataView(n.buffer);if(O(this.value))throw new Error("OSC Atomic cant't be encoded with empty value");return r[t](this.offset,this.value,!1),n}},{key:"unpack",value:function(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;if(!(t&&e&&n))throw new Error("OSC Atomic cant't be unpacked without given dataView, method or byteLength");if(!(t instanceof DataView))throw new Error("OSC Atomic expects an instance of type DataView");return this.value=t[e](r,!1),this.offset=r+n,this.offset}}]),t}(),H=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!p(t))throw new Error("OSC AtomicInt32 constructor expects value of type number");return e.call(this,t)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setInt32",4)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getInt32",4,e)}}]),r}(B),T="utf-8";function L(t){if(P("Buffer"))return Buffer.from(t).toString(T);if(P("TextDecoder"))return new TextDecoder(T).decode(new Int8Array(t));for(var e="",n=0;n1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC AtomicString expects an instance of type DataView");for(var n,r=e,o=[];r0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(n(this,t),!p(e)||!p(r))throw new Error("OSC Timetag constructor expects values of type integer number");this.seconds=e,this.fractions=r}return o(t,[{key:"timestamp",value:function(t){var e;if("number"==typeof t){e=t/1e3;var n=Math.floor(e);return this.seconds=n+M,this.fractions=Math.round(N*(e-n)),t}return 1e3*((e=this.seconds-M)+Math.round(this.fractions/N))}}]),t}(),U=function(t){s(r,t);var e=f(r);function r(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Date.now();n(this,r);var o=new V;return t instanceof V?o=t:p(t)?o.timestamp(t):S(t)&&o.timestamp(t.getTime()),e.call(this,o)}return o(r,[{key:"pack",value:function(){if(O(this.value))throw new Error("OSC AtomicTimetag can not be encoded with empty value");var t=this.value,e=t.seconds,n=t.fractions,r=new Uint8Array(8),o=new DataView(r.buffer);return o.setInt32(0,e,!1),o.setInt32(4,n,!1),r}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC AtomicTimetag expects an instance of type DataView");var n=t.getUint32(e,!1),r=t.getUint32(e+4,!1);return this.value=new V(n,r),this.offset=e+8,this.offset}}]),r}(B),R=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!m(t))throw new Error("OSC AtomicBlob constructor expects value of type Uint8Array");return e.call(this,t)}return o(r,[{key:"pack",value:function(){if(O(this.value))throw new Error("OSC AtomicBlob can not be encoded with empty value");var t=C(this.value.byteLength),e=new Uint8Array(t+4);return new DataView(e.buffer).setInt32(0,this.value.byteLength,!1),e.set(this.value,4),e}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC AtomicBlob expects an instance of type DataView");var n=t.getInt32(e,!1);return this.value=new Uint8Array(t.buffer,e+4,n),this.offset=C(e+4+n),this.offset}}]),r}(B),F=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!d(t))throw new Error("OSC AtomicFloat32 constructor expects value of type float");return e.call(this,t)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setFloat32",4)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getFloat32",4,e)}}]),r}(B),W=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&!d(t))throw new Error("OSC AtomicFloat64 constructor expects value of type float");return e.call(this,t)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setFloat64",8)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getFloat64",8,e)}}]),r}(B),q=BigInt("9223372036854775807"),z=BigInt("-9223372036854775808"),G=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&"bigint"!=typeof t)throw new Error("OSC AtomicInt64 constructor expects value of type BigInt");if(t&&(tq))throw new Error("OSC AtomicInt64 value is out of bounds");var o;return t&&(o=BigInt.asIntN(64,t)),e.call(this,o)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setBigInt64",8)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getBigInt64",8,e)}}]),r}(B),Z=BigInt("18446744073709551615"),J=function(t){s(r,t);var e=f(r);function r(t){if(n(this,r),t&&"bigint"!=typeof t)throw new Error("OSC AtomicUInt64 constructor expects value of type BigInt");if(t&&(t<0||t>Z))throw new Error("OSC AtomicUInt64 value is out of bounds");var o;return t&&(o=BigInt.asUintN(64,t)),e.call(this,o)}return o(r,[{key:"pack",value:function(){return h(a(r.prototype),"pack",this).call(this,"setBigUint64",8)}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return h(a(r.prototype),"unpack",this).call(this,t,"getBigUint64",8,e)}}]),r}(B),K=!0,Q=!1,X=null,Y=1/0,$=function(){function t(e,r){var o=this;if(n(this,t),this.offset=0,this.address="",this.types="",this.args=[],!O(e)){if(!v(e)&&!g(e))throw new Error("OSC Message constructor first argument (address) must be a string or array");this.address=D(e)}if(!O(r)){if(!g(r))throw new Error("OSC Message constructor second argument (args) must be an array");r.forEach((function(t){return o.add(t.type,t.value)}))}}return o(t,[{key:"add",value:function(t,e){if(O(t))throw new Error("OSC Message needs a valid OSC Atomic Data Type");"N"===t?this.args.push(X):"T"===t?this.args.push(K):"F"===t?this.args.push(Q):"I"===t?this.args.push(Y):this.args.push(e),this.types+=t}},{key:"pack",value:function(){var t=this;if(0===this.address.length||"/"!==this.address[0])throw new Error("OSC Message has an invalid address");var e=new x;if(e.add(new _(this.address)),e.add(new _(",".concat(this.types))),this.args.length>0){var n;if(this.args.length>this.types.length)throw new Error("OSC Message argument and type tag mismatch");this.args.forEach((function(r,o){var i=t.types[o];if("i"===i)n=new H(r);else if("h"===i)n=new G(r);else if("t"===i)n=new J(r);else if("f"===i)n=new F(r);else if("d"===i)n=new W(r);else if("s"===i)n=new _(r);else if("b"===i)n=new R(r);else if("T"===i)n=K;else if("F"===i)n=Q;else if("N"===i)n=X;else{if("I"!==i)throw new Error("OSC Message found unknown argument type");n=Y}e.add(n)}))}return e.merge()}},{key:"unpack",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC Message expects an instance of type DataView.");var n=new _;n.unpack(t,e);var r=new _;if(r.unpack(t,n.offset),0===n.value.length||"/"!==n.value[0])throw new Error("OSC Message found malformed or missing address string");if(0===r.value.length&&","!==r.value[0])throw new Error("OSC Message found malformed or missing type string");for(var o,i,s=r.offset,a=[],u=1;u0&&(o=a.shift()),a.length>0&&a[0]instanceof Array&&(i=a.shift()),t=e.call(this,o,i),a.length>0&&(t.types=a.map((function(t){return I(t)})).join(""),t.args=a),t}return o(r,[{key:"add",value:function(t){h(a(r.prototype),"add",this).call(this,I(t),t)}}]),r}($),et="#bundle",nt=function(){function t(){var e=this;n(this,t),this.offset=0,this.timetag=new U,this.bundleElements=[];for(var r=arguments.length,o=new Array(r),i=0;i0&&(o[0]instanceof Date||p(o[0])?this.timetag=new U(o[0]):g(o[0])?(o[0].forEach((function(t){e.add(t)})),o.length>1&&(o[1]instanceof Date||p(o[0]))&&(this.timetag=new U(o[1]))):o.forEach((function(t){e.add(t)})))}return o(t,[{key:"timestamp",value:function(t){if(!p(t))throw new Error("OSC Bundle needs an integer for setting the timestamp");this.timetag=new U(t)}},{key:"add",value:function(e){if(!(e instanceof tt||e instanceof t))throw new Error("OSC Bundle contains only Messages and Bundles");this.bundleElements.push(e)}},{key:"pack",value:function(){var t=new x;return t.add(new _(et)),this.timetag||(this.timetag=new U),t.add(this.timetag),this.bundleElements.forEach((function(e){t.add(new H(e.pack().byteLength)),t.add(e)})),t.merge()}},{key:"unpack",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(!(e instanceof DataView))throw new Error("OSC Bundle expects an instance of type DataView");var r=new _;if(r.unpack(e,n),r.value!==et)throw new Error("OSC Bundle does not contain a valid #bundle head");var o=new U,i=o.unpack(e,r.offset);for(this.bundleElements=[];i1&&void 0!==arguments[1]?arguments[1]:0;if(!(t instanceof DataView))throw new Error("OSC Packet expects an instance of type DataView");if(t.byteLength%4!=0)throw new Error("OSC Packet byteLength has to be a multiple of four");var n,r=new _;return r.unpack(t,e),(n=r.value===et?new nt:new tt).unpack(t,e),this.offset=n.offset,this.value=n,this.offset}}]),t}(),ot={discardLateMessages:!1},it=function(){function t(r){n(this,t),this.options=e(e({},ot),r),this.addressHandlers=[],this.eventHandlers={open:[],error:[],close:[]},this.uuid=0}return o(t,[{key:"dispatch",value:function(t,e){var n=this;if(!(t instanceof rt))throw new Error("OSC EventHander dispatch() accepts only arguments of type Packet");if(!t.value)throw new Error("OSC EventHander dispatch() can't read empty Packets");if(t.value instanceof nt){var r=t.value;return r.bundleElements.forEach((function(t){if(t instanceof nt){if(r.timetag.value.timestamp()1&&(i=e[1]);var s=null;if(e.length>2)if(p(e[2]))s=e[2];else{if(!(e[2]instanceof Date))throw new Error("OSC EventHandler timestamp has to be a number or Date");s=e[2].getTime()}var a=null;if(e.length>=3&&(a=e[3]),s){var u=Date.now();if(u>s&&!this.options.discardLateMessages)return this.call(o,i,a);var c=this;return setTimeout((function(){c.call(o,i,a)}),s-u),!0}return this.call(o,i,a)}},{key:"on",value:function(t,e){if(!v(t)&&!g(t))throw new Error("OSC EventHandler accepts only strings or arrays for address patterns");if(!b(e))throw new Error("OSC EventHandler callback has to be a function");this.uuid+=1;var n={id:this.uuid,callback:e};if(v(t)&&t in this.eventHandlers)return this.eventHandlers[t].push(n),this.uuid;var r=D(t);return r in this.addressHandlers||(this.addressHandlers[r]=[]),this.addressHandlers[r].push(n),this.uuid}},{key:"off",value:function(t,e){if(!v(t)&&!g(t))throw new Error("OSC EventHandler accepts only strings or arrays for address patterns");if(!p(e))throw new Error("OSC EventHandler subscription id has to be a number");var n,r;return v(t)&&t in this.eventHandlers?(n=t,r=this.eventHandlers):(n=D(t),r=this.addressHandlers),n in r&&r[n].some((function(t,o){return t.id===e&&(r[n].splice(o,1),!0)}))}}]),t}(),st="undefined"!=typeof __dirname?require("dgram"):void 0,at=-1,ut=0,ct=1,ft=2,lt=3,ht={type:"udp4",open:{host:"localhost",port:41234,exclusive:!1},send:{host:"localhost",port:41235}};function pt(t,n){return e(e(e(e({},ht),t),n),{},{open:e(e(e({},ht.open),t.open),n.open),send:e(e(e({},ht.send),t.send),n.send)})}var dt=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(n(this,t),!st)throw new Error("DatagramPlugin can not be used in browser context");this.options=pt({},r),this.socket=st.createSocket(this.options.type),this.socketStatus=at,this.socket.on("message",(function(t,n){e.notify(t,n)})),this.socket.on("error",(function(t){e.notify("error",t)})),this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e(e({},this.options.open),n),o=r.port,i=r.exclusive;this.socketStatus=ut,this.socket.bind({address:r.host,port:o,exclusive:i},(function(){t.socketStatus=ct,t.notify("open")}))}},{key:"close",value:function(){var t=this;this.socketStatus=ft,this.socket.close((function(){t.socketStatus=lt,t.notify("close")}))}},{key:"send",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=e(e({},this.options.send),n),o=r.port,i=r.host;this.socket.send(Buffer.from(t),0,t.byteLength,o,i)}}]),t}(),vt="undefined"!=typeof __dirname?require("dgram"):void 0,wt="undefined"!=typeof __dirname?require("isomorphic-ws").Server:void 0,yt=-1,gt=0,kt=1,bt=2,mt=3,St={udpServer:{host:"localhost",port:41234,exclusive:!1},udpClient:{host:"localhost",port:41235},wsServer:{host:"localhost",port:8080},receiver:"ws"};function Ot(t,n){return e(e(e(e({},St),t),n),{},{udpServer:e(e(e({},St.udpServer),t.udpServer),n.udpServer),udpClient:e(e(e({},St.udpClient),t.udpClient),n.udpClient),wsServer:e(e(e({},St.wsServer),t.wsServer),n.wsServer)})}var Et=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(n(this,t),!vt||!wt)throw new Error("BridgePlugin can not be used in browser context");this.options=Ot({},r),this.websocket=null,this.socket=vt.createSocket("udp4"),this.socketStatus=yt,this.socket.on("message",(function(t){e.send(t,{receiver:"ws"}),e.notify(t.buffer)})),this.socket.on("error",(function(t){e.notify("error",t)})),this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=Ot(this.options,e);this.socketStatus=gt,this.socket.bind({address:n.udpServer.host,port:n.udpServer.port,exclusive:n.udpServer.exclusive},(function(){var e={};n.wsServer.server?e.server=n.wsServer.server:e=n.wsServer,t.websocket=new wt(e),t.websocket.binaryType="arraybuffer",t.websocket.on("listening",(function(){t.socketStatus=kt,t.notify("open")})),t.websocket.on("error",(function(e){t.notify("error",e)})),t.websocket.on("connection",(function(e){e.on("message",(function(e,n){t.send(e,{receiver:"udp"}),t.notify(new Uint8Array(e),n)}))}))}))}},{key:"close",value:function(){var t=this;this.socketStatus=bt,this.socket.close((function(){t.websocket.close((function(){t.socketStatus=mt,t.notify("close")}))}))}},{key:"send",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Ot(this.options,e),r=n.receiver;if("udp"===r){var o=t instanceof Buffer?t:Buffer.from(t);this.socket.send(o,0,o.byteLength,n.udpClient.port,n.udpClient.host)}else{if("ws"!==r)throw new Error("BridgePlugin can not send message to unknown receiver");this.websocket.clients.forEach((function(e){e.send(t,{binary:!0})}))}}}]),t}(),Ct="undefined"==typeof global?window:global,Pt="undefined"==typeof __dirname?Ct.WebSocket:require("isomorphic-ws"),At=-1,It=0,Dt=1,jt=2,xt=3,Bt={host:"localhost",port:8080,secure:!1,protocol:[]},Ht=function(){function t(r){if(n(this,t),!Pt)throw new Error("WebsocketClientPlugin can't find a WebSocket class");this.options=e(e({},Bt),r),this.socket=null,this.socketStatus=At,this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e(e({},this.options),n),o=r.port,i=r.host,s=r.secure,a=r.protocol;this.socket&&this.close();var u=s?"wss":"ws",c={address:i,family:u,port:o,size:0};this.socket=new Pt("".concat(u,"://").concat(i,":").concat(o),a),this.socket.binaryType="arraybuffer",this.socketStatus=It,this.socket.onopen=function(){t.socketStatus=Dt,t.notify("open")},this.socket.onclose=function(){t.socketStatus=xt,t.notify("close")},this.socket.onerror=function(e){t.notify("error",e)},this.socket.onmessage=function(e){t.notify(e.data,c)}}},{key:"close",value:function(){this.socketStatus=jt,this.socket.close()}},{key:"send",value:function(t){this.socket.send(t)}}]),t}(),Tt="undefined"!=typeof __dirname?require("isomorphic-ws").Server:void 0,Lt=-1,_t=0,Mt=1,Nt=2,Vt=3,Ut={host:"localhost",port:8080},Rt=function(){function t(r){if(n(this,t),!Tt)throw new Error("WebsocketServerPlugin can not be used in browser context");this.options=e(e({},Ut),r),this.socket=null,this.socketStatus=Lt,this.notify=function(){}}return o(t,[{key:"registerNotify",value:function(t){this.notify=t}},{key:"status",value:function(){return this.socketStatus}},{key:"open",value:function(){var t=this,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e(e({},this.options),n),o=r.port,i=r.host,s={address:i,family:"wsserver",port:o,size:0};this.socket&&this.close(),r.server?this.socket=new Tt({server:r.server}):this.socket=new Tt({host:i,port:o}),this.socket.binaryType="arraybuffer",this.socketStatus=_t,this.socket.on("listening",(function(){t.socketStatus=Mt,t.notify("open")})),this.socket.on("error",(function(e){t.notify("error",e)})),this.socket.on("connection",(function(e){e.on("message",(function(e){t.notify(new Uint8Array(e),s)}))}))}},{key:"close",value:function(){var t=this;this.socketStatus=Nt,this.socket.close((function(){t.socketStatus=Vt,t.notify("close")}))}},{key:"send",value:function(t){this.socket.clients.forEach((function(e){e.send(t,{binary:!0})}))}}]),t}(),Ft={discardLateMessages:!1,plugin:new Ht},Wt=function(){function t(r){if(n(this,t),r&&!k(r))throw new Error("OSC options argument has to be an object.");this.options=e(e({},Ft),r),this.eventHandler=new it({discardLateMessages:this.options.discardLateMessages});var o=this.eventHandler;this.options.plugin&&this.options.plugin.registerNotify&&this.options.plugin.registerNotify((function(){return o.notify.apply(o,arguments)}))}return o(t,[{key:"on",value:function(t,e){if(!v(t)||!b(e))throw new Error("OSC on() needs event- or address string and callback function");return this.eventHandler.on(t,e)}},{key:"off",value:function(t,e){if(!v(t)||!p(e))throw new Error("OSC off() needs string and number (subscriptionId) to unsubscribe");return this.eventHandler.off(t,e)}},{key:"open",value:function(t){if(t&&!k(t))throw new Error("OSC open() options argument needs to be an object");if(!this.options.plugin||!b(this.options.plugin.open))throw new Error("OSC Plugin API #open is not implemented!");return this.options.plugin.open(t)}},{key:"status",value:function(){if(!this.options.plugin||!b(this.options.plugin.status))throw new Error("OSC Plugin API #status is not implemented!");return this.options.plugin.status()}},{key:"close",value:function(){if(!this.options.plugin||!b(this.options.plugin.close))throw new Error("OSC Plugin API #close is not implemented!");return this.options.plugin.close()}},{key:"send",value:function(t,e){if(!this.options.plugin||!b(this.options.plugin.send))throw new Error("OSC Plugin API #send is not implemented!");if(!(t instanceof $||t instanceof tt||t instanceof nt||t instanceof rt))throw new Error("OSC send() needs Messages, Bundles or Packets");if(e&&!k(e))throw new Error("OSC send() options argument has to be an object");return this.options.plugin.send(t.pack(),e)}}]),t}();return Wt.STATUS={IS_NOT_INITIALIZED:-1,IS_CONNECTING:0,IS_OPEN:1,IS_CLOSING:2,IS_CLOSED:3},Wt.Packet=rt,Wt.Bundle=nt,Wt.Message=tt,Wt.TypedMessage=$,Wt.DatagramPlugin=dt,Wt.WebsocketClientPlugin=Ht,Wt.WebsocketServerPlugin=Rt,Wt.BridgePlugin=Et,Wt}));
2 | //# sourceMappingURL=osc.min.js.map
3 |
--------------------------------------------------------------------------------
/procmessage.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | "time"
7 |
8 | "github.com/chabad360/go-osc/osc"
9 | )
10 |
11 | var (
12 | clipName = ""
13 | directionForward = true
14 |
15 | timeLeft string
16 |
17 | clipLength float32
18 | posPrev float32
19 | )
20 |
21 | func procMsg(data *osc.Message) {
22 | if strings.HasPrefix(data.Address, clipPath) {
23 | switch {
24 | case strings.HasSuffix(data.Address, "/position"):
25 | procPos(data)
26 | case strings.HasSuffix(data.Address, "direction"):
27 | procDirection(data)
28 | case strings.HasSuffix(data.Address, "/name"):
29 | procName(data)
30 | case strings.HasSuffix(data.Address, "/duration"):
31 | procDuration(data)
32 | case strings.HasSuffix(data.Address, "/connect"):
33 | reset()
34 | case strings.Contains(data.Address, "/select"):
35 | reset()
36 | }
37 | }
38 | }
39 |
40 | func procDirection(data *osc.Message) {
41 | directionForward = data.Arguments[0].(int32) != 0
42 | if !directionForward {
43 | posPrev = 1 - posPrev
44 | }
45 | }
46 |
47 | func procName(data *osc.Message) {
48 | clipName = data.Arguments[0].(string)
49 | clipNameBinding.Set("Clip Name: " + clipName)
50 | broadcast.Publish(osc.NewMessage("/name", clipName))
51 | }
52 |
53 | func procDuration(data *osc.Message) {
54 | clipLength = (data.Arguments[0].(float32) * 604800) + 0.001
55 | clipLengthBinding.Set(fmt.Sprintf("Clip Length: %.3fs", clipLength))
56 | broadcast.Publish(osc.NewMessage("/duration", clipLength))
57 | }
58 |
59 | func reset() {
60 | lightReset()
61 |
62 | posPrev = 0
63 | }
64 |
65 | func lightReset() {
66 | message.Address = clipPath + "/name"
67 | message2.Address = clipPath + "/transport/position/behaviour/duration"
68 | if _, err := oscServer.WriteTo(osc.NewBundle(message, message2), OSCAddr+":"+OSCPort); err != nil {
69 | fmt.Println(err)
70 | }
71 | }
72 |
73 | func procPos(data *osc.Message) {
74 | pos := data.Arguments[0].(float32)
75 |
76 | if !directionForward {
77 | pos = 1 - pos
78 | }
79 |
80 | if posPrev == 0 || posPrev == pos || pos < 0.002 {
81 | posPrev = pos
82 | return
83 | }
84 |
85 | currentPosInterval := pos - posPrev
86 |
87 | if currentPosInterval < 0 && posPrev > 0 {
88 | return
89 | }
90 |
91 | posPrev = pos
92 |
93 | if clipInvert {
94 | pos = 1 - pos
95 | }
96 |
97 | t := (clipLength * 1000) * (1 - pos)
98 |
99 | timeActual := time.UnixMilli(int64(t)).UTC()
100 |
101 | timeLeft = fmt.Sprintf("-%02d:%02d:%02d.%03d", timeActual.Hour(), timeActual.Minute(), timeActual.Second(), timeActual.Nanosecond()/1000000)
102 | broadcast.Publish(osc.NewMessage("/time", timeLeft, fmt.Sprintf("%.3fs", clipLength)))
103 | broadcast.Send()
104 |
105 | //fmt.Println(message, clipLength, samples, pos, currentPosInterval, currentTimeInterval, currentEstSize, posInterval, timeInterval, average(estSizeBuffer))
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/winres/winres.json:
--------------------------------------------------------------------------------
1 | {
2 | "RT_GROUP_ICON": {
3 | "OTHER": {
4 | "0000": [
5 | "icon.png"
6 | ]
7 | }
8 | },
9 | "RT_MANIFEST": {
10 | "#1": {
11 | "0409": {
12 | "identity": {
13 | "name": "",
14 | "version": ""
15 | },
16 | "description": "",
17 | "minimum-os": "win7",
18 | "execution-level": "as invoker",
19 | "ui-access": false,
20 | "auto-elevate": false,
21 | "dpi-awareness": "system",
22 | "disable-theming": false,
23 | "disable-window-filtering": false,
24 | "high-resolution-scrolling-aware": false,
25 | "ultra-high-resolution-scrolling-aware": false,
26 | "long-path-aware": false,
27 | "printer-driver-isolation": false,
28 | "gdi-scaling": false,
29 | "segment-heap": false,
30 | "use-common-controls-v6": false
31 | }
32 | }
33 | },
34 | "RT_VERSION": {
35 | "#1": {
36 | "0000": {
37 | "fixed": {
38 | "file_version": "0.0.0.0",
39 | "product_version": "0.0.0.0",
40 | "flags":"Prerelease"
41 | },
42 | "info": {
43 | "0409": {
44 | "Comments": "",
45 | "CompanyName": "chabad360",
46 | "FileDescription": "",
47 | "FileVersion": "",
48 | "InternalName": "",
49 | "LegalCopyright": "© 2021 Mendel Greenberg",
50 | "OriginalFilename": "resolume-timecode.exe",
51 | "PrivateBuild": "",
52 | "ProductName": "Resolume Timecode Monitor",
53 | "ProductVersion": "",
54 | "SpecialBuild": ""
55 | }
56 | }
57 | }
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------