Developing pianod2 Summary: Instructions for setting up a pianod2 development area. Index: pianod, setting up a development environment
Developing pianod2
This file is intentionally not included with releases. It is only available from the pianod2 SVN respository.
This file outlines creating a development area for pianod2. If you just want to install pianod2, download a tarball and see the INSTALL file instead.
Setting Up
Prerequisites
- make
- C, C++ compilers; also Objective C compiler if on OS X/macOS
- m4
- automake, autoconf, and Perl
- Node.js (nodejs and npm (node package manager))
- ksh (the genuine article, not pdksh; ideally ksh’93)
- Java (ugh, I know, but Validator.nu is written in it.)
- HTML Tidy (a recent one–I have 5.7.3. The 2009 versions supplied by some package managers won’t cut it.)
Installing Components
Install Node.js modules:
# Typescript compiler
sudo npm install -g typescript
# Type definitions are used by the TypeScript compiler to
# validate the code.
# Note: Currently we require @types/jquery v. 2.0.39 (look in the
# package.json file for the version number). There's an issue
# with JQuery trying to use `Iterable<type>`, but not knowing what
# `Iterable<>` is. There are 101 answers on the web for this,
# all different. If someone wants to look into this, it would be
# great. I think we may need a `--lib` when compiling, but I'm
# unclear exactly what it wants. Until fixed, we're out of
# luck on the tightened-up v. 3.2+ jquery definitions.
sudo npm install -g @types/jquery@2.0.39
sudo npm install -g @types/assert
sudo npm install -g @types/node
# These next node things perform required transforms.
sudo npm install -g browserify
sudo npm install -g browserify-shim
# Currently not using unassertify; doesn't work right.
# If we ever fix it: sudo npm install -g unassertify
sudo npm install -g uglify-js
# Install Validator.nu HTML validator
sudo npm install -g vnu-jar
As a bonus, browserify
installs itself with a
shebang of #!/usr/bin/env node
, even though
node
switched to nodejs
years ago to
avoid a naming collision with other packages. Depending on your
installation, you may need to change it to #!/usr/bin/env
nodejs
. (Goddess I hate depending on Node.js!)
Note: In the future, you can update your nodejs
installation by sudo npm update -g
. Note, however,
this might update and break the JQuery types if we haven’t
solved that yet.
Setting up a build area
Get the source code from SVN. If you’re just submitting minor fixes, you may work directly on the trunk.
svn co svn://svn.deviousfish.com/trunk your_local_dirname
If you’re working on something large, like a new source, please create a branch and we’ll integrate it back into the trunk when it’s ready.
svn copy svn://svn.deviousfish.com/trunk svn://svn.deviousfish.com/branches/name_feature
svn co svn://svn.deviousfish.com/branches/name_feature your_local_dirname
To prepare the directory for use:
autoreconf -i
./configure --enable-debug [insert your configure options here]
Before proceding, check that configure is building with what you expect. Add packages or switches as necessary.
make
make check
Running make check
is especially important as a
developer: you don’t want to troubleshoot your code trying to
find something that was already broken.
Integration test Suite
You can run the test suite directly:
./pianod_unittest
There are 5 environment variables used by the unit test script for audio output settings, should the default outputs not be right:
- PIANOD_UNITTEST_AUDIO_LIBRARY
- PIANOD_UNITTEST_AUDIO_DRIVER
- PIANOD_UNITTEST_AUDIO_ID
- PIANOD_UNITTEST_AUDIO_OPTIONS
- PIANOD_UNITTEST_AUDIO_SERVER
To add tests, follow the formula of the
test_something
functions. The driver loop uses
introspection find and execute all tests, and report the the
results.
Session and daemon transcripts are reported when failures are
encountered, or when the -v
option is given.
Manual testing
The executable is in the src
directory. It expects
the client to be in its installed location (often
/usr/local/share/pianod/html
). Use the -c option point
it to your build area:
src/pianod -c `pwd`/html
Submitting code
You’ll need commit rights. Mail a preferred username & password to perette@deviousfish.com.
Before committing code to the trunk, notify us what’s
coming on the pianod mailing list. For small things, include the
patch (from svn diff
). svn
may force you
to update before commit: svn update
. In the unlikely
event of conflicts with other changes, you’ll need to resolve
them. When ready: svn commit
.
For larger changes, commit the changes to your branch, then notify the mailing list the branch is ready for review. Once a second pair of eyes has reviewed it, it will be reintegrated into the trunk. Do not use the branch for futher work except bug fixes prior to reintegration; after reintegration, the branch is deleted. Create a new branch from the trunk if required.
About The Code
The Daemon
The daemon is found in the src
directory.
libfootball
, in C99, is the communication layer code.mediaunits/audio
contains the bridges to various audo decoding and audio output code.mediaunits/metadata
contains the bridges to various tag/ID3 extracting code.- The rest of the
mediaunits
directories are the sources. mediaunits/sources.cpp
provides source registration at startup.
Coding Standards
Write good code. Don’t just write the expected case; think
about what can go wrong, and ensure it’ll be handled
correctly. Test your stuff, and run it through
valgrind
. Add test cases where possible.
Use assertions to check expectations and enforce contracts.
Take time to pick clear variable and function names. Although it’s said the length of a name is proportional to its scope, that doesn’t excuse many 1-letter names. Use names that provide context to the next guy.
Use const
or its equivalent whenever you can.
Do not use “Hungarian notation.”
If you encounter a piece of code that doesn’t follow the standards here, use your judgement. If you’re only making small revisions, it may be better to follow the existing style. If the out-of-policy parts are small, consider conforming them.
C99
Use all_lowercase_snake_case for function_names, variables (both global and automatic), and parameter_names.
typedefs
prefer LeadingCapital CamelCase.
When creating a typedef for a struct or union, assign the struct an all-underscore name ending with _t (some compilers yield better warnings):
typedef struct my_struct_t {
int my_field;
} MyStruct;
enum
values should USE ALL CAPS. (But prefer C++
enum classes, mentioned below).
C++14
If you’re new to C++, bone up on RAII. It’s really important.
Non-class functions, and static class members, all variables and all parameters should use all lowercase snake_case.
Use enum class
instead of old-style
enum
. The enumeration type name should be
LeadingCapital CamelCase. Enumeration values should be ALL CAPITAL,
although CamelCase is acceptable.
Namespace, class, structure, and template names should use LeadingCapital CamelCase.
Use operator overloading with care: use it where appropriate, but don’t go crazy; it can make code illegible. If having both forms (operator and function) make the code more legible, depending on context, considering defining one as an inline function wrapping the other.
Google hard, but ask questions when you need. Study the issue so you can ask the question effective. And don’t be offended when asked a question. Take the time to answer well; half-assed answers are a waste of your time, that of the person you are responding to, and anyone listening in to the conversation.
Read that last one again, because crappy questions cause answer apathy, which disincents us from asking useful ones. Let’s not go down that path, and instead communicate effectively. It makes it funner for all of us.
Code Formatting
Please try to follow the existing style. Use:
- attached opening braces (aspell: –style=attached), not on a separate line.
- Braces:
- go on the same line as whatever they are defining/structuring.
(aspell: –style-attached) Exception: when a
case
needs braces, they go on the next line. - are optional in loops and
if
s, but if any case of anif
requires braces, wrap all of them. - should be used when encompasing another conditional/loop.
- the closing brace goes on its own line
- go on the same line as whatever they are defining/structuring.
(aspell: –style-attached) Exception: when a
- Spaces:
- are used for indentation, not tabs (–indent=spaces=4).
- are placed around infix operators (but not prefix/postfix).
- are included after function names in calls, declarations and definitions.
- Indent:
- Four spaces per level.
- For now, the bodies of namespaces are indented. (–indent-namespaces)
- Case labels are indented 4 spaces, with their statements
indented 4 more spaces (–indent-switches). (If case bodies
require braces, these go on the same line as the
case
).
- For multi-line statements:
- indent continued conditionals a little more than the subsequent body to create a distinction (–min-conditional-indent=8).
- indent continued assignments to the characters 1 space past =, to align with the assigned value. Alternately, if the assigned value is a function call, align parameters with its parentheses (below).
- indent continued function call parameters with the right side of the open-parenthesis. (–max-continuation-indent=40)
Screens are big now, so don’t spare the whitespace if it helps legibility or comprehension. Try to keep things uniform, but use good judgement; if there’s a good reason to break from the usual style, that’s okay.
The Clients
The client, console, and viewer are in the html
subdirectory, with 3 branches off that: pages (the HTML source),
locale (text for various languages), and scripts (client-side
TypeScript and JavaScript).
pages
There are 3 .web files, one for each client: client, console,
and viewer. The console and viewer are self-contained. To keep
things manageable, each of the client’s panes has its own
.m4
source file; index.web
pulls these in
to assemble the completed client.
Clients can be compiled in regular mode and compressed mode. In regular mode, clients reference their supporting JavaScript libraries in the scripts directory, and expect a local JQuery. In compressed mode, JavaScript libraries are expected to be co-located in the directory with the HTML, and a Google-hosted JQuery is used.
Page compilation happens in 3 phases:
- Use
m4
to convert source to HTML. - Use
tidy
to clean up the results. - Validate the resulting HTML.
If successful, the resulting page is technically valid but
filled with language keys. These are replaced by the Makefiles in
locale
.
locale
Contains the language-specific text for the clients. Each
language has a phrases.<language>.lang
file with
key-to-text dictionary such as:
HEADING_ACTION Actions
PROMPT_CONFIRM_DELETE Are you sure you want to delete %1$s?
PIANOD_LICENSE Released under the MIT license.
The locale Makefile
uses m4
to
substitute the keys into the client HTML in the pages
directory.
There is also a translate.js.m4 file. It contains a list of the
translation keys utilized by client’s JavaScript using JSON
notation. The Makefile uses m4
to insert keys, create
language-specific translate.js
files.
scripts
The client scripts are mostly written in TypeScript, which is
transpiled into JavaScript. TypeScript has a cleaner syntax, and in
the compilation process, the typescript compiler tsc
gives lots of lovely warnings and errors when we mere humans try to
do something stupid.
communication.ts
contains the protocol code used by all clients.console.ts
andviewer.ts
are for the respective clients.view.ts
andcomm.ts
provide infrastructure for the main client views.tableview.js
provides infrastructure for a few of the views.ratings.js
contains code for the client’s star ratings widget.- The rest of the files correspond to each pane/view in the client.
Functions are documented with docucomments in the manner of the daemon.
miniscripts
When making the clients for distribution, a fourth directory is
created. miniscripts
contains a copy of
scripts
, but with assertions stripped from the code.
This is recompiled, and the resulting code copied into the parent
html
directory.
miniscripts
is removed by make
clean
.