Ejemplo n.º 1
0
function wrk_mpdconf($outpath, $db)
{
    // extract mpd.conf from SQLite datastore
    $dbh = cfgdb_connect($db);
    $query_cfg = "SELECT param,value_player FROM cfg_mpd WHERE value_player!=''";
    $mpdcfg = sdbquery($query_cfg, $dbh);
    $dbh = null;
    // set mpd.conf file header
    $output = "###################################\n";
    $output .= "# Auto generated mpd.conf file\n";
    $output .= "# please DO NOT edit it manually!\n";
    $output .= "# Use player-UI MPD config section\n";
    $output .= "###################################\n";
    $output .= "\n";
    // parse DB output
    foreach ($mpdcfg as $cfg) {
        if ($cfg['param'] == 'audio_output_format' && $cfg['value_player'] == 'disabled') {
            $output .= '';
        } else {
            if ($cfg['param'] == 'dsd_usb') {
                $dsd = $cfg['value_player'];
            } else {
                if ($cfg['param'] == 'device') {
                    $device = $cfg['value_player'];
                    var_export($device);
                    // $output .= '';
                } else {
                    if ($cfg['param'] == 'mixer_type' && $cfg['value_player'] == 'hardware') {
                        // $hwmixer['device'] = 'hw:0';
                        $hwmixer['control'] = alsa_findHwMixerControl($device);
                        // $hwmixer['index'] = '1';
                    } else {
                        $output .= $cfg['param'] . " \t\"" . $cfg['value_player'] . "\"\n";
                    }
                }
            }
        }
    }
    // format audio input / output interfaces
    $output .= "max_connections \"20\"\n";
    $output .= "\n";
    $output .= "decoder {\n";
    $output .= "\t\tplugin \"ffmpeg\"\n";
    $output .= "\t\tenabled \"yes\"\n";
    $output .= "}\n";
    $output .= "\n";
    $output .= "input {\n";
    $output .= "\t\tplugin \"curl\"\n";
    $output .= "}\n";
    $output .= "\n";
    $output .= "audio_output {\n\n";
    $output .= "\t\t type \t\t\"alsa\"\n";
    $output .= "\t\t name \t\t\"Output\"\n";
    $output .= "\t\t device \t\"hw:" . $device . ",0\"\n";
    if (isset($hwmixer)) {
        //$output .= "\t\t mixer_device \t\"".$hwmixer['device']."\"\n";
        $output .= "\t\t mixer_control \t\"" . $hwmixer['control'] . "\"\n";
        $output .= "\t\t mixer_device \t\"hw:" . $device . "\"\n";
        $output .= "\t\t mixer_index \t\"0\"\n";
        //$output .= "\t\t mixer_index \t\"".$hwmixer['index']."\"\n";
    }
    $output .= "\t\t dsd_usb \t\"" . $dsd . "\"\n";
    $output .= "\n}\n";
    // write mpd.conf file
    $fh = fopen($outpath . "/mpd.conf", 'w');
    fwrite($fh, $output);
    fclose($fh);
}
Ejemplo n.º 2
0
function wrk_mpdconf($redis, $action, $args = null, $jobID = null)
{
    // set mpd.conf file header
    $header = "###################################\n";
    $header .= "# Auto generated mpd.conf file\n";
    $header .= "# please DO NOT edit it manually!\n";
    $header .= "# Use RuneUI MPD config section\n";
    $header .= "###################################\n";
    $header .= "\n";
    switch ($action) {
        case 'reset':
            // default MPD config
            $redis->hSet('mpdconf', 'zeroconf_enabled', 'yes');
            $redis->hSet('mpdconf', 'zeroconf_name', 'runeaudio');
            $redis->hSet('mpdconf', 'log_level', 'none');
            $redis->hSet('mpdconf', 'bind_to_address', 'any');
            $redis->hSet('mpdconf', 'port', '6600');
            $redis->hSet('mpdconf', 'max_connections', '20');
            $redis->hSet('mpdconf', 'user', 'mpd');
            $redis->hSet('mpdconf', 'db_file', '/var/lib/mpd/mpd.db');
            $redis->hSet('mpdconf', 'sticker_file', '/var/lib/mpd/sticker.sql');
            $redis->hSet('mpdconf', 'pid_file', '/var/run/mpd/pid');
            $redis->hSet('mpdconf', 'music_directory', '/mnt/MPD');
            $redis->hSet('mpdconf', 'playlist_directory', '/var/lib/mpd/playlists');
            $redis->hSet('mpdconf', 'state_file', '/var/lib/mpd/mpdstate');
            $redis->hSet('mpdconf', 'follow_outside_symlinks', 'yes');
            $redis->hSet('mpdconf', 'follow_inside_symlinks', 'yes');
            $redis->hSet('mpdconf', 'auto_update', 'no');
            $redis->hSet('mpdconf', 'filesystem_charset', 'UTF-8');
            $redis->hSet('mpdconf', 'id3v1_encoding', 'UTF-8');
            $redis->hSet('mpdconf', 'volume_normalization', 'no');
            $redis->hSet('mpdconf', 'audio_buffer_size', '2048');
            $redis->hSet('mpdconf', 'buffer_before_play', '10%');
            $redis->hSet('mpdconf', 'gapless_mp3_playback', 'yes');
            $redis->hSet('mpdconf', 'mixer_type', 'software');
            $redis->hSet('mpdconf', 'curl', 'yes');
            $redis->hSet('mpdconf', 'ffmpeg', 'yes');
            $redis->hSet('mpdconf', 'log_file', '/var/log/runeaudio/mpd.log');
            wrk_mpdconf($redis, 'writecfg');
            break;
        case 'writecfg':
            $mpdcfg = $redis->hGetAll('mpdconf');
            $current_out = $redis->Get('ao');
            // if (!$redis->hExists('acards', $current_out)) {
            if (!$redis->hExists('acards', $current_out) && $redis->Get('i2smodule') === 'none') {
                $stored_acards = $redis->hKeys('acards');
                // debug
                runelog('force audio output', $stored_acards[0]);
                // force first output available if the current interface does not exists
                $redis->Set('ao', $stored_acards[0]);
                $redis->Save();
            }
            $output = null;
            // --- log settings ---
            if ($mpdcfg['log_level'] === 'none') {
                $redis->hDel('mpdconf', 'log_file');
            } else {
                $output .= "log_level\t\"" . $mpdcfg['log_level'] . "\"\n";
                $output .= "log_file\t\"/var/log/runeaudio/mpd.log\"\n";
                $redis->hSet('mpdconf', 'log_file', '/var/log/runeaudio/mpd.log');
            }
            unset($mpdcfg['log_level']);
            unset($mpdcfg['log_file']);
            // --- state file ---
            if ($mpdcfg['state_file'] === 'no') {
                $redis->hDel('mpdconf', 'state_file');
            } else {
                $output .= "state_file\t\"/var/lib/mpd/mpdstate\"\n";
                $redis->hSet('mpdconf', 'state_file', '/var/lib/mpd/mpdstate');
            }
            unset($mpdcfg['state_file']);
            // --- general settings ---
            foreach ($mpdcfg as $param => $value) {
                if ($param === 'audio_output_interface' or $param === 'dsd_usb') {
                    continue;
                }
                if ($param === 'mixer_type') {
                    if ($value === 'software' or $value === 'hardware') {
                        $redis->set('volume', 1);
                        if ($value === 'hardware') {
                            $hwmixer = 1;
                            continue;
                        }
                    } else {
                        $redis->set('volume', 0);
                    }
                }
                if ($param === 'user' && $value === 'mpd') {
                    $output .= $param . " \t\"" . $value . "\"\n";
                    $output .= "group \t\"audio\"\n";
                    continue;
                }
                if ($param === 'user' && $value === 'root') {
                    $output .= $param . " \t\"" . $value . "\"\n";
                    $output .= "group \t\"root\"\n";
                    continue;
                }
                if ($param === 'bind_to_address') {
                    $output .= "bind_to_address \"/run/mpd.sock\"\n";
                }
                if ($param === 'ffmpeg') {
                    // --- decoder plugin ---
                    $output .= "\n";
                    $output .= "decoder {\n";
                    $output .= "plugin \t\"ffmpeg\"\n";
                    $output .= "enabled \"" . $value . "\"\n";
                    $output .= "}\n";
                    continue;
                }
                if ($param === 'curl') {
                    // --- input plugin ---
                    $output .= "\n";
                    $output .= "input {\n";
                    $output .= "plugin \t\"curl\"\n";
                    if ($redis->hget('proxy', 'enable') === '1') {
                        $output .= "proxy \t\"" . $redis->hget('proxy', 'host') . "\"\n";
                        if ($redis->hget('proxy', 'user') !== '') {
                            $output .= "proxy_user \t\"" . $redis->hget('proxy', 'user') . "\"\n";
                            $output .= "proxy_password \t\"" . $redis->hget('proxy', 'pass') . "\"\n";
                        }
                    }
                    $output .= "}\n";
                    continue;
                }
                $output .= $param . " \t\"" . $value . "\"\n";
            }
            $output = $header . $output;
            // --- audio output ---
            $acards = $redis->hGetAll('acards');
            // debug
            runelog('detected ACARDS ', $acards, __FUNCTION__);
            $ao = $redis->Get('ao');
            $sub_count = 0;
            foreach ($acards as $card) {
                $card_decoded = new stdClass();
                $card_decoded = json_decode($card);
                // debug
                runelog('decoded ACARD ', $card_decoded, __FUNCTION__);
                if (isset($card_decoded->integrated_sub) && $card_decoded->integrated_sub === 1) {
                    // record UI audio output name
                    $current_card = $card_decoded->name;
                    if ($sub_count >= 1) {
                        continue;
                    }
                    $card_decoded = json_decode($card_decoded->real_interface);
                    runelog('current AO ---->  ', $ao, __FUNCTION__);
                    // var_dump($ao);
                    runelog('current card_name ---->  ', $card_decoded->name, __FUNCTION__);
                    // var_dump($card_decoded->name);
                    // var_dump(strpos($ao, $card_decoded->name));
                    if (strpos($ao, $card_decoded->name) === true or strpos($ao, $card_decoded->name) === 0) {
                        $sub_interface_selected = 1;
                    }
                    // debug
                    if (isset($sub_interface_selected)) {
                        runelog('sub_card_selected ? >>>> ' . $sub_interface_selected);
                    }
                    // debug
                    runelog('this is a sub_interface', __FUNCTION__);
                    $sub_interface = 1;
                    $sub_count++;
                    runelog('sub_count', $sub_count, __FUNCTION__);
                }
                $output .= "\n";
                $output .= "audio_output {\n";
                $output .= "name \t\t\"" . $card_decoded->name . "\"\n";
                $output .= "type \t\t\"" . $card_decoded->type . "\"\n";
                $output .= "device \t\t\"" . $card_decoded->device . "\"\n";
                if (isset($hwmixer)) {
                    $output .= "mixer_type \t\"hardware\"\n";
                    if (isset($card_decoded->mixer_device)) {
                        $output .= "mixer_device \t\"" . $card_decoded->mixer_device . "\"\n";
                    } else {
                        $output .= "mixer_device \t\"hw:" . $card_decoded->device . "\"\n";
                    }
                    if (isset($card_decoded->mixer_control)) {
                        $output .= "mixer_control \t\"" . $card_decoded->mixer_control . "\"\n";
                    } else {
                        $output .= "mixer_control \t\"" . alsa_findHwMixerControl(substr($card_decoded->device, 4, 1)) . ",0\"\n";
                    }
                    $output .= "mixer_index \t\"0\"\n";
                    "\t\t  \t\"0\"\n";
                }
                if ($mpdcfg['dsd_usb'] === 'yes') {
                    $output .= "dsd_usb \t\"yes\"\n";
                }
                $output .= "auto_resample \t\"no\"\n";
                $output .= "auto_format \t\"no\"\n";
                if (isset($sub_interface_selected)) {
                    // use UI selector name to enable a sub_interface (ex. switch between AnalogOut / HDMI on RaspberryPI)
                    $output .= "enabled \t\"yes\"\n";
                } else {
                    // normal condition
                    if ($ao === $card_decoded->name) {
                        $output .= "enabled \t\"yes\"\n";
                    }
                }
                $output .= "}\n";
                // unset($current_card);
                // unset($sub_interface);
                // unset($card_decoded);
                // debug
                runelog('conf output (in loop)', $output, __FUNCTION__);
            }
            $output .= "\n";
            // debug
            runelog('raw mpd.conf', $output, __FUNCTION__);
            // write mpd.conf file
            $fh = fopen('/etc/mpd.conf', 'w');
            fwrite($fh, $output);
            fclose($fh);
            // update hash
            $redis->set('mpdconfhash', md5_file('/etc/mpd.conf'));
            break;
        case 'update':
            foreach ($args as $param => $value) {
                $redis->hSet('mpdconf', $param, $value);
            }
            wrk_mpdconf($redis, 'writecfg');
            break;
        case 'switchao':
            // record current interface selection
            $redis->set('ao', $args);
            $mpdout = $args;
            // get interface details
            $interface_details = $redis->hGet('acards', $args);
            $interface_details = json_decode($interface_details);
            // check for "special" sub_interfaces
            if (isset($interface_details->integrated_sub)) {
                // execute special internal route command
                sysCmd($interface_details->route_cmd);
                // TODO: improove this function
                sysCmd('amixer -c 0 set PCM unmute');
                $mpdout = $interface_details->sysname;
            }
            wrk_mpdconf($redis, 'writecfg');
            wrk_shairport($redis, $args);
            // toggle playback state
            if (wrk_mpdPlaybackStatus() === 'playing') {
                syscmd('mpc toggle');
                $recover_state = 1;
                // debug
                runelog('switchao (set recover state):', $recover_state);
            }
            // switch interface
            // debug
            runelog('switchao (switch AO):', $mpdout);
            syscmd('mpc enable only "' . $mpdout . '"');
            // restore playback state
            if (isset($recover_state)) {
                // debug
                runelog('switchao (RECOVER STATE!)');
                syscmd('mpc toggle');
            }
            // set notify label
            if (isset($interface_details->extlabel)) {
                $interface_label = $interface_details->extlabel;
            } else {
                $interface_label = $args;
            }
            // notify UI
            ui_notify_async('Audio output switched', "Current active output:\n" . $interface_label, $jobID);
            break;
        case 'refresh':
            wrk_audioOutput($redis, 'refresh');
            wrk_mpdconf($redis, 'writecfg');
            wrk_mpdconf($redis, 'restart');
            break;
        case 'start':
            $activePlayer = $redis->get('activePlayer');
            if ($activePlayer === 'MPD') {
                sysCmd('systemctl start mpd');
                if ($redis->get('mpd_playback_status') === 'playing') {
                    syscmd('mpc play');
                }
                // restart mpdscribble
                if ($redis->hGet('lastfm', 'enable') === '1') {
                    sysCmd('systemctl restart mpdscribble');
                }
                // restart upmpdcli
                if ($redis->hGet('dlna', 'enable') === '1') {
                    sysCmd('systemctl restart upmpdcli');
                }
                // set process priority
                sysCmdAsync('sleep 1 && rune_prio nice');
            }
            break;
        case 'stop':
            $redis->set('mpd_playback_status', wrk_mpdPlaybackStatus());
            $mpd = openMpdSocket('/run/mpd.sock');
            sendMpdCommand($mpd, 'kill');
            closeMpdSocket($mpd);
            sleep(1);
            sysCmd('systemctl stop mpd');
            break;
        case 'restart':
            wrk_mpdconf($redis, 'stop');
            sleep(1);
            wrk_mpdconf($redis, 'start');
            break;
    }
}