-- Update Music info using mpd/mpc -- Depends mpd, mpc local gears = require('gears') local awful = require('awful') local config_dir = gears.filesystem.get_configuration_dir() local widget_icon_dir = config_dir .. 'widget/music/icons/' local ui_content = require('widget.music.content') local album_cover = ui_content.album_cover local prog_bar = ui_content.progress_bar local track_time = ui_content.track_time local song_info = ui_content.song_info local vol_slider = ui_content.volume_slider local media_buttons = ui_content.media_buttons local apps = require('configuration.apps') local update_cover = function() local extract_script = [[ MUSIC_DIR="$(xdg-user-dir MUSIC)" TMP_DIR="/tmp/awesomewm/${USER}/" TMP_COVER_PATH=${TMP_DIR}"cover.jpg" TMP_SONG="${TMP_DIR}current-song" CHECK_EXIFTOOL=$(command -v exiftool) if [ ! -d "${TMP_DIR}" ]; then mkdir -p "${TMP_DIR}"; fi if [ ! -z "$CHECK_EXIFTOOL" ]; then # Extract album cover using perl-image-exiftool exiftool -b -Picture \ "$MUSIC_DIR/$(mpc -p 6600 --format "%file%" current)" > "$TMP_COVER_PATH" else #Extract image using ffmpeg cp "$MUSIC_DIR/$(mpc --format %file% current)" "$TMP_SONG" ffmpeg \ -hide_banner \ -loglevel 0 \ -y \ -i "$TMP_SONG" \ -vf scale=300:-1 \ "$TMP_COVER_PATH" > /dev/null 2>&1 rm "$TMP_SONG" fi img_data=$(identify $TMP_COVER_PATH 2>&1) # Delete the cover.jpg if it's not a valid image if [[ $img_data == *"insufficient"* ]] .. ']]' .. [[; then rm $TMP_COVER_PATH fi if [ -f $TMP_COVER_PATH ]; then echo $TMP_COVER_PATH; fi ]] awful.spawn.easy_async_with_shell( extract_script, function(stdout) local album_icon = widget_icon_dir .. 'vinyl' .. '.svg' if not (stdout == nil or stdout == '') then album_icon = stdout:gsub('%\n', '') end album_cover.cover:set_image(gears.surface.load_uncached(album_icon)) album_cover:emit_signal("widget::redraw_needed") album_cover:emit_signal("widget::layout_changed") collectgarbage('collect') end ) end local update_progress_bar = function() awful.spawn.easy_async_with_shell( [[ mpc status | awk 'NR==2 { split($4, a); print a[1]}' | tr -d '[\%\(\)]' ]], function(stdout) local progress_bar = prog_bar.music_bar if stdout ~= nil then progress_bar:set_value(tonumber(stdout)) else progress_bar:set_value(0) end end ) end local update_time_progress = function() awful.spawn.easy_async_with_shell( [[ mpc status | awk 'NR==2 { split($3, a, "/"); print a[1]}' | tr -d '[\%\(\)]' ]], function(stdout) local time_status = track_time.time_status if stdout ~= nil then time_status:set_text(tostring(stdout)) else time_status:set_text(tostring("00:00")) end end ) end local update_time_duration = function() awful.spawn.easy_async_with_shell( [[ mpc --format %time% current ]], function(stdout) local time_duration = track_time.time_duration if stdout ~= nil then time_duration:set_text(tostring(stdout)) else time_duration:set_text(tostring("99:59")) end end ) end local update_file = function() awful.spawn.easy_async_with_shell( [[ mpc -f %file% current ]], function(stdout) file_name = stdout:gsub('%\n','') end ) return file_name end local update_title = function() awful.spawn.easy_async_with_shell( [[ mpc -f %title% current ]], function(stdout) -- Remove new lines local title = stdout:gsub('%\n', '') local title_widget = song_info.music_title local title_text = song_info.music_title:get_children_by_id('title')[1] -- Make sure it's not null if not (title == nil or title == '') then title_text:set_text(title) else awful.spawn.easy_async_with_shell( [[ mpc -f %file% current ]], function(stdout) if not (stdout == nil or stdout == '') then file_name = stdout:gsub('%\n','') file_name = file_name:sub(1, title:len() - 5) .. '' title_text:set_text(file_name) else -- Set title title_text:set_text("Play some music!") end title_widget:emit_signal("widget::redraw_needed") title_widget:emit_signal("widget::layout_changed") end ) end title_widget:emit_signal("widget::redraw_needed") title_widget:emit_signal("widget::layout_changed") collectgarbage('collect') end ) end local update_artist = function() awful.spawn.easy_async_with_shell( [[ mpc -f %artist% current ]], function(stdout) -- Remove new lines local artist = stdout:gsub('%\n', '') local artist_widget = song_info.music_artist local artist_text = artist_widget:get_children_by_id('artist')[1] if not (artist == nil or artist == '') then artist_text:set_text(artist) else awful.spawn.easy_async_with_shell( [[ mpc -f %file% current ]], function(stdout) if not (stdout == nil or stdout == '') then artist_text:set_text('unknown artist') else artist_text:set_text("or play some porn?") end artist_widget:emit_signal("widget::redraw_needed") artist_widget:emit_signal("widget::layout_changed") end ) end artist_widget:emit_signal("widget::redraw_needed") artist_widget:emit_signal("widget::layout_changed") collectgarbage('collect') end ) end local update_volume_slider = function() awful.spawn.easy_async_with_shell( [[ mpc volume ]], function(stdout) local volume_slider = vol_slider.vol_slider if stdout:match('n/a') then return end volume_slider:set_value(tonumber(stdout:match('%d+'))) end ) end local check_if_playing = function() awful.spawn.easy_async_with_shell( [[ mpc status | awk 'NR==2' | grep -o playing ]], function(stdout) local play_button_img = media_buttons.play_button_image.play if not (stdout == nil or stdout == '') then play_button_img:set_image(widget_icon_dir .. 'pause.svg') update_volume_slider() else play_button_img:set_image(widget_icon_dir .. 'play.svg') end end ) end local check_repeat_status = function() awful.spawn.easy_async_with_shell( [[ mpc status | sed -n '/random/p' | cut -c23-24 | sed 's/^[ \t]*//' ]], function(stdout) local repeat_button_img = media_buttons.repeat_button_image.rep if stdout:match("on") then repeat_button_img:set_image(widget_icon_dir .. 'repeat-on.svg') else repeat_button_img:set_image(widget_icon_dir .. 'repeat-off.svg') end end ) end local check_random_status = function() awful.spawn.easy_async_with_shell( [[ mpc status | sed -n '/random/p' | cut -c37-38 | sed 's/^[ \t]*//' ]], function(stdout) local random_button_image = media_buttons.random_button_image.rand if stdout:match("on") then random_button_image:set_image(widget_icon_dir .. 'random-on.svg') else random_button_image:set_image(widget_icon_dir .. 'random-off.svg') end end ) end vol_slider.vol_slider:connect_signal( 'property::value', function() awful.spawn.easy_async_with_shell( 'mpc volume ' .. vol_slider.vol_slider:get_value(), function() end ) end ) local update_all_content = function() update_progress_bar() update_time_progress() update_time_duration() update_title() update_artist() update_cover() check_if_playing() check_repeat_status() check_random_status() update_volume_slider() end local startup_update_quota = 0 gears.timer.start_new(3, function() update_all_content() startup_update_quota = startup_update_quota + 1 if startup_update_quota <= 5 then return true else return false end end) gears.timer.start_new( 5, function() update_progress_bar() update_time_progress() return true end ) local mpd_startup = [[ # Let's make sure that MPD is running. if [ -z $(pgrep mpd) ]; then mpd; fi ]] local mpd_change_event_listener = [[ sh -c ' mpc idleloop player ' ]] local kill_mpd_change_event_listener = [[ ps x | grep "mpc idleloop player" | grep -v grep | awk '{print $1}' | xargs kill ]] awful.spawn.easy_async_with_shell( mpd_startup, function () awful.spawn.easy_async_with_shell( kill_mpd_change_event_listener, function () awful.spawn.with_line_callback( mpd_change_event_listener, { stdout = function(line) update_all_content() end } ) end ) end ) media_buttons.play_button:buttons( gears.table.join( awful.button( {}, 1, nil, function() awful.spawn.with_shell('mpc toggle') end ) ) ) media_buttons.next_button:buttons( gears.table.join( awful.button( {}, 1, nil, function() awful.spawn.with_shell('mpc next') end ) ) ) media_buttons.prev_button:buttons( gears.table.join( awful.button( {}, 1, nil, function() awful.spawn.with_shell('mpc prev') end ) ) ) media_buttons.repeat_button:buttons( gears.table.join( awful.button( {}, 1, nil, function() awful.spawn.easy_async_with_shell( 'mpc repeat', function () check_repeat_status() end ) end ) ) ) media_buttons.random_button:buttons( gears.table.join( awful.button( {}, 1, nil, function() awful.spawn.easy_async_with_shell( 'mpc random', function () check_random_status() end ) end ) ) )