diff --git a/README.md b/README.md index 8ba9203..0c2da9b 100644 --- a/README.md +++ b/README.md @@ -51,27 +51,36 @@ See [docs/hyperhdr.md](docs/hyperhdr.md) for both, step by step. ## Installing -**From the Homebrew Channel.** Open the Homebrew Channel on the TV, find -*Audio Cap*, install, launch. +This app is not in the official Homebrew Channel repository (that needs a +review submission — see [docs/development.md](docs/development.md)). Two ways +to get it onto the TV instead, neither needing SSH or Developer Mode: -**From an ipk.** Copy the ipk to the TV and install it with the Homebrew -Channel's *Install from file*, or from a workstation: +**Add it as a custom repository (recommended).** The Homebrew Channel can +browse-and-install from any repository URL you give it, not just the official +one. Build the ipk, publish it plus a generated repo index, then add that URL +on the TV: + +```sh +npm install # ares-cli, only needed for step 2 +./tools/docker-build.sh # cross-compile; Linux: ./tools/build.sh native +./tools/build.sh package # -> out/*.ipk +python3 tools/make-manifest.py --base-url +# -> out/repo.json, out/manifest.json +``` + +Attach the ipk, `frontend/assets/icon.png` and `out/repo.json` to a release at +that URL, then on the TV: **Homebrew Channel → ⚙ → Add repository** → paste the +`repo.json` URL → back to Browse → *Audio Cap* → Install. Full walkthrough, +including why the URLs have to match exactly, in +[docs/development.md](docs/development.md#publishing-to-the-homebrew-channel). + +**Install the ipk directly**, if you do have ares-cli talking to the TV (e.g. +LG Developer Mode's ssh on port 9922, or a root SSH server you've enabled): ```sh ares-install --device tv out/org.webosbrew.audiocap_1.0.0_all.ipk ``` -**From source.** The NDK is Linux-only, so on macOS or Windows the compile goes -through Docker: - -```sh -npm install # ares-cli -./tools/docker-build.sh # or ./tools/build.sh native on Linux -./tools/build.sh package # -> out/*.ipk -``` - -See [docs/development.md](docs/development.md) for the rest. - ## First run 1. Launch **Audio Cap** on the TV. diff --git a/docs/development.md b/docs/development.md index 21ef7a5..bed7ee5 100644 --- a/docs/development.md +++ b/docs/development.md @@ -107,22 +107,56 @@ npm run serve # http://localhost:8000 ## Publishing to the Homebrew Channel +Two ways to get an ipk into the Browse tab. Neither one touches `ares-install` +or ssh — the app installs itself once the TV can reach a URL. + +### Your own repository (no review, no waiting) + +The Homebrew Channel's *Settings → Repositories → Add repository* accepts any +URL that returns `{"packages": [...]}`, where each entry is the same manifest +[`make-manifest.py`](../tools/make-manifest.py) already writes. Point one at +your own git host's release assets and the app shows up in Browse with no +submission process at all — this is what `--repo-out` (on by default) is for. + 1. Bump `version` in `frontend/appinfo.json`, `servicefiles/package.json` and `package.json`. -2. `./tools/build.sh` and test the ipk on a real set. -3. Attach the ipk and `frontend/assets/icon.png` to a release. -4. Generate the manifest and attach that too: +2. Build the ipk: `./tools/docker-build.sh && ./tools/build.sh package` (or + `./tools/build.sh` on Linux with the NDK installed). +3. Create a release tagged e.g. `v1.0.0` and attach three files to it: the + ipk, `frontend/assets/icon.png`, and a repo index generated with + `--base-url` set to that release's asset URL: ```sh python3 tools/make-manifest.py \ --base-url https://git.crylia.de/Crylia/lgtv_audio_cap/releases/download/v1.0.0 + # -> out/manifest.json (one app entry) + # -> out/repo.json (that entry wrapped as {"packages": [...]}) ``` -5. Submit the manifest URL to [webosbrew/repo](https://github.com/webosbrew/repo). + Attach `out/repo.json` itself too — its own download URL is what you paste + into the TV, and it must match `--base-url` exactly or the ipk/icon links + inside it point at the wrong place. +4. On the TV: Homebrew Channel → gear icon → *Add repository* → paste the + `repo.json` release URL → back out to Browse → find *Audio Cap* → Install. -The manifest sets `"rootRequired": true`, which tells the Homebrew Channel the -service needs elevating. The app can also do it on demand — *System → Grant root -access* runs the Channel's `elevate-service`. +Shipping an update later is the same four steps with a bumped version and a +new release tag; the Channel diffs against the installed version and offers +an update once the repo URL is already added. + +### The official repo (public listing, reviewed) + +Submit once to [webosbrew/apps-repo](https://github.com/webosbrew/apps-repo) +and anyone with a stock Homebrew Channel install can find it without adding a +custom repository. That project wants a `.yml` descriptor pointing at your own +hosted `manifest.json` (the un-wrapped file from step 3 above) — see its README +for the submission format. + +--- + +`rootRequired: true` in the manifest tells the Homebrew Channel the service +needs elevating, from either path. The app can also do it on demand — +*System → Grant root access* runs the Channel's `elevate-service` itself, over +the Luna bus, so it works whether SSH is enabled on the TV or not. ## How the service is put together diff --git a/tools/make-manifest.py b/tools/make-manifest.py index 194063d..270ade3 100755 --- a/tools/make-manifest.py +++ b/tools/make-manifest.py @@ -1,15 +1,21 @@ #!/usr/bin/env python3 -"""Writes the Homebrew Channel manifest for a built ipk. +"""Writes the Homebrew Channel manifest for a built ipk, and a custom-repo +index that wraps it. -The Homebrew Channel installs apps from a manifest that points at the ipk and -carries its hash. Publishing means putting this file somewhere stable (a GitHub -release asset, or the repository itself) and submitting the URL to -webosbrew/repo. +The manifest (out/manifest.json) is one app entry: id, ipkUrl, ipkHash, and so +on. It is what you submit to webosbrew/apps-repo to get into the official +store. + +The repo index (out/repo.json) is that same entry wrapped as +`{"packages": [...]}`, which is the format the Homebrew Channel's own +"Add repository" dialog expects (Settings -> Repositories -> Add repository). +Host it anywhere static, paste its URL in, and the app shows up in Browse — +no submission, no review, no shell access to the TV at all. python3 tools/make-manifest.py \\ - --base-url https://github.com/you/lgtv-audio-cap/releases/download/v1.0.0 + --base-url https://git.example/you/lgtv-audio-cap/releases/download/v1.0.0 -Defaults to the newest ipk in out/ and writes out/manifest.json. +Defaults to the newest ipk in out/ and writes out/manifest.json + out/repo.json. """ import argparse @@ -47,6 +53,8 @@ def main(): parser.add_argument("--source-url", default=SOURCE_URL, help="project page shown in the Homebrew Channel") parser.add_argument("--out", default=os.path.join(ROOT, "out", "manifest.json")) + parser.add_argument("--repo-out", default=os.path.join(ROOT, "out", "repo.json"), + help="path for the custom-repo index (set to '' to skip)") args = parser.parse_args() appinfo = json.load(open(os.path.join(ROOT, "frontend", "appinfo.json"))) @@ -79,9 +87,16 @@ def main(): with open(args.out, "w") as fh: json.dump(manifest, fh, indent=2) fh.write("\n") - print(json.dumps(manifest, indent=2)) print("\nwrote %s" % os.path.relpath(args.out, ROOT), file=sys.stderr) + + if args.repo_out: + os.makedirs(os.path.dirname(args.repo_out) or ".", exist_ok=True) + with open(args.repo_out, "w") as fh: + json.dump({"packages": [manifest]}, fh, indent=2) + fh.write("\n") + print("wrote %s" % os.path.relpath(args.repo_out, ROOT), file=sys.stderr) + if not base: print("note: no --base-url given, so ipkUrl and iconUri are relative", file=sys.stderr)