Skip to content

Create a custom effect

Anton edited this page Feb 14, 2021 · 4 revisions

This guide will help you to create your own effect. We will create an effect called "effect_custom". Replace the name with your effect name.

You can find all modified files here: Custom Effect Demo Files

Do not copy and paste the whole file. These files may be outdated! Use the files from the master branch and add the required code lines.

Create the effect

Create a new file inside the directory music_led_strip_control/server/libs/effects/:

sudo touch /share/music_led_strip_control/server/libs/effects/effect_custom.py

Add the following content:

from libs.effects.effect import Effect  # pylint: disable=E0611, E0401

import numpy as np
from scipy.ndimage.filters import gaussian_filter1d

class EffectCustom(Effect):

    def __init__(self, device):

        # Call the constructor of the base class.
        super(EffectCustom, self).__init__(device)

        # Init your custom variables here.


    def run(self):
        effect_config = self._device.device_config["effects"]["effect_custom"]
        led_count = self._device.device_config["LED_Count"]
        led_mid = self._device.device_config["LED_Mid"]

        audio_data = self.get_audio_data()
        y = self.get_mel(audio_data)

        if y is None:
            return

        # Build an empty array.
        output_array = np.zeros((3, self._device.device_config["LED_Count"]))

        # Use this output method for music responsive effects.
        # It will put the output array into a queue.
        # After this it continues directly with the next music signal.
        self.queue_output_array_noneblocking(output_array)

        # Use this output method for non-music responsive effects.
        # It will block the effect until the array was output.
        self.queue_output_array_blocking(output_array)

Above is the file where you will manipulate the output array.

Code description:

Create a new class EffectCustom that inherits from Effect.

class EffectCustom(Effect):

This will be called during the start of the effect. It will be executed once. Add all variables that should be stored between the output cycle. E.g. the previous output array.

def __init__(self, device):

This method will be called each time the program wants to update the LED strip. E.g. 60 times per second. Add the array manipulation here.

def run(self):

Configs of your effect, that are stored inside the config.json.

effect_config = self._device.device_config["effects"]["effect_custom"]

The count of the LEDs.

led_count = self._device.device_config["LED_Count"]

The mid that you set for this LED strip.

led_mid = self._device.device_config["LED_Mid"]

This variable is the audio signal that was captured between the last call of the run and now. It is an array of 24 elements and represents the level of a specific frequency range. It goes from lows to highs. See the other effects to understand it better.

y

This is the array you will output. It is three-dimensional with the length of the LED strip. E.g. output[0][:] the [0] represents the red color channel. [:] selects all LEDs. See the other effects for inspiration.

output_array

This will put the output_array into a queue which will output it. Use the blocking method for non-music effects and the non-blocking one for music reactive effects.

self.queue_output_array_noneblocking(output_array)

self.queue_output_array_blocking(output_array)

Set all dependencies

Configuration

Add the configuration of your effect inside the config"

image

Remember the following line:

effect_config = self._device.device_config["effects"]["effect_custom"]

Open music_led_strip_control/server/libs/config.json.bak (this is the backup config, which will be used if you reset your settings) and add your effect. Find default_device, then effects. Now you should see some other effect settings like effect_bars.

Add your own settings:

"effect_custom": {
    "setting1": 1,
    "setting2": 0.7
},

Add the same block inside music_led_strip_control/server/libs/config.json.

You have to add it inside all of your existing devices and the "default_device" block.

EffectsEnum

Add a new entry in music_led_strip_control/server/libs/effects_enum.py:

effect_custom = 26

image

Effect Service

Add your effect to the imports in music_led_strip_control/server/libs/effect_service.py:

from libs.effects.effect_custom import EffectCustom  # pylint: disable=E0611, E0401`

image

Add your effect to the available effects in self._available_effects:

EffectsEnum.effect_custom: EffectCustom

This will link your effect class with the enum.

image

Web interface integration

Dashboard

Add a new tile to the Dashboard.

image

Open music_led_strip_control/server/libs/templates/dashboard.html and create a new li element:

<li id="effect_custom">
  <i class="fa fa-male dasboard-glyph" aria-hidden="true"></i>
  <span class="glyphicon-class">Custom</span>
</li>

Change the icon "fa-male" with any icon in this list: https://fontawesome.com/icons?d=gallery&m=free

Create Effect Settings page

image

Create the endpoint. Open music_led_strip_control/server/libs/webserver.py and add the following code to the "Effects" section.

    @server.route('/effects/effect_custom', methods=['GET', 'POST'])
    def effect_custom():  # pylint: disable=E0211
        # Render the effect_custom page
        return render_template('effects/effect_custom.html')

image

Create effect_custom.html inside music_led_strip_control/server/libs/templates/effects/

sudo touch /share/music_led_strip_control/server/libs/templates/effects/effect_custom.html

Add the following content to effect_custom.html:

{% extends "base/base_site.html" %}

{% block title %}Custom Effect{% endblock title %}

{% block content %}
<input type="hidden" id="settingsIdentifier" value="effect">
<input type="hidden" id="effectIdentifier" value="effect_custom">
<div class="row">
  <div class="col-md-12">
    <div class="x_panel">
      <div class="x_content">
        <div class="bs-docs-section">
          <h2 id="dashboard-header-2">Custom Effect Settings</h2>
          <p>Edit the Custom effect.
          </p>
          <form id="settingsForm" data-parsley-validate class="form-horizontal form-label-left" action method="post" novalidate>

              <div class="item form-group">
                <label class="center control-label col-md-3 col-sm-3 col-xs-12" for="setting1">Setting1</label>
                <input id="setting1" class="knob col-md-6 col-sm-6 col-xs-12 setting_input"  type="number" data-step="0.01" data-angleoffset="-125" data-anglearc="250" data-max="10" data-width="100" data-height="100" data-cursor=true data-fgColor="#f0ad4e" value="1">
              </div>

              <div class="item form-group">
                <label class="center control-label col-md-3 col-sm-3 col-xs-12" for="setting2">Setting2</label>
                <input id="setting2" class="knob col-md-6 col-sm-6 col-xs-12 setting_input"  type="number" data-step="0.01" data-angleoffset="-125" data-anglearc="250" data-max="10" data-width="100" data-height="100" data-cursor=true data-fgColor="#f0ad4e" value="1">
              </div>

              <div class="text-right">
                  <button type="button" id="save_btn" class="btn btn-success">Save</button>
              </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</div>

{% endblock content %}

{% block custom_javascripts %}

<script src="{{ url_for('static', filename='vendors/switchery/dist/switchery.min.js') }}" type="text/javascript"></script>

<!-- Validator -->
<script src="{{ url_for('static', filename='vendors/validator/validator.js') }}" type="text/javascript"></script>

<!-- jQuery Knob -->
<script src="{{ url_for('static', filename='vendors/jquery-knob/dist/jquery.knob.min.js') }}"></script>

<!-- Custom Theme Scripts -->
<script src="{{ url_for('static', filename='own/js/settings.effect.js') }}"></script>
{% endblock custom_javascripts %}

This will add Setting1 and Settings2 knobs. See the other effect settings pages for gradients and colors.

Add Settings Site to the Navigation

image

Open music_led_strip_control/server/libs/templates/nav/sidebar.html and add a new li element:

<li><a href="/effects/effect_custom">Custom</a></li>

Revision 2.0