# About In C, [libcdio](https://www.gnu.org/software/libcdio/) provides a widely-ported and highly-usable library for retrieving data from CDs (and disc images). This is an area which Haskell has thus far been lacking a solution for; while modern technology has admittedly been moving away from discs in favour of downloading files over the internet, there is still some utility in the medium for any programmers whose projects might involve external storage (note, however, that `libcdio` only allows /reading/ discs, and leaves /authoring/ to other libraries). While the majority of the core library has been translated, many supplemental headers (MMC commands, CD-Paranoia, etc.) are not yet available; for the current progress see the [FEATURES](./FEATURES) file and the [ROADMAP](./ROADMAP.md) for the rough order in which those are planned to be developed, and please do report any bugs you find (or even fix them yourself!) # License The original `libcdio` is licensed under the GPL, and these bindings, of course, follow suit. If you do use this in your own project, therefore, you are subject to the ambiguity of whether linking to a GPL library then requires your own code to also be released under the GPL. Look elsewhere for a full discussion on what arguments are given in that debate, but in short, the GPL says that "a work based on the Program" must *also* be released under the GPL. To err on the side of caution, if you use this library, release your code under the GPL. To do otherwise is to take a firm stance against the linking argument at best, violate the copyright at worst, and make GPL proponents angry at you either way. # Installation ## Requirements As with nearly every Haskell project, the `.cabal` file maintains the list of dependencies, and that should be taken as authoritative over anywhere else except Hackage revisions, and I'll try to keep the code up to date with those. Notably, the actual core of this package is the C `libcdio` library. All bindings should fail gracefully for any version within the supported range, and so should be safe to call blindly, but this is accomplished via preprocessor commands, and so *this package must be recompiled whenever the base libcdio version changes*. Minor version bumps to the underlying library (and certainly patch releases) should still run safely after being recompiled, but there may be some unexpected behaviour: version 2.1 added a few meta-values to the `Language` enum, for example, at values greater than 255, while the previous maximum value was below that. It is possible for a C compiler to have used a byte representation for <2.1 and a larger one for >=2.1; something like that could *possibly* result in things being set at/referenced from the wrong memory offset. * libcdio: >= 0.93 && < 2.2 * c2hs: >= 0.26 * ghc: >= 8.0 ## c2hs + ghc Some parts of the bindings have been written for the `c2hs` preprocessor, and while manual compilation is technically possible, it's much more involved than necessary. Instead, just use `cabal-install` or `stack` as usual. If you really do have to invoke `gcc` manually, however, run that preprocessor first: c2hs --cppopts=-E --cppopts=-Iinclude/ --include=.../ src/Foreign/Libcdio/Types/Enums.chs c2hs --cppopts=-E --cppopts=-Iinclude/ --include=.../ src/Foreign/Libcdio/Types/Offsets.chs # Usage The original implementation revolves around a classically-C architecture of threading a mutable (though opaque) pointer through through many function calls. For those used to that or who are following pre-existing guides, a set of low-level bindings mirroring that architecture may be found under the "Foreign.Libcdio" tree; for anyone used to Haskell, the monadic bindings under "Sound.Libcdio" are recommended instead. A lookup table for translating existing code and/or knowledge into each progressively higher-level interface is provided in the documentation of the `Foreign.Libcdio.*` modules. As a general rule, any project should /only/ import modules from a single set of bindings, not both, as while the datatypes can frequently be passed between them, several function names have been reused and so may collide. # Contributing I welcome any patches, whether for bug fixes, new features, or anything else. If you just want to point out a bug or ask for some yet-unmentioned feature, I maintain that list in [ISSUES](./ISSUES/); see the [README](./ISSUES/README.md) in that directory for the format if you want to submit something in a more complete form or contribute to any ongoing discussion, but otherwise feel free to simply [email me](mailto:ag@eitilt.life) and I'll wrangle it into the right form. If you decide to contribute yourself, please enable the `dev` build flag. For the moment, it just enables all warnings I want to enforce in the code, but it might provide other aids in the future as well. I've avoided enabling them during everyday building as while an end user seeing a warning *might* feel inclined to fix the program, chances are it's just going to be ignored as the list of built files scrolls by. cabal configure -fdev Depending on the size of your hack, I welcome either a diff file, or you can bundle your complete darcs patches with `darcs send`. Either way, attach the changes to an email addressed to ag@eitilt.life and I'll see about adding it to the codebase. ## Patch format If you do send the latter, every patch should have a comment with a (at least mildly) descriptive name prefixed with a tag indicating the general category addressed by the patch: for fixing issues, that is an "i/" followed by the issue number (padded with leading zeros to three digits); for general development, "f/" followed by the best topic in the `FEATURES` key; for completeness, version tags are "v/" followed by the package reference followed by the version. All are terminated with a final period. Please do not squash patches. Each patch should represent a minimal but complete change: certainly enough context to successfully compile, hopefully enough context to not break any previously-passing tests, and potentially combining closely-related changes at your discretion, but if you wind up trying to decide between multiple tags or you're adding all of your work over the entire day, you should probably look closely at whether you can break the patch apart any farther. Additionally, make good use of the `--ask-deps` flag. Until I get a CI integration together, it's easy to miss a dependency, but do your best to select anything which your patch may require to build successfully.