Logo


↩ Back to Developer Documentation



Coding Style

Please follow the following rough rules when submitting code for inclusion in PA or committing code into Git. Although this list might appear massive I am still quite liberal in accepting patches that do not follow these rules. OTOH I am not your reindenting monkey, so please follow them, especially if your submissions are non-trivial!

  • No tabs please! Please indent exclusively with spaces.
  • Indentation is 4 characters.
  • Please keep the opening bracket of a block on the same line as the expression opening it. i.e. This is correct:

    void good_function(void) {
        if (a) {
            printf("Hello World!\n");
            a = 0;
        }
    }
    

    And this is wrong:

    void bad_function(void)
    {
        if (a)
        {
            printf("Hello World!\n");
            a = 0;
        }
    }
    
  • Avoid unnecessary curly braces on one-line code blocks. Good code:

    if (!braces_needed)
        printf("This is compact and neat.\n");
    

    Bad code:

    if (!braces_needed) {
        printf("This is superfluous and noisy.\n");
    }
    

    This applies also if only one of the if-else branches have an one-line code block. Good code:

    if (!braces_needed)
        printf("This is compact and neat.\n");
    else {
        printf("Hello World!\n");
        a = 0;
    }
    

    However, braces are welcome if there are multiple lines in a code block, even if the braces aren't technically necessary. Good code:

    if (a) {
        /* Imagine this comment explains something about using do_something(). */
        do_something(a);
    }
    

    Also good code:

    if (a) {
        do_something(a, "This function call is split to two lines, because it's long. Other reasons: %s and %s",
                     one_reason, another_reason);
    }
    
  • Don't put the return type of a function on a separate line. This is good:

    int good_function(void) {
    }
    

    and this is bad:

    int
    bad_function(void) {
    }
    
  • On function calls and definitions, don't put an extra space between the function name and the opening parenthesis of the argument list. This good:

    double sin(double x);
    

    This bad:

    double sin (double x);
    
  • Exported function names should be prefixed with pa_. Static definitions should not be prefixed. Exported structs should be typedef'ed so they can be used without typing "struct" each time. Structs that are used only inside a single source file should not be typedef'ed that way.

  • Keep private functions private! Make them static!

  • Data types that are usually passed as call-by-value arguments should be suffixed with _t with a typedef. I.e. all enums should be suffixed like this:

    typedef enum pa_resample_method {
      /* ... */
    } pa_resample_method_t;
    
  • No C++ comments please! i.e. this is good:

    /* This is a good comment */
    

    and this is bad:

    // This is a bad comment
    

    Yes, the newest C iterations allow those comments. But they are ugly.

  • Comments are good, use them wherever it makes sense. Excessive comments are bad. i.e. comment complicated code, don't comment trivial code. For hackers it's usually easier to understand well written code than prose. Use doxygen only for exported APIs, not for internal code.

  • Code is about aesthetics. So please, format you code cleanly.

  • Please do not wrap your lines at 80 characters. Given that most screens are now considerably wider than they used to be, please make use of it. Wrap them at 128 characters. An exception: comments, especially multi-line comments, should be wrapped at 80 characters.

    When a function declaration exceeds 128 charactes and wrapping is needed, please wrap the parameters using this style:

    pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device *d, const char *owner, const char *path,
                                                       pa_bluetooth_profile_t p, const uint8_t *config, size_t size) {
        ...
    }
    

    That is, wrap at 128 characters, and start the new line aligned with the opening parenthesis.

  • Please check parameters on each function call. Use pa_assert() when checking parameters which are -- when wrong -- most likely programming errors in PA. For bad parameters that are not necessarily programming errors, or which might be programming errors outside of PA, return with an error code. Please add a separate pa_assert() for each argument. Do not use a single check for all parameters using &&. This would make debugging more difficult. Good code:

    void good_code(int a, int b) {
        pa_assert(a > 47);
        pa_assert(b != 0);
    
    
    
    /* ... */
    
    }

    Bad code:

    void bad_code(int a, int b) {
        pa_assert(a > 47 && b != 0);
    
    
    }
    
  • Errors are returned from functions as negative values. Success is returned as 0 or positive value.

  • Check for error codes on every system call, and every external library call. If you you are sure that calls like that cannot return an error, make that clear by wrapping it in pa_assert_se(). i.e.:

    pa_assert_se(close(fd) == 0);
    

    Please note that pa_assert_se() is identical to pa_assert(), except that it is not optimized away if NDEBUG is defined. (se stands for side effect)

  • Every .c file should have a matching .h file (exceptions allowed)

  • In .c files we include .h files whose definitions we make use of with #include <>. Header files which we implement are to be included with #include "".

  • If #include <> is used the full path to the file relative to src/ should be used.

  • Please submit code only under LGPL2+, BSD/MIT or GPL2+, but don't make GPL code a hard dependency. Since PA is pluggable this would make it it impossible to load less-free-than-GPL code into the PA daemon.

  • Booleans: Use int as the boolean type in public APIs. Internally, use bool from stdbool.h.

Yes, not all code that is part of PA right now follows these rules closely. This is mostly due to the fact that the formalization of these rules is newer then most of the code itself.


Localization

We have some rules for deciding whether a log message should be localized or not (again, the existing code base is mostly older than the rules, so there are a lot of places where the rules are not followed). From a message on the mailing list:

A few of us had an IRC conversation about whether or not to localise PulseAudio's log messages. The suggestion/outcome is to add localisation only if all of the following points are fulfilled:

  1. The message is of type "warning" or "error". (Debug and info levels are seldom exposed to end users.)

  2. The translator is likely to understand the sentence. (Otherwise we'll have a useless translation anyway.)

  3. It's at least remotely likely that someone will ever encounter it. (Otherwise we're just wasting translator's time.)

  4. The user is likely to be able to help himself, or at least be informed, after having read the message.

Example:

  • pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n" (etc)

    The above can remain localised.

  • pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));

    The above should NOT be localised (fails both 2, 3, and 4.)

  • pa_log_info(_("Fresh high-resolution timers available! Bon appetit!"));

    The above should be changed to NOT be localised. (fails at least 1. Maybe also 2 and 4.)


Indentation in Emacs

If you use Emacs, consider using this Elisp function for proper indentation:

(defun my-c-mode()
 "Lennart Poettering's C indentation"
 (message "Setting Lennart Poettering's C indentation...")
 (c-set-offset 'substatement-open 0)
 (c-set-offset 'statement-case-open 0)
 (c-set-offset 'case-label '+)
 (c-set-offset 'arglist-intro '++)
 (c-set-offset 'arglist-close 0)
 (define-key c-mode-base-map "\C-m" 'c-context-line-break)
 (setq tab-width 8)
 (setq c-basic-offset 4)
 (c-toggle-hungry-state 1)
 (setq indent-tabs-mode nil))