Search in sources :

Example 1 with Sink

use of org.openhab.binding.pulseaudio.internal.items.Sink in project openhab1-addons by openhab.

the class Parser method parseSinks.

/**
     * parses the pulseaudio servers answer to the list-sinks command and returns a list of
     * {@link Sink} objects
     * 
     * @param raw the given string from the pulseaudio server
     * @return list of sinks
     */
public static Collection<Sink> parseSinks(String raw, PulseaudioClient client) {
    Hashtable<String, Sink> sinks = new Hashtable<String, Sink>();
    // System.out.println(raw);
    String[] parts = raw.split("index: ");
    if (parts.length <= 1) {
        return sinks.values();
    }
    // skip first part
    List<Sink> combinedSinks = new ArrayList<Sink>();
    for (int i = 1; i < parts.length; i++) {
        String[] lines = parts[i].split("\n");
        Hashtable<String, String> properties = new Hashtable<String, String>();
        int id = 0;
        try {
            id = Integer.valueOf(lines[0].trim());
        } catch (NumberFormatException e) {
            // sometime the line feed is missing here
            Matcher matcher = fallBackPattern.matcher(lines[0].trim());
            if (matcher.find()) {
                id = Integer.valueOf(matcher.group(1));
                properties.put(matcher.group(2).trim(), matcher.group(3).trim());
            }
        }
        for (int j = 1; j < lines.length; j++) {
            Matcher matcher = pattern.matcher(lines[j]);
            if (matcher.find()) {
                // System.out.println(matcher.group(1).trim()+": "+matcher.group(2).trim());
                properties.put(matcher.group(1).trim(), matcher.group(2).trim());
            }
        }
        if (properties.containsKey("name")) {
            Sink sink = new Sink(id, properties.get("name"), client.getModule(getNumberValue(properties.get("module"))));
            if (properties.containsKey("state")) {
                try {
                    sink.setState(AbstractAudioDeviceConfig.State.valueOf(properties.get("state")));
                } catch (IllegalArgumentException e) {
                    logger.error("unhandled state " + properties.get("state") + " in sink item #" + id);
                }
            }
            if (properties.containsKey("muted")) {
                sink.setMuted(properties.get("muted").equalsIgnoreCase("yes"));
            }
            if (properties.containsKey("volume")) {
                sink.setVolume(Integer.valueOf(parseVolume(properties.get("volume"))));
            }
            if (properties.containsKey("combine.slaves")) {
                // be
                for (String sinkName : properties.get("combine.slaves").replace("\"", "").split(",")) {
                    sink.addCombinedSinkName(sinkName);
                }
                combinedSinks.add(sink);
            }
            sinks.put(sink.getName(), sink);
        }
    }
    for (Sink combinedSink : combinedSinks) {
        for (String sinkName : combinedSink.getCombinedSinkNames()) {
            combinedSink.addCombinedSink(sinks.get(sinkName));
        }
    }
    return sinks.values();
}
Also used : Sink(org.openhab.binding.pulseaudio.internal.items.Sink) Matcher(java.util.regex.Matcher) Hashtable(java.util.Hashtable) ArrayList(java.util.ArrayList)

Example 2 with Sink

use of org.openhab.binding.pulseaudio.internal.items.Sink in project openhab1-addons by openhab.

the class PulseaudioBinding method internalReceiveCommand.

@Override
public void internalReceiveCommand(String itemName, Command command) {
    PulseaudioBindingProvider provider = findFirstMatchingBindingProvider(itemName, command);
    if (provider == null) {
        logger.warn("doesn't find matching binding provider [itemName={}, command={}]", itemName, command);
        return;
    }
    String audioItemName = provider.getItemName(itemName);
    String serverId = provider.getServerId(itemName);
    // Item item = provider.getItem(itemName);
    String paCommand = provider.getCommand(itemName);
    PulseaudioCommandTypeMapping pulseaudioCommandType = null;
    if (paCommand != null && !paCommand.isEmpty()) {
        try {
            pulseaudioCommandType = PulseaudioCommandTypeMapping.valueOf(paCommand.toUpperCase());
        } catch (IllegalArgumentException e) {
            logger.warn("unknown command specified for the given itemName [itemName={}, audio-item-name={}, serverId={}, command={}] => querying for values aborted!", new Object[] { itemName, audioItemName, serverId, command });
        }
    }
    PulseaudioClient client = clients.get(serverId);
    if (client == null) {
        // try to reconnect if the server is configured
        if (serverConfigCache.containsKey(serverId)) {
            connect(serverId, serverConfigCache.get(serverId));
            client = clients.get(serverId);
        }
    }
    if (client == null) {
        logger.warn("does't find matching pulseaudio client [itemName={}, serverId={}]", itemName, serverId);
        return;
    }
    if (audioItemName != null && !audioItemName.isEmpty()) {
        AbstractAudioDeviceConfig audioItem = client.getGenericAudioItem(audioItemName);
        if (audioItem == null) {
            logger.warn("no corresponding audio-item found [audioItemName={}]", audioItemName);
            return;
        }
        State updateState = UnDefType.UNDEF;
        if (command instanceof IncreaseDecreaseType) {
            int volume = audioItem.getVolume();
            logger.debug(audioItemName + " volume is " + volume);
            if (command.equals(IncreaseDecreaseType.INCREASE)) {
                volume = Math.min(100, volume + 5);
            }
            if (command.equals(IncreaseDecreaseType.DECREASE)) {
                volume = Math.max(0, volume - 5);
            }
            logger.debug("setting " + audioItemName + " volume to " + volume);
            client.setVolumePercent(audioItem, volume);
            updateState = new PercentType(volume);
        } else if (command instanceof PercentType) {
            client.setVolumePercent(audioItem, Integer.valueOf(command.toString()));
            updateState = (PercentType) command;
        } else if (command instanceof DecimalType) {
            if (pulseaudioCommandType == null || pulseaudioCommandType.equals(PulseaudioCommandTypeMapping.VOLUME)) {
                // set volume
                client.setVolume(audioItem, Integer.valueOf(command.toString()));
                updateState = (DecimalType) command;
            }
        // all other pulseaudioCommandType's for DecimalTypes are
        // read-only and
        // therefore we do nothing here
        } else if (command instanceof OnOffType) {
            if (pulseaudioCommandType == null) {
                // Default behaviour when no command is specified => mute
                client.setMute(audioItem, ((OnOffType) command).equals(OnOffType.ON));
                updateState = (OnOffType) command;
            } else {
                switch(pulseaudioCommandType) {
                    case EXISTS:
                        // we better do nothing here
                        break;
                    case MUTED:
                        client.setMute(audioItem, ((OnOffType) command).equals(OnOffType.ON));
                        updateState = (OnOffType) command;
                        break;
                    case RUNNING:
                    case CORKED:
                    case SUSPENDED:
                    case IDLE:
                        // the state of an audio-item cannot be changed
                        break;
                    case ID:
                    case MODULE_ID:
                        // changed
                        break;
                    case VOLUME:
                        if (((OnOffType) command).equals(OnOffType.ON)) {
                            // Set Volume to 100%
                            client.setVolume(audioItem, 100);
                        } else {
                            // set volume to 0
                            client.setVolume(audioItem, 100);
                        }
                        updateState = (OnOffType) command;
                        break;
                    case SLAVE_SINKS:
                        // also an read-only field
                        break;
                }
            }
        } else if (command instanceof StringType) {
            if (pulseaudioCommandType != null) {
                switch(pulseaudioCommandType) {
                    case CORKED:
                    case EXISTS:
                    case ID:
                    case IDLE:
                    case MODULE_ID:
                    case MUTED:
                    case RUNNING:
                    case SUSPENDED:
                    case VOLUME:
                        // no action here
                        break;
                    case SLAVE_SINKS:
                        if (audioItem instanceof Sink && ((Sink) audioItem).isCombinedSink()) {
                            // change the slave sinks of the given combined sink
                            // to the new value
                            Sink mainSink = (Sink) audioItem;
                            ArrayList<Sink> slaveSinks = new ArrayList<Sink>();
                            for (String slaveSinkName : StringUtils.split(command.toString(), ",")) {
                                Sink slaveSink = client.getSink(slaveSinkName);
                                if (slaveSink != null) {
                                    slaveSinks.add(slaveSink);
                                }
                            }
                            logger.debug(slaveSinks.size() + " slave sinks");
                            if (slaveSinks.size() > 0) {
                                client.setCombinedSinkSlaves(mainSink, slaveSinks);
                            }
                        }
                        break;
                }
            }
        }
        if (!updateState.equals(UnDefType.UNDEF)) {
            eventPublisher.postUpdate(itemName, updateState);
        }
    } else if (command instanceof StringType) {
        // send the command directly to the pulseaudio server
        client.sendCommand(command.toString());
        eventPublisher.postUpdate(itemName, (StringType) command);
    }
}
Also used : PulseaudioBindingProvider(org.openhab.binding.pulseaudio.PulseaudioBindingProvider) StringType(org.openhab.core.library.types.StringType) ArrayList(java.util.ArrayList) PercentType(org.openhab.core.library.types.PercentType) Sink(org.openhab.binding.pulseaudio.internal.items.Sink) OnOffType(org.openhab.core.library.types.OnOffType) State(org.openhab.core.types.State) DecimalType(org.openhab.core.library.types.DecimalType) IncreaseDecreaseType(org.openhab.core.library.types.IncreaseDecreaseType) AbstractAudioDeviceConfig(org.openhab.binding.pulseaudio.internal.items.AbstractAudioDeviceConfig)

Example 3 with Sink

use of org.openhab.binding.pulseaudio.internal.items.Sink in project openhab1-addons by openhab.

the class PulseaudioBinding method execute.

/**
     * @{inheritDoc
     */
@Override
@SuppressWarnings("incomplete-switch")
public void execute() {
    List<PulseaudioClient> updatedClients = new ArrayList<PulseaudioClient>();
    for (PulseaudioBindingProvider provider : providers) {
        for (String itemName : provider.getItemNames()) {
            String audioItemName = provider.getItemName(itemName);
            String serverId = provider.getServerId(itemName);
            Class<? extends Item> itemType = provider.getItemType(itemName);
            String command = provider.getCommand(itemName);
            PulseaudioCommandTypeMapping commandType = null;
            if (command != null && !command.isEmpty()) {
                try {
                    commandType = PulseaudioCommandTypeMapping.valueOf(command.toUpperCase());
                } catch (IllegalArgumentException e) {
                    logger.warn("unknown command specified for the given itemName [itemName={}, audio-item-name={}, serverId={}, command={}] => querying for values aborted!", new Object[] { itemName, audioItemName, serverId, command });
                    continue;
                }
            }
            if (itemType.isAssignableFrom(GroupItem.class) || itemType.isAssignableFrom(StringItem.class)) {
                // directly
                continue;
            }
            PulseaudioClient client = clients.get(serverId);
            if (client == null) {
                logger.warn("connection to pulseaudio server in not available " + "for the given itemName [itemName={}, audio-item-name={}, serverId={}, command={}] => querying for values aborted!", new Object[] { itemName, audioItemName, serverId, command });
                continue;
            }
            if (audioItemName == null) {
                logger.warn("audio-item-name isn't configured properly " + "for the given itemName [itemName={}, audio-item-name={}, serverId={}, command={}] => querying for values aborted!", new Object[] { itemName, audioItemName, serverId, command });
                continue;
            }
            if (!updatedClients.contains(client)) {
                // update the clients data structure to avoid
                // inconsistencies
                client.update();
                updatedClients.add(client);
            }
            State value = UnDefType.UNDEF;
            AbstractAudioDeviceConfig audioItem = client.getGenericAudioItem(audioItemName);
            if (audioItem != null) {
                // item found
                if (itemType.isAssignableFrom(SwitchItem.class)) {
                    if (commandType == null) {
                        // Check if item is unmuted and running
                        if (!audioItem.isMuted() && audioItem.getState() != null && audioItem.getState().equals(AbstractAudioDeviceConfig.State.RUNNING)) {
                            value = OnOffType.ON;
                        } else {
                            value = OnOffType.OFF;
                        }
                    } else {
                        switch(commandType) {
                            case EXISTS:
                                value = OnOffType.ON;
                                break;
                            case MUTED:
                                value = audioItem.isMuted() ? OnOffType.ON : OnOffType.OFF;
                                break;
                            case RUNNING:
                            case CORKED:
                            case SUSPENDED:
                            case IDLE:
                                try {
                                    value = audioItem.getState() != null && audioItem.getState().equals(AbstractAudioDeviceConfig.State.valueOf(commandType.name())) ? OnOffType.ON : OnOffType.OFF;
                                } catch (IllegalArgumentException e) {
                                    logger.warn("no corresponding AbstractAudioDeviceConfig.State found for " + commandType.name());
                                }
                                break;
                        }
                    }
                } else if (itemType.isAssignableFrom(DimmerItem.class)) {
                    value = new PercentType(audioItem.getVolume());
                } else if (itemType.isAssignableFrom(NumberItem.class)) {
                    if (commandType == null) {
                        // when no other pulseaudioCommand specified, we use
                        // VOLUME
                        value = new DecimalType(audioItem.getVolume());
                    } else {
                        // ID command types
                        switch(commandType) {
                            case VOLUME:
                                value = new DecimalType(audioItem.getVolume());
                                break;
                            case ID:
                                value = new DecimalType(audioItem.getId());
                                break;
                            case MODULE_ID:
                                if (audioItem.getModule() != null) {
                                    value = new DecimalType(audioItem.getModule().getId());
                                }
                                break;
                        }
                    }
                } else if (itemType.isAssignableFrom(StringItem.class)) {
                    if (commandType == null) {
                        value = new StringType(audioItem.toString());
                    } else if (audioItem instanceof Sink) {
                        Sink sink = (Sink) audioItem;
                        switch(commandType) {
                            case SLAVE_SINKS:
                                if (sink.isCombinedSink()) {
                                    value = new StringType(StringUtils.join(sink.getCombinedSinkNames(), ","));
                                }
                                break;
                        }
                    }
                } else {
                    logger.debug("unhandled item type [type={}, name={}]", itemType.getClass(), audioItemName);
                }
            } else if (itemType.isAssignableFrom(SwitchItem.class)) {
                value = OnOffType.OFF;
            }
            eventPublisher.postUpdate(itemName, value);
        }
    }
}
Also used : PulseaudioBindingProvider(org.openhab.binding.pulseaudio.PulseaudioBindingProvider) StringType(org.openhab.core.library.types.StringType) ArrayList(java.util.ArrayList) PercentType(org.openhab.core.library.types.PercentType) StringItem(org.openhab.core.library.items.StringItem) Sink(org.openhab.binding.pulseaudio.internal.items.Sink) State(org.openhab.core.types.State) DimmerItem(org.openhab.core.library.items.DimmerItem) DecimalType(org.openhab.core.library.types.DecimalType) GroupItem(org.openhab.core.items.GroupItem) AbstractAudioDeviceConfig(org.openhab.binding.pulseaudio.internal.items.AbstractAudioDeviceConfig) SwitchItem(org.openhab.core.library.items.SwitchItem)

Example 4 with Sink

use of org.openhab.binding.pulseaudio.internal.items.Sink in project openhab1-addons by openhab.

the class PulseaudioClient method setCombinedSinkSlaves.

/**
     * changes the combined sinks slaves to the given <code>sinks</code>
     * 
     * @param combinedSink the combined sink which slaves should be changed
     * @param sinks the list of new slaves
     */
public void setCombinedSinkSlaves(String combinedSinkName, List<Sink> sinks) {
    if (getSink(combinedSinkName) != null) {
        return;
    }
    List<String> slaves = new ArrayList<String>();
    for (Sink sink : sinks) {
        slaves.add(sink.getName());
    }
    // add new combined-sink with same name and all slaves
    _sendRawCommand(CMD_LOAD_MODULE + " " + MODULE_COMBINE_SINK + " sink_name=" + combinedSinkName + " slaves=" + StringUtils.join(slaves, ","));
    // update internal data structure because the combined sink is new
    update();
}
Also used : Sink(org.openhab.binding.pulseaudio.internal.items.Sink) ArrayList(java.util.ArrayList)

Example 5 with Sink

use of org.openhab.binding.pulseaudio.internal.items.Sink in project openhab1-addons by openhab.

the class PulseaudioClient method setCombinedSinkSlaves.

/**
     * changes the combined sinks slaves to the given <code>sinks</code>
     * 
     * @param combinedSink the combined sink which slaves should be changed
     * @param sinks the list of new slaves
     */
public void setCombinedSinkSlaves(Sink combinedSink, List<Sink> sinks) {
    if (combinedSink == null || !combinedSink.isCombinedSink()) {
        return;
    }
    List<String> slaves = new ArrayList<String>();
    for (Sink sink : sinks) {
        slaves.add(sink.getName());
    }
    // 1. delete old combined-sink
    _sendRawCommand(CMD_UNLOAD_MODULE + " " + combinedSink.getModule().getId());
    // 2. add new combined-sink with same name and all slaves
    _sendRawCommand(CMD_LOAD_MODULE + " " + MODULE_COMBINE_SINK + " sink_name=" + combinedSink.getName() + " slaves=" + StringUtils.join(slaves, ","));
    // 3. update internal data structure because the combined sink has a new number + other slaves
    update();
}
Also used : Sink(org.openhab.binding.pulseaudio.internal.items.Sink) ArrayList(java.util.ArrayList)

Aggregations

ArrayList (java.util.ArrayList)5 Sink (org.openhab.binding.pulseaudio.internal.items.Sink)5 PulseaudioBindingProvider (org.openhab.binding.pulseaudio.PulseaudioBindingProvider)2 AbstractAudioDeviceConfig (org.openhab.binding.pulseaudio.internal.items.AbstractAudioDeviceConfig)2 DecimalType (org.openhab.core.library.types.DecimalType)2 PercentType (org.openhab.core.library.types.PercentType)2 StringType (org.openhab.core.library.types.StringType)2 State (org.openhab.core.types.State)2 Hashtable (java.util.Hashtable)1 Matcher (java.util.regex.Matcher)1 GroupItem (org.openhab.core.items.GroupItem)1 DimmerItem (org.openhab.core.library.items.DimmerItem)1 StringItem (org.openhab.core.library.items.StringItem)1 SwitchItem (org.openhab.core.library.items.SwitchItem)1 IncreaseDecreaseType (org.openhab.core.library.types.IncreaseDecreaseType)1 OnOffType (org.openhab.core.library.types.OnOffType)1