-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6d85622
Showing
10 changed files
with
1,521 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Rearchiver <img src="rearchiver.svg" align="right" alt="Rearchiver logo" width="20%"/> | ||
> [Third Hemisphere Studio](https://thirdhemisphere.studio) tooling | ||
Rearchiver prepares your [Reaper](https://reaper.fm) project for archiving: | ||
|
||
- Scans the project file for all used WAV files | ||
- Converts WAV to FLAC and changes the links in the input RPP file accordingly | ||
- Optionally deletes converted source files | ||
|
||
Only WAV files supported by the `flac` binary can be converted. Currently, this means 32 bit floating point PCM files will be skipped and left uncompressed! | ||
|
||
## Usage | ||
Rearchiver relies on **[Flac](https://xiph.org/flac/download.html)** for conversions, | ||
so the `flac` program must be present in your PATH or placed in the same directory as `rearchiver` executable. | ||
|
||
By default the edited project file is written to the standard output, use redirection or `-o` to write to a file: | ||
|
||
``` | ||
# redirect standard output to a file | ||
> rearchiver INPUT.rpp > output.rpp | ||
# write to a file | ||
> rearchiver INPUT.rpp -o output2.rpp | ||
``` | ||
|
||
Rearchiver is interactive, it will print the pairs of the found WAV files and the proposed names for the FLACs and will ask for your confirmation. Use `-y` to bypass the confirmation. | ||
|
||
Additional options are available in help: `rearchiver --help`. | ||
|
||
## Disclaimer | ||
Rearchiver tries to be conservative and will not overwrite anything unless asked by the user. However, there might be bugs.\ | ||
This software is provided without any guarantees. | ||
|
||
## Installation | ||
Rearchiver is tested to work under Windows and GNU/Linux. Probably works on OSX with no changes. | ||
|
||
Download a binary from the [release assets](https://github.com/indiscipline/rearchiver/releases/latest) or compile yourself. | ||
|
||
### Building manually | ||
Building requires the Nim compiler and a Nim package manager (such as Nimble) to resolve the dependencies. | ||
Third-party libraries Rearchiver relies on: `fusion`, `threading`, `argparse`. | ||
Use `choosenim` to install and manage the Nim compilation toolchain. | ||
|
||
To install with Nimble: | ||
|
||
``` | ||
nimble install https://github.com/indiscipline/rearchiver | ||
rearchiver -h | ||
``` | ||
|
||
## TODO: | ||
- [] Add support for WavPack as an alternative codec / codec supporting 32 bit float WAV files | ||
- [] Migrate to a proper pool for managing concurrent process execution | ||
|
||
## Contributing | ||
The project is open for contributions. Please, try to limit the scope of your changes. | ||
|
||
Open an issue for bugs, ideas and feature requests. | ||
|
||
## License | ||
Rearchiver is licensed under GNU General Public License version 3.0 or later; See `LICENSE.md` for full details. | ||
|
||
[Logo](rearchiver.svg) is licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--mm:arc | ||
--threads:on | ||
|
||
|
||
when defined(release) or defined(danger): | ||
--opt:speed | ||
--passC:"-flto" | ||
--passL:"-flto" | ||
--passL:"-s" |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Cozy Task Pool | ||
|
||
Just a repeating pattern of launching `tasks` concurrently in threads with `threading/channels`, extracted into its own micro package. | ||
Not very ergonomic, just hides some of the boilerplate of preparing and tearing down everything. | ||
|
||
**Requires** `--threads:on` and (`--mm:arc` or `--mm:orc`) | ||
|
||
## Installation | ||
Currently not in nimble directory. | ||
|
||
``` | ||
nimble install https://github.com/indiscipline/cozytaskpool | ||
``` | ||
|
||
## Usage | ||
Look at the executable part of the source, which is almost the copy of the following block: | ||
|
||
```nim | ||
import std/[tasks], threading/channels | ||
var | ||
data = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61] | ||
pool: CozyTaskPool = newTaskPool() | ||
proc log(inputData: int) = | ||
echo "Received some message about ", inputData | ||
proc work(consumer: ptr Chan[Task]; inputData: int) = | ||
doTheWork(inputData) | ||
consumer[].send(toTask( log(inputData) )) | ||
for x in data: | ||
pool.sendTask(toTask( work(pool.resultsAddr(), x) )) | ||
pool.stopPool() | ||
``` | ||
|
||
## License | ||
Cozy Task Pool is licensed under GNU General Public License version 2.0 or later; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
version = "0.1.0" | ||
author = "Kirill I" | ||
description = "Cozy Task pool" | ||
license = "GPL-2.0-or-later" | ||
srcDir = "src" | ||
|
||
|
||
# Dependencies | ||
|
||
requires "nim >= 1.6.12" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import std/[tasks, osproc], threading/channels | ||
|
||
when not defined(gcArc) and not defined(gcOrc) and not defined(nimdoc): | ||
{.error: "This package requires --mm:arc or --mm:orc".} | ||
|
||
type | ||
RunnerArgs = tuple[tasks: ptr Chan[Task], results: ptr Chan[Task]] | ||
ConsumerArgs = tuple[results: ptr Chan[Task], nthreads: Positive] | ||
CozyTaskPool* = object | ||
nthreads: Positive | ||
taskThreads: seq[Thread[RunnerArgs]] | ||
consumerThread: Thread[ConsumerArgs] | ||
tasks: Chan[Task] | ||
results: Chan[Task] | ||
StopFlag = object of CatchableError | ||
|
||
proc stop() = raise newException(StopFlag, "") | ||
|
||
proc runner(args: RunnerArgs) {.thread.} = | ||
var t: Task | ||
while true: | ||
args.tasks[].recv(t) | ||
try: t.invoke() | ||
except StopFlag: break | ||
args.results[].send(toTask(stop())) # notify consumer thread finished | ||
|
||
proc consumer(args: ConsumerArgs) {.thread.} = | ||
var activethreads: Natural = args.nthreads | ||
var t: Task | ||
while activethreads > 0: | ||
args.results[].recv(t) | ||
try: t.invoke() | ||
except StopFlag: dec(activethreads) | ||
|
||
func resultsAddr*(pool: CozyTaskPool): ptr Chan[Task] {.inline.} = | ||
pool.results.addr | ||
|
||
proc sendTask*(pool: var CozyTaskPool; task: sink Task) {.inline.} = | ||
pool.tasks.send(isolate(task)) | ||
|
||
proc newTaskPool*(nthreads: Positive = countProcessors()): CozyTaskPool = | ||
result.nthreads = nthreads | ||
result.taskThreads = newSeq[Thread[RunnerArgs]](nthreads) | ||
result.tasks = newChan[Task]() | ||
result.results = newChan[Task]() | ||
createThread(result.consumerThread, consumer, (result.results.addr, nthreads)) | ||
for ti in 0..high(result.taskThreads): | ||
createThread(result.taskThreads[ti], runner, (result.tasks.addr, result.results.addr)) | ||
result | ||
|
||
proc stopPool*(pool: var CozyTaskPool) = | ||
for _ in pool.taskThreads: pool.tasks.send(toTask(stop())) | ||
joinThreads(pool.taskThreads) | ||
joinThread(pool.consumerThread) | ||
|
||
|
||
when isMainModule: | ||
import std/[tasks, os, unittest], threading/channels | ||
|
||
var | ||
data = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61] | ||
checkset: set[byte] = {1, 2, 4, 6, 10, 12, 16, 18, 22, 28, 30, 36, 40, 42, 46, 52, 58, 60} | ||
results: set[byte] | ||
|
||
suite "Cozy Task Pool test suite": | ||
setup: | ||
var pool: CozyTaskPool = newTaskPool() | ||
|
||
test "Test completion": | ||
proc log(inputData: int) = | ||
results.incl(inputData.byte) | ||
# echo "Received some message about ", inputData | ||
|
||
proc work(consumer: ptr Chan[Task]; inputData: int) = | ||
sleep(100) | ||
let r = inputData - 1 | ||
consumer[].send(toTask( log(r) )) | ||
|
||
for x in data: | ||
pool.sendTask(toTask( work(pool.resultsAddr(), x) )) | ||
|
||
pool.stopPool() | ||
check results == checkset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from std/strformat import `&` | ||
|
||
version = "0.1.0" | ||
author = "Kirill I" | ||
description = "Prepare your Reaper project for archiving, converting WAV to FLAC and changing the RPP file accordingly" | ||
license = "GPL-3.0-or-later" | ||
srcDir = "src" | ||
bin = @["rearchiver"] | ||
|
||
|
||
# Dependencies | ||
|
||
requires "nim >= 1.6.6", "argparse >= 3.0.0", "fusion >= 1.1", "threading >= 0.1.0" | ||
|
||
task release, "Build release": | ||
let binName = bin[0] & (when defined(windows): ".exe" else: "") | ||
exec(&"nim c --define:release --out:{binName} src/{bin[0]}.nim") |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.