Skip to content
Tobias Blomberg edited this page Aug 2, 2014 · 20 revisions

Contributing to the SvxLink project

There are a lot of ways in which you can contribute to the SvxLink project. Even if you are not a programmer, you can still contribute other things.

Contributing documentation

If you want to contribute documentation to this wiki, just start typing. The Wiki is open for all logged in GitHub users to write in.

Qtel language translation

Creating a translation to another language for Qtel is rather simple. First you should install the software used for doing the translation. It is called Qt Linguist. In Fedora 20, for example, the package containing this utility is called qt-devel. Then you need to get hold of a file containing the text strings that should be translated. The easiest way to do this is to download the latest template file directly from this link: https://github.com/sm0svx/svxlink/raw/master/src/qtel/translations/qtel_tmpl.ts. Rename the downloaded template file, replacing "tmpl" with your ISO 639 language code. The language code consists of two or three letters (e.g. sv=Swedish, en=English). If you are not sure what your language code is, have a look on this page for example: http://www.loc.gov/standards/iso639-2/php/code_list.php. Use the two letter variant if available.

Now either start Qt Linguist from the menu 'Development/Qt4 Linguist' and open the template file or launch it directly on the command line with:

linguist qtel_xx.ts

Start translating! Help on using Qt Linguist is available inside that application so I won’t repeat any of it here.

When you are done, compress the file (e.g. gzip qtel_xx.ts) and send it to the svxlink-devel@lists.sourceforge.net mailing list.

Language translations already available are: German (de), Spanish (es), Hungarian (hu), Russian (ru), Swedish (sv), Turkish (tr), Ukrainian (uk), Italian (it), Dutch (nl), French (fr), Hungarian (hu) and Japanese (ja).

SvxLink Server language translation

The SvxLink Server application use sound clips to play back announcements. These are small sound clips that may range from part of a word to full help messages with multiple sentences. The default language used in SvxLink is US English so using that setup as a template is a good start. The end result after completing the steps below should be an archive containing sound clips and possibly some language specific TCL script adaptions. This is called a "language pack". More on the TCL script adaptions below.

Setting up the build environment

Start by setting up a build directory for the sounds and cd into it.

mkdir sounds
cd sounds

Prepare the build environment by getting hold of the build scripts that are used to build the final sound clips. If you already have a checked out source tree the best way may be to softlink to the script files which can be found under 'src/svxlink/scripts/'. Another way is to get them directly from Git.

wget https://raw.githubusercontent.com/sm0svx/svxlink/master/src/svxlink/scripts/play_sound.sh
wget https://raw.githubusercontent.com/sm0svx/svxlink/master/src/svxlink/scripts/filter_sounds.sh

Make sure that the 'sox' utility is installed on the system since that is used to process the sound clips.

Set up a language pack template directory

Now decide what your directory for this translation should be called. The directory should be named "orig-ll_LL-name" where "ll" and "LL" should be replaced with the ISO language codes (e.g. sv_SE for Swedish) and name should be replaced with the voice name. The word "orig" should not be replaced since it just signifies that this is the original, unprocessed sound clip files. The default voice is called en_US-heather since it’s US English and the voice is called Heather. To get a template to start from we now use the en_US-heather directory. This is most easily obtained using Subversion to get the latest version.

svn export https://github.com/sm0svx/svxlink/trunk/src/svxlink/scripts/sounds/en_US-heather orig-ll_LL-name

The orig-ll_LL-name directory now created should contain a base structure, configuration files and text files. The text files are the text representation used to generate a specific sound clip. Either keep them as a reference or remove them. If kept, they should be edited to reflect the language that the language pack is being created for.

Creating the clips

Now comes the hard part, which is generating all the sound clips. The preferred way to generate sound clips is to use the online service at Acapela Box. The service is not free but generate good quality sound clips in a lot of languages. Using a publicly available service is good since other people may want to generate additional sound clips for a specific installation and then it’s easy to get the same voice. There are lots of other commercial text to speech applications but the license on the generated sound clips may make it illegal to release the clips publicly. There are also a number of free text to speech applications but I have so far not found one that is good enough. Of course it’s also possible to use your own voice to record the sound clips but then only you can generate new sound clips with the same voice. The sampling rate for the sound clips should be at least 16kHz. If possible use an even higher sampling rate, like 48kHz, to get the highest quality in the originals. A script will be used later to convert the sampling rate to the one SvxLink is using.

So what sound clips should be generated then? In each subdirectory under orig-ll_LL-name you will find a configuration file called 'subdir.cfg'. In this file you can find a list of file names for all sound clips that need to be generated for this subdirectory. The file contains three configuration variables. The two that is of interest right now is MAXIMIZE_SOUNDS and TRIM_SOUNDS. For each listed sound clip name, a corresponding wav file should be created that is named clipname.wav (e.g. help.wav, press_0_for_help.wav etc). Another way of finding out which clips to generate is to use the text files mentioned above. Simply generate a sound clip with the same name as the text file. For example, if there is a text file called help.txt, a file named help.wav should be created. What content the sound clip should have can be found out by looking at the content of the text file. Note that the text in some text files have been misspelled on purpose to force the text to speech system to generate the correct pronunciation.

A good tip is to start small and try the whole process of generating the final sound clips before going ahead and create all clips. Start with the clips is the Core subdirectory, the first one being "online". That clip should contain the translation of "SvxLink online".

Run the filter script

The script 'filter_sounds.sh' is used to filter the sound clips to enhance them further. For example, the clips are maximized in level and silence is trimmed at the beginning and end to get them tighter together. The script use some configuration files. Directly under the orig-ll_LL-name directory there is a configuration file called 'filter_sounds.cfg'. At this moment we’re only interested in the SUBDIRS configuration variable. Comment out the original lines and set SUBDIRS="Core". This will make the script only process the Core directory. If we don’t do this, an error message will be printed for each missing file and there will be a lot of them. Now we can try to run the script. You should stand in the same directory as where the script is located. This should be the "sounds" directory, that is the directory above the orig-ll_LL-name directory, if this instruction have been followed correctly. Now run the following.

./filter_sounds.sh orig-ll_LL-name ll_LL-name-16k

This will process the files under the orig-ll_LL-name directory and put them in the ll_LL-name-16k directory. The latter directory will contain the end product, the files that SvxLink can use. A warning will be printed for each missing file. The default sampling rate for the generated sound clips is 16kHz, hence the directory name suffix for the target directory. The filter_sounds.sh script can also generate 8k sound clips if that is needed. Add the "-r 8000" command line switch to the command to achieve that. Remember to rename the target directory.

A tar archive will also be created with the contents in the target directory. It will be named sounds-ll_LL-name-16k.tar.bz2.

To try your language pack in SvxLink, unpack the generated tar archive in the sounds directory configured in SvxLink. See the InstallationInstructions for how to do that. Set the DEFAULT_LANG configuration variable in svxlink.conf to match the language code for the generated language pack. If you only generated the 'online.wav' clip you can trigger a manual identification (*) to make it use that clip. Missing sound clips will be printed out.

If everything seem to work, start creating the rest of the sound clips. The most important subdirectories are "Core" and "Default". Then there is one subdirectory for each SvxLink module. If it is desirable to tweak the quality of the sound in some way that is done in the filter_sounds.cfg file. Read the comments above the configuration variables to understand what they do. To choose which sound clips that should be created, edit the subdir.cfg file in each subdirectory. There may be clips that are unnecessary for a certain language and to suppress the error printout they should be removed from the subdir.cfg file.

Adapting the TCL scripts

Not all languages have the same word ordering as English have. In this case the TCL scripts, that decide in which order sound clips should be played, have to be modified for correct word ordering. Frequent candidates for differences is when announcing time and numbers. Time and numbers are handled in the file locale.tcl which can be found under the /usr/share/svxlink/events.d directory on a standard installed SvxLink system. Create a events.d directory in the orig-ll_LL-name directory and copy the locale.tcl file there. Then modify it for correct word ordering. If you don’t know how to do this, request help on the svxlink-devel mailing list. The events.d directory will be copied to the target directory by the filter_sounds.sh script.

Contributing code

Code contributions are welcome. Just make sure to follow the instructions on this page in detail. Any deviation from the instructions mean more job for me or if it’s really bad the contribution will not be accepted until fixed.

One mistake open source contributers do is to confuse "contribution" with "help". Not all contributions actually help since there very often is a fair amount of work to go through a patch. If the contribution is of low priority for the project maintainer, expect the process to take a lot of time.

All new features should be developed using the latest code from Git. The forking workflow should be used on GitHub to contribute to the project.

GitHub praparations

To be able to contribute you must have a GitHub account. Head over to GitHub to create an account if you don’t already have one.

Then you need to configure git locally on your system. The documentation at GitHub says it all so there is no meaning in repeating it here

The forking workflow

The first step in contributing to SvxLink is to create a fork of the SvxLink Git repository. Creating a fork means that you get your own repository of SvxLink that is connected to your GitHub user account.

Next clone your fork. Cloning in Git will get you a local copy of the repository on your harddrive.

$ git clone git@github.com:USERNAME/svxlink.git
Cloning into 'svxlink'...
remote: Reusing existing pack: 20471, done.
remote: Total 20471 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (20471/20471), 4.69 MiB | 745.00 KiB/s, done.
Resolving deltas: 100% (13624/13624), done.
Checking connectivity... done.
$ cd svxlink

The new clone will be associated with your fork on GitHub. This is called the origin. We will also need to associate it with the original SvxLink repository. That is called the upstream repository.

git remote add upstream https://github.com/sm0svx/svxlink.git

The main branch in Git is called "master". Never change anything without first creating a branch. Contributions directly from the master branch will not be accepted. Also, never use a branch to implement more than one feature. A branch that contains multiple feature changes will not be accepted into the SvxLink core distribution.

$ git checkout -b my_new_feature master
Switched to a new branch 'my_new_feature'

You can verify that you are on the correct branch using the following command.

$ git branch
  master
* my_new_feature

To get the status of the whole tree, use:

$ git status
On branch my_new_feature
nothing to commit, working directory clean

Now you can start developing the new feature. Committing changes in Git is a two step process. First both new and changed files will have to be added to something called the index or staging area. It’s the files added to the index that will later be comitted. In this example the INSTALL file have been changed and a README file have been added. Using the status command will look like this:

$ git status
On branch my_new_feature
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   INSTALL

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        README

no changes added to commit (use "git add" and/or "git commit -a")

Let’s say we want to commit both these files. We then use the add command:

$ git add INSTALL README

Now the status will look like this:

$ git status
On branch my_new_feature
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   INSTALL
        new file:   README

Before committing it’s always good to check what we are actually going to commit. That can be done using the git diff command. The "--cached" command line argument will tell git to do the diff against the staged files that we added above.

$ git diff --cached
diff --git a/INSTALL b/INSTALL
index f06d5fc..a2c38e5 100644
--- a/INSTALL
+++ b/INSTALL
@@ -42,3 +42,5 @@ command line switch are:

 For more detailed information, see http://www.svxlink.org/

+Added some information to the INSTALL file...
+
diff --git a/README b/README
new file mode 100644
index 0000000..92e04e7
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+This is a shiny new README file.

If everything looks good we can now commit the changes. Make sure to write a good comment that properly describe what has been changed.

$ git commit
[my_new_feature ffdd69b] Added some information to the INSTALL and README files
 2 files changed, 3 insertions(+)
 create mode 100644 README

Now this is only committed locally. Nothing has been sent to GitHub yet. This is good since it’s possible to use the full power of Git even if no network is available. Also it’s possible to discard the whole branch if it did not turn out to be useful and no trance will be left of it. It’s also possible to undo/change the commit if something went wrong with a specific commit. A tip is to commit often to avoid large diffs.

To publish this branch on GitHub, use the following command the first time:

$ git push -u origin my_new_feature
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 406 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To git@github.com:USERNAME/svxlink
 * [new branch]      my_new_feature -> my_new_feature
Branch my_new_feature set up to track remote branch my_new_feature from origin.

On the following pushes, just use:

$ git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 370 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:USERNAME/svxlink
   671b23a..8b3c43a  my_new_feature -> my_new_feature

After a commit has been pushed to GitHub it must not be changed. That will cause confusion for other users possibly using your repository. It is possible to do but should be done with great care after reading all the proper documentation so that all side-effects are well understood.

When you are done with your branch and want to contribute it back to the SvxLink main distribution, go to the GitHub web page for your repository. There you will find your recently pushed branches and a button next to it saying "Compare & pull request". Push that button to start creating a pull request. Enter detailed information describing the changes. A notification will now be sent to the original repository owner and the changes can be discussed in the pull request (PR). Changes can be done to the branch until its quality is satisfactory. The original repository owner can now merge the branch into the main SvxLink distribution.

When the PR has been accepted and fully merged, pull the changes from the original SvxLink repository and look it over so that everything look good.

$ git checkout master
Switched to branch 'master'
$ git fetch upstream
$ git merge upstream/master

If it looks good, the branch can now be deleted. That have to be done both on GitHub and locally. On GitHub there is a button to press at the end of the PR. Locally, delete the branch using the following command:

$ git branch -d my_new_feature
Deleted branch my_new_feature (was ce2b61e).

Also read the documentation on GitHub for how to contribute to a project.

Keeping a branch up-to-date with master

If a branch live for a long time it will deviate from the master branch. The bigger the deviation, the harder it will be to merge. This is a good reason to keep branches up-to-date with the master branch. There are a couple of ways of doing this, rebase and merge. Rebase should not be used if a branch has already been pushed to GitHub so merge is the safe thing to do.

$ git checkout master
$ git fetch upstream
$ git merge upstream/master
$ git checkout my_new_feature
$ git merge master

Coding Guidelines

Here are some guidelines for contributing code to SvxLink. If these are not followed it will take me longer to accept the patch and if it’s really bad it will be rejected all together.

  • Before putting in a lot of time to code a feature, send an e-mail to the svxlink-devel mailing list to see if someone else is working on something similar and that what you are about to do is in compliance with the architecture in SvxLink.

  • Stick to the coding standards. Just look at existing code and do the same. Examples:

    • Never ever change the TAB size in your editor. It should always be eight characters wide.

    • Indentation should be two spaces.

    • No single line of code should exceed 80 characters unless it is impossible to break it up.

    • Variables are always in small caps. Words should be separated using underscore (e.g. my_variable)

    • Member variables may be prefixed with "m_" to distinguish them from other variables (e.g. m_my_member_variable).

    • Type and class definitions are written in upper camel case (e.g. MyClass)

    • Member and class functions are written in lower camel case (e.g. myFunction)

    • Macros and static constants are written in all upper case (e.g. MY_CONSTANT)

  • Update the appropriate manual page if you have added a new feature.

  • Try to keep branches as clean as possible. One branch should contain one new feature, if possible. Try to avoid lumping a lot of new features into one "personal" branch. The risk here is that the branch will grow larger while new features are added but not finished. Creating separate branches for each feature will encourage finishing implementing a feature so that it can be merged to git master and then merged into other branches that need it.

  • You are responsible for keeping your branches in sync with git master. This is to make later merging easier and of course so that you get the latest features into the branches. It’s pretty easy to do as well unless lots of changes conflict. Then it can be a bit of a pain. This should not be a big problem unless we start to have a lot of overlapping features being developed at the same time.

  • All checkins should have a meaningful comment. This is very important. The checkin comment will be shown on the "GitHub Commits" page so it serves as information to other users of what is going on. It is also very important to have a good comment if one want to go back to check when something specific was changed. Maybe a bug was introduced at some point. It will be easier to find if a good comment is used.

  • Try to check stuff in together that belong together in one go. Don’t check it in file by file.

  • Don’t check multiple changes in together that don’t directly belong together. One may later want to remove something that was checked in earlier. That will be much harder if multiple unrelated changes are lumped in the same commit.

Clone this wiki locally