MocPList - Enfileirador de áudio e locutor em voz sintetizada
Publicado por Khayla Elias dos Santos (última atualização em 21/02/2019)
[ Hits: 3.059 ]
Homepage: https://linktr.ee/khayla.elias
Download 1549117671.mocplist-1.19.83 (versão 2)
MocPlist é um cliente enfileirador randômico de mídias de áudio para o serviço MOC Player que permite gerar "playlists" baseando-se nas Info Tags dos arquivos de mídias. Além disso, é um locutor em voz sintetizada com diversos recursos como anúncio do título da mídia em reprodução, das horas local e do estado da caixa de email. Mais informações, nas primeiras linhas comentadas do script.
Versão 2 - Enviado por Khayla Elias dos Santos em 02/02/2019
Changelog: Versão 1.19.83 do MocpList Enfileirador automático para o Moc Player.
Novidades:
- Inclusão de arquivo de cache para agilizar novas pesquisas.
- Alteração no algoritmo e na estrutura de dados para acelerar a pesquisa. Esta mudança visa a reduzir principalmente o custo da geração dos índices randômicos na medida em que estes se tornam mais raros de serem gerados.
- Maior confiabilidade no processo de enfileiramento e inclusão de um indicador de número de falhas de arquivos não enfileirados.
- Melhoria dos recursos já implementados.
Download 1549117671.mocplist-1.19.83
#!/bin/bash
# === M O C P L I S T - M o c P l a y l i s t V e r s ã o 1 . 1 9 =================================================
#
# DESCRIÇÃO:
#
# Cliente enfileirador de mídias de áudio para o serviço MOC Player e locutor em voz sintetizada com as seguintes
# características:
#
# - Indentifica informações (tags) da mídia em reprodução no Moc Player.
# - Permite o uso de palavras chaves (padrões de busca) para pesquisa e seleção de mídias que casem com
# as expressões fornecidas pelo usuário.
# - Seleciona as mídias aleatoriamente e as enfileira criando um novo playlist ou ao já existente.
# - Utilizá-se das tags contidas nas mídias e/ou do nome do arquivo destas no processo de enfileiramento.
# - Auto-enfileiramento de mídias quando o tocador está ocioso.
# - Locutor(a) em voz sintetizada para anunciar:
#
# + Título da mídia
# + As horas da máquina local
# + Alguma mensagem de difusão fornecida pelo usuário (broadcast)
# + O número de mensagens não lidas da caixa de email (via fetchmail)
# + Sobre o programa e do tocador
#
#
# NOTAS:
#
# 1) A pesquisa deve ser feita preenchendo-se alguns dos seguintes campos na janela de diálogo:
#
# + Artista/Banda
# + Título
# + Álbum
# + Ano
# + Gênero
# + Outros
#
# 2) No campo 'Outros' pode-se fornecer uma expressão livre que, por sua vez, pode casar com uma tag específica
# (fornecendo-se o padrão adequado da mesma) ou com quaisquer outras pré-filtradas ou, ainda, com o nome do
# arquivo.
#
# 3) A INTERSEÇÃO de casamentos de padrões ocorrerá se houver sucesso no casamento de cada um dos campos
# acima. Note que, com essa regra, cada mídia selecionada CASA COM TODOS OS CAMPOS, inclusive os vazios (veja
# exemplos 1 à 4 abaixo).
#
# 4) A UNIÃO de casamentos de padrões pode ser obtida utilizando-se "Expressões Regulares" (REGEX) separando
# os padrões com o operador OU (o caractere "|"). Note que, com essa regra, cada mídia selecionada CASA COM
# ALGUM DOS PADRÔES fornecidos num determinado campo (exemplos 3 e 4 abaixo).
#
# 5) O pŕe-filtro de busca contém as seguintes tags:
#
# Id3v1: Artist, Year, Genre, Title, Album, Comment.
# Id3v2: TP1, TALB, TYE, TCON, TCOM, TIT, TPE, TOLY, TOPE, TEXT, COMM.
#
# 6) A cada mídia selecionada durante o processo de enfileiramento, um segmento de mídias vizinhas também é
# pesquisado para enfileirar um conjunto de mídias que também casam com as palavras chaves fornecidas pelo
# usuário. A relação de vizinhança se dá na proximidade da árvore do subdiretório que elas pertencem.
#
#
#
# PRÉ-REQUISITOS:
#
# Os pacotes dos seguintes programas devem estar instalados para o funcionamento adequado deste script:
#
# - MOC: Tocador de áudio em console (Music On Console Player).
# - ID3V2: Editor de tags id3v2 em linha de comando.
# - DIALOG: Exibe caixas de diálogo amigáveis ao usuário em scripts shell.
# - ESPEAK: Locutor multilíngue em voz sintetizada.
# - FETCHMAIL: Fetch mail from a POP, IMAP, ETRN, or ODMR-capable server (opcional).
# - FORTUNE: Print a random, hopefully interesting, adage (opcional).
#
#
#
# OPÇÕES:
#
# --update, -u: Atualiza a lista de mídias. Sempre que houver alteração no diretório padrão de músicas é
# necessário iniciar a execução da seguinte forma:
#
# mocplist --update
#
#
# --help, -h: Ajuda básica para executar este script.
#
#
# --about: Exibe estas informações sobre e de ajuda.
#
#
# --reset-theme: restaura o arquivo de configurações do tema do dialog na home do usuário.
#
#
#
# TECLAS DE CONTROLE DA TELA PRINCIPAL:
#
# a: Ativa/desativa o enfileiramento AUTOMÁTICO quando o tocador estiver ocioso.
# b: Toca a mídia ANTERIOR no Moc Player.
# i: Exibe INFO TAGS da mídia em reprodução e que podem ser usadas para pesquisa.
# h: Ajuda.
# l: ADICIONA novas mídias ao playlist atual sem limpá-lo.
# m: Exibe informações da caixa de EMAIL (INBOX).
# n: Toca a PRÓXIMA mídia no Moc Player.
# p: PAUSA/DESPAUSA a mídia em reprodução.
# q: ENCERRA o programa.
# r: Exibe RELATÓRIO da lista de mídias contidas no diretório padrão de músicas.
# s: Permite alterar as CONFIGURAÇÕES básicas.
# L: LIMPA o playlist atual e ADICIONA novas mídias.
# ,: REDUZ o volume 5%.
# .: AUMENTA o volume 5%.
#
#
#
# EXEMPLOS DE USO DE PADRÕES DE BUSCA:
#
#
# 1) Para pesquisar e enfileirar músicas do álbum Falso Brilhante da cantora Elis Regina, basta preencher
# os campos abaixo e deixar os demais vazios:
#
# Artista/banda: Elis Regina
# Álbum: Falso Brilhante
#
# 2) Para obter uma busca mais refinada, pode-se utilizar das "Expressões Regulares". Por exemplo, se quiser buscar
# mídias do gênero Progressive Rock entre os anos de 2010 à 2018, pode-se fornecer as expressões abaixo:
#
# Ano: 201[0-8]
# Gênero: progressive rock
#
# 3) Buscando e enfileirando músicas da banda Sepultura OU Slayer OU Iron Maiden dos anos de 1983 à 1985:
#
# Artista/banda: sepultura|slayer|iron maiden
# Ano: 1983|1984|1985
#
# 4) Para um casamento independente das tags, pode-se usar exclusivamente o campo 'Outros' da seguinte forma:
#
# Outros: techno|Kraftwerk|19[7-9][0-9]
#
# Neste caso, serão enfileirados áudios que contém alguma tag com a expressão "techno" OU "Krafwerk" OU números
# entre 1970 à 1999. Além das tags, vale ressaltar que o nome do arquivo também será usado para o casamento
# de padrões no uso do campo 'Outros'.
#
#
#
# COMENTÁRIOS:
#
# - A busca será mais precisa quanto melhor se utilizar das "Expressões Regulares" para casamento de
# padrões de busca.
#
#
#
# POR: Khayla Elias dos Santos (Alexandre)
# Email: avezdopinguim@gmail.com
# DATA: Julho 2009
# ATUALIZADO EM: Fevereiro 2018
# PLATAFORMA DE TESTE: Linux, Ubuntu 14.04
#
# "Ela virá, a revolução conquistará a todos o direito não somente ao pão, mas, também, a poesia." (Leon Trotsky)
#
# ============================================================================================================================
# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#
# ESQUEMA DE PESQUISA E PARTICIONAMENTO DA LISTA DE MÍDIAS:
#
# VETOR COM ÍNDICES DA LISTA DE MÍDIAS:
#
# 1 2 3 n
# [...+......<...+.+..+....++.>..+.....+...+..]
# ^ ^
# |....segmento....|
# ponteiro ponteiro
# inicial final
# (randômico)
#
#
#
# PARTICIONAMENTO RANDOMICO DO VETOR A CADA ITERAÇÃO:
#
#
# NÃO PARTICIONADO PÓS PARTICIONADO
# (com índices sujeito a pesquisa) (com índices pesquisados)
#
# 0 [..............<???>....] []
# 1 [...<???>..........] [(...)]
# 2 [.....<???>....] [(...)(...)]
# 3 [...<???>..] [(...)(...)(...)]
# . . .
# . . .
# . . .
# 20 [] [(...)(...)(...) ... (...)]
# P0 P1 P2 P20
#
#
#
# LEGENDA:
#
# (.) Índice de uma mídia qualquer da lista
# (+) Índice de mídia que casam com os padrões de busca
# (1 - n) Índices de mídias vizinhas que serão enfileirados
# (?) Indices de mídias sujeitas a serem pesquisadas
# (< >) Índices limitadores do segmento (vizinhança) a ser pesquisado
# (P0 - P20) Partições pesquisadas
#
# ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# === P A R Á M E T R O S D E E N T R A D A =============================================================================
UPDATE="$1" # 1) --update ou --report ou --reset-theme ou --help ou --about
shopt -s -o nounset # disallow undefined variables
# === D E C L A R A Ç Ã O D E C O N S T A N T ES =========================================================================
# NOME DO PROCESSO:
declare -r SCRIPT=`basename $0`
declare -r PROG=`echo $SCRIPT | sed 's/\.sh$//'`
declare -r LOCATE="`ps aux|grep ".*bash.*${SCRIPT}"|grep -v "grep"|head -1 |sed "s;^.*/bin/bash ;;"|sed "s; -.*$;;"`" # local
# ARQUIVOS E DIRETÓRIOS:
declare -r BASE=$HOME/.mocplist # diretório de arquivos do script
declare -r MUSICA=$HOME/Música # diretório raiz de áudios
declare -r TEMP=/var/tmp/$SCRIPT # diretório de arquivos temporários
declare -r LOG=$BASE/$SCRIPT.log # arquivo de log do script
declare -r FICHEIROS=$BASE/media-list # lista de todas mídias para pesquisas
declare -r INDEX=$TEMP/indices # índices de mídias a serem pesquisadas
declare -r CHECKEDS=$TEMP/checkeds # índices de mídias pesquisadas (partições)
declare -r WORDS_EN=$BASE/words-en # lista de expressões para eleger idioma inglês
declare -r WORDS_ES=$BASE/words-es # lista de expressões para eleger idioma espanhol
declare -r CONF=$BASE/mocplist.conf # arquivo de configuração
declare -r GENRE_LIST=$BASE/genre.txt # lista de gêneros musicais
declare -r REPORT=$BASE/report-medias.txt # Relatório de mídias contidas em MUSICA
declare -r DATA_MEDIA=$TEMP/data-media # dados da mídia em reprodução
declare -r DATA_ID3=$TEMP/dataID3 # tags id3 da mídia em reprodução
declare -r TOT_FILA=$TEMP/tt-fila # número de enfileirados
declare -r PERC_OUT=$TEMP/perc-out # percentual geral de arquivos varridos
declare -r TT_VARRIDOS=$TEMP/tt-varridos # total acumulado de ficheiros varridos
declare -r SINAL=$TEMP/sinal # flag de interrupção de enfileiramento
declare -r CHMAIL=$BASE/mail.$USER # arquivo de saída do fetchmail
# === A R Q U I V O S E C O N S T A N T E S R E L A T I V O S A O P R O C E S S O ==================================
declare -r VERSAO="Version 1.19"
declare -r TMP_PID=$TEMP/$SCRIPT.pid # pid deste script
declare -r SUB_PID=$TEMP/${SCRIPT}.sub.pid # pid da rotina de enfileiramento em segundo plano
declare -r TMP_LOG=$TEMP/${SCRIPT}_$$.log # log temporário do script em execução
declare -r TMP_TRUNC=$TEMP/${SCRIPT}_$$.trunc # log temporário auxilar
declare -ir MAX_RETIDO=5000 # tamanho máximo do arquivo de log
# === C O N S T A N T E S G E R A I S ======================================================================================
declare -ri PROB=50 # (%) # probabilidade de difusão das horas do host
declare -ri INTERVAL=12 # intervalo de checagem de email (minutos modular)
declare -r UPDATE=${UPDATE:=null} # ativa atualização da lista de 'media-list'
declare -r FRASE_EN="Music On Console Player: " # pronúncia em inglês
declare -r FRASE_PT="Míusic On Console Player: " # pronúncia em português
declare -r FRASE_OP="M.O.C Playlist, enfileiramento de áudio configurável." # frase default
declare -a DICA=("<artist>" "<title>" "<album>" "<year>" "<genre>" "<others>")
# === V A R I Á V E I S I N T E I R A S ====================================================================================
declare -i PID_SPK=99999 # pid do locutor em segundo plano
declare -i MAX_FILA=0 # número de mídias a enfileirar
declare -i VIZINHOS=0 # número de mídias vizinhas a enfileirar
declare -i SECAO=0 # tamanho a ser varrido do seguimento da lista
declare -i REFRESH=0 # set de retorno de atualização da tela principal
declare -i TT_FICHEIROS=0 # Total de mídias na lista de mídias
declare -i BEFORE_MINUTE=0 # minuto obtido na checagem de email
declare -i AFTER_MINUTE=-1 # minuto passado pos checagem de email
declare -i TOT_MAIL=0 # total de mensagens na caixa de entrada
declare -i NEW_MAIL=0 # ńumero de mensagens não lidas
# === V A R I Á V E I S L I T E R A I S ====================================================================================
# FILTRO para pesquisa baseado na saída do programa id3v2:
declare -r FILTRO="id3v|ID3|^Title|^Album|^Comment|\
^TP1|^TALB|^TYE|^TCON|^TCOM|^TIT|^TPE|^TOLY|^TOPE|^TEXT|^COMM"
declare -a PADRAO=("" "" "" "" "" "") # expressões regulares utilizadas nas buscas id3v2
TALK= # ativa/desativa locutor em voz sintetizada
DIFUSAO= # ativa/desativa anúncio de mensagens
VOZ="off" # idioma default do locutor
CHK_MAIL= # ativa checagem de email
MENSAGEM= # mensagem de difusão (broadcast)
COMANDO= # comando gerador de texto
TECLA= # entrada de comandos (teclas de controle da tela principal)
ARTIST= # artista da mídia em reprodução
SONG_TITLE= # titulo da mídia em reprodução
TITLE= # título unificado da mídia
GENRE= # género da mídia em reprodução
YEAR= # ano da mídia em reprodução
ALBUM= # álbum da mídia em reprodução
TRACK= # track da mídia em reprodução
TRACK0= # track passado
TRACK1= # track checked
MODO= # estado do tocador (barra de título)
GMAIL= # endereço de email obtido pelo fetchmail
FRAME_ART= # dicas do dialog
FRAME_TIT= # //
FRAME_ALB= # //
FRAME_YER= # //
FRAME_CON= # //
FRAME_ALL= # //
AUTO="no-auto" # ativa/desativa enfileramento automático
TEXTO=" MocpList - $VERSAO\n\nBy: Khayla Elias dos Santos \
\nEmail: avezdopinguim@gmail.com\n\n \
<3\"(: Uma dedicação do Pinguim à amada Sabiá" # créditos do desenvolverdor
SELECAO= # auxiliar para formatar padrões de busca
# === F U N Ç Õ E S ==========================================================================================================
function help_fn(){
if [ "$#" != 0 ]; then
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
printf "MocpList - $VERSAO\n\n"
printf "This is searcher in data id3v2 tag and enqueuer list to moc player server.\n\n"
printf "Use:\t$SCRIPT [ --about | <--update> | <-u> | <--help> | <-h> ]\n\n"
exit
else if [ "$1" != "--update" ] && [ "$1" != "-u" ] && [ $1 != "--about" ] && [ "$1" != "--reset-theme" ]; then
printf "Erro: opção inválida.\nUse '$SCRIPT --help' para ajuda.\n"
exit 1
else if [ "$1" = "--about" ]; then
head -200 $LOCATE|sed -e "s;^#;;" -e "/^\!/d"|less
exit
fi # about
fi # opções
fi # help and check parameters
fi # Help and check parameters
} # help_fn - help and check parameters
function fn_fim_script(){
tail -$MAX_RETIDO $LOG > $TMP_TRUNC
echo "$PROG: pid $$", início de linhas ===== >> $TMP_TRUNC
cat $TMP_LOG >> $TMP_TRUNC
mv $TMP_TRUNC $LOG
# extermina processo em segundo plano
[ "`cat $SUB_PID`" -gt 0 ] && kill -9 `cat $SUB_PID`
# Remoção de arquivos temporários:
cd $TEMP; rm -f ./*
tput cnorm; reset
} # fn_fim_script - tratamento de encerramento
function fn_trap(){
#fn_erro N "$PROG: Interrupção forçada"
fn_fim_script &>/dev/null
exit 2
} # fn_trap - tratamento de interrupções
function check_sanity(){
if ! ( type -a mocp 2>/dev/null|grep -q "/mocp" ); then
printf "\r`basename $0`:$LINENO: the command 'mocp' is not available\naborting\n" >&2
exit 1
fi # check mocp
if ! ( type -a dialog 2>/dev/null|grep -q "/dialog" ); then
printf "\r`basename $0`:$LINENO: the command 'dialog' is not available\naborting\n" >&2
exit 1
fi # check dialog
if ! ( type -a id3v2 2>/dev/null|grep -q "/id3v2" ); then
printf "\r`basename $0`:$LINENO: the command 'id3v2' is not available\naborting\n" >&2
exit 1
fi # check id3v2
if ! ( type -a espeak 2>/dev/null|grep -q "/espeak" ); then
printf "\r`basename $0`:$LINENO: the command 'espeak' is not available\naborting\n" >&2
exit 1
fi # check espeak
[ -d "$TEMP" ] || mkdir $TEMP
if [ -s "$TMP_PID" ]; then
PID=`cat $TMP_PID`
if ps -p $PID 2> /dev/null >&2; then
echo "$PROG: Uma instância deste programa já está em execução. PID=$PID." >&2
exit 3
fi
else echo $$ > $TMP_PID
rm -f $TMP_LOG &>/dev/null
fi # garante a execucão de uma única instância
} # check_sanity - verificações pré-eliminares
function reset_theme(){
[ "$UPDATE" = "--reset-theme" ] && dialog --create-rc $HOME/.dialogrc
} # reset_theme - recria arquivo do tema
function check_files(){
# cria diretório do aplicativo na home do usuário
[ -d "$BASE" ] || mkdir $BASE
# padrões básicos para eleger idioma inglês (inclui o subdiretório Internacionais)
[ ! -f "$WORDS_EN" ] && \
printf ".*/M[úu]sica/Internacionais/\nabout[,.!?]*\n^all,* | all,* | all[.!?]*$\n^are,* | are,* | are[.!?]*$\neyes,* | eyes,* | eyes[.!?]*\n^in,* | in,* | in[.!?]*$\n^it,* | it,* | it[.!?]*$\n^how,* | how,* | how[.!?]*$\nlike[,.!?]*\n^m[ae]n,* | m[ae]n,* | m[ae]n[.!?]*$\n^of,* | of,* | of[.!?]*$\n^off,* | off,* | off[.!?]*$\n^on,* | on,* | on[.!?]*$\n^one,* | one,* | one[.!?]*$\n^she,* | she,* | she[.!?]*$\n^the,* | the,* | the[.!?]*$\nthey[,.!?]*\n^we,* | we,* | we[.!?]*$\nwhen,* | when,* |when[.!?]*\nwom[ae]n[,.!?]*\nwitho*[,.!?]*\nyear,* | year,* |year[.!?]*\nyou,* | you,* | you[.!?]*\n^up,* | up,* | up[.!?]*$\n" > $WORDS_EN
# padrões básicos para eleger idioma espanhol (inclui o subdiretório Latinas)
[ ! -f "$WORDS_ES" ] && \
printf ".*/M[úu]sica/Latinas/\n.*ción[,.!?]*\ncoraz[óo]n[,.!?]*\n^cuanto,* | cuanto,* | cuanto[.!?]*$\n^el,* | el,* | el[.!?]*$\nestoy[,.!?]*\n^gustas*,* | gustas*,* | gustas*[.!?]*$\nhasta,* | hasta[.!?]*\nhola,* | hola,* | hola[.!?]*$\nhombres*[,.!?]*\n^hoy,* | hoy,* | hoy[.!?]*$\ninmortal[,.!?]*\nlibertad[,.!?]*\nllorar[,.!?]*\nmío,* | mío[.!?]*\nmujer[,.!?]*\nnecesito[,.!?]*\nquier.,* | quier.[.!?]*\nsoledad[,.!?]*\ntengo,* | tengo[.!?]*\ntiempo[,.!?]*\n^un,* | un,* | un[.!?]*$\n^un[ao],* | un[ao],* | un[ao][.!?]*$\nusted[,.!?]*\nvivir[,.!?]*\n" > $WORDS_ES
[ ! -f "$CONF" ] &&(
printf "# MocpList - Configurações gerais\n\n" > $CONF
printf "# Ativa/desativa locutor em voz sintetizada\n" >>$CONF
printf "TALKER = on\n\n" >>$CONF
printf "# Ativa/desativa difusão de mensagens\n" >>$CONF
printf "BROADCAST = on\n\n" >>$CONF
printf "# Tamanho máximo da lista de enfileiramento\n" >>$CONF
printf "TAM_FILA = 12\n\n" >>$CONF
printf "# Número de mídias vizinhas relação ao subdiretório\n" >>$CONF
printf "NEIGHBOR = 4\n\n" >>$CONF
printf "# Tamanho de cada segmento (vizinhança) pesquisado\n" >>$CONF
printf "NEIGHBORHOOD = 60\n\n" >>$CONF
printf "# Ativa/desativa checagem da caixa de email.\n" >>$CONF
printf "# É necessário que o Fetchmail esteja configurado.\n" >>$CONF
printf "MAIL = off\n\n" >>$CONF
printf "# Comando gerador de texto para difusão.\n" >>$CONF
printf "COMMAND = fortune\n\n" >>$CONF
printf "# Mensagem principal de difusão\n" >>$CONF
printf "MESSAGE = \"Ubuntu, Linux para seres humanos.\"\n" >>$CONF
) # cria arquivo de configuração
# lista de gêneros musicais
[ -f $GENRE_LIST ] || id3v2 -L >$GENRE_LIST
# variáveis arquivadas
echo 0 > $TOT_FILA
echo 0 > $PERC_OUT
echo -1 > $SUB_PID
} # check_files - verifica e (re)cria arquivo de configuração
function set_variables(){
local VALOR=
VALOR="`grep "^[ ]*TALKER[ ]*=" $CONF| sed -r 's/^[ ]*TALKER[ ]*=[ ]*([ONFonf]{2,3})[ ]*$/\1/'`"
case "$VALOR" in
on|ON)
TALK="on"
VOZ="on";;
off|OFF)
TALK="off"
VOZ="off";;
*)
TALK="on";;
esac # ativa/desativa LOCUTOR
VALOR="`grep "^[ ]*BROADCAST[ ]*=" $CONF| sed -r 's/^[ ]*BROADCAST[ ]*=[ ]*([ONFonf]{2,3})[ ]*$/\1/'`"
case "$VALOR" in
on|ON)
DIFUSAO="on";;
off|OFF)
DIFUSAO="off";;
*)
DIFUSAO="on";;
esac # ativa/desativa anúncio de MENSAGENS
VALOR="`grep "^[ ]*MAIL[ ]*=" $CONF| sed -r 's/^[ ]*MAIL[ ]*=[ ]*([onf]{2,3})[ ]*$/\1/'`"
case "$VALOR" in
on|ON)
CHK_MAIL="on";;
off|OFF)
CHK_MAIL="off";;
*)
CHK_MAIL="off";;
esac # ativa/desativa checagem de EMAIL
grep -q "^[ ]*TAM_FILA[ ]*=[ ]*[0-9]\{1,4\}[ ]*$" $CONF
if [ "$?" -eq 0 ]; then
MAX_FILA="`grep "^TAM_FILA[ ]*=[ ]*[0-9]\{1,4\}[ ]*$" $CONF| \
sed -r 's/^TAM_FILA.*=[ ]*([0-9]{1,4})[ ]*$/\1/; s/^00*//'`"
[ "${MAX_FILA:=0}" -eq 0 ] && MAX_FILA=12
else MAX_FILA=12
fi # determina Tamanho MÁXIMO do enfileiramento
grep -q "^[ ]*NEIGHBOR[ ]*=[ ]*[0-9]\{1,2\}[ ]*$" $CONF
if [ "$?" -eq 0 ]; then
VIZINHOS="`grep "^[ ]*NEIGHBOR[ ]*=[ ]*[0-9]\{1,2\}[ ]*$" $CONF| \
sed -r 's/^[ ]*NEIGHBOR[ ]*=[ ]*([0-9]{1,2})[ ]*$/\1/; s/^00*//'`"
[ "${VIZINHOS:=0}" -eq 0 ] && VIZINHOS=3
else VIZINHOS=3
fi # determina o número de VIZINHOS a enfileirar ao varrer o segmento
grep -q "^[ ]*NEIGHBORHOOD[ ]*=[ ]*[0-9]\{1,3\}[ ]*$" $CONF
if [ "$?" -eq 0 ]; then
SECAO="`grep "^[ ]*NEIGHBORHOOD[ ]*=[ ]*[0-9]\{1,3\}[ ]*$" $CONF| \
sed -r 's/^[ ]*NEIGHBORHOOD[ ]*=[ ]*([0-9]{1,3})[ ]*$/\1/; s/^00*//'`"
[ "${SECAO:=0}" -lt "$VIZINHOS" ] && SECAO=$VIZINHOS
else SECAO=50
fi # determinha tamanho de cada SEGMENTO a ser varrido
grep -q "^[ ]*MESSAGE[ ]*=" $CONF
if [ "$?" -eq 0 ]; then
MENSAGEM="`grep "^[ ]*MESSAGE[ ]*=" $CONF|sed "s/^[ ]*MESSAGE[ ]*=[ ]*//"|sed -r 's;"(.*)";\1;'`"
MENSAGEM=${MENSAGEM:=${FRASE_OP}}
fi # mensagem de DIFUSÃO
grep -q "^[ ]*COMMAND[ ]*=" $CONF
if [ "$?" -eq 0 ]; then
COMANDO="`grep "^[ ]*COMMAND[ ]*=" $CONF|sed "s/^[ ]*COMMAND[ ]*=[ ]*//"|sed -r 's;"(.*)";\1;'`"
else COMANDO=
fi # COMANDO para gerador de texto de DIFUSÃO
} # set_variables - configuração dos principais parâmetros
function report(){
local -i SUB_TOTAL=0
local -i TOTAL=0
printf "RELATÓRIO DE MÍDIAS - $HOSTNAME - `date`\n\n" > $REPORT
printf "Local:\t$MUSICA\n\n" >> $REPORT
TOTAL="`find -L $MUSICA/ -iname "*.mp3"| wc -l`"
printf "Mídias *.mp3:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.ogg"| wc -l`"
printf "Mídias *.ogg:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.wmv"| wc -l`"
printf "Mídias *.wmv:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.wav"| wc -l`"
printf "Mídias *.wav:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.wma"| wc -l`"
printf "Mídias *.wma:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.aac"| wc -l`"
printf "Mídias *.aac:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.flac"| wc -l`"
printf "Mídias *.flac:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.avi"| wc -l`"
printf "Mídias *.avi:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.mp4"| wc -l`"
printf "Mídias *.mp4:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.flv"| wc -l`"
printf "Mídias *.flv:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.ac3"| wc -l`"
printf "Mídias *.ac3:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
TOTAL="`find -L $MUSICA/ -iname "*.3gp"| wc -l`"
printf "Mídias *.3gp:\t$TOTAL\n" >> $REPORT
let SUB_TOTAL=SUB_TOTAL+TOTAL
printf "Total:\t\t$SUB_TOTAL\n" >> $REPORT
} # report - produz relatório de mídias contidas no diretório $MUSICA
function atualiza(){
if [ ! -f "$FICHEIROS" ] || [ "$UPDATE" = "--update" ] || [ "$UPDATE" = "-u" ]; then
local -r FRASE_CRED="`mocp -V |grep -E "This|Version|Run|Author|Home|Copy|License"`"
#=== C R E D I T O S =============================================
if [ "$TALK" = "on" ]; then
espeak -p0 -ven+f4 "About Player:" &>/dev/null
echo "$FRASE_CRED"|espeak -p0 -ven+us+m7 &>/dev/null&
local -i PID_SPK=$!
fi # =============================================================
dialog --stdout --no-collapse --cr-wrap \
--backtitle "Extração de ficheiros de áudios" \
--title "MocpList - Aguarde! Extraindo arquivos de mídias..." \
--infobox "About Player:\n\n`echo "$FRASE_CRED"| sed 's/ //'`\n" 0 0
# Extração de ficheiros ==========================================
find -L $MUSICA/ -iname "*.mp3"| sed "s;.*${MUSICA}/;;" > $FICHEIROS
find -L $MUSICA/ -iname "*.ogg"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.wav"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.wma"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.wmv"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.aac"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.ac3"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.mp4"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.avi"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.flv"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.3gp"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
find -L $MUSICA/ -iname "*.flac"| sed "s;.*${MUSICA}/;;" >> $FICHEIROS
# ================================================================
report& 2>>$TMP_LOG
sort $FICHEIROS > $FICHEIROS.tmp
mv $FICHEIROS.tmp $FICHEIROS
fi # cria ou atualiza a lista de mídias
# aguarda finalização do locutor:
while [ "`ps au| grep $PID_SPK|wc -l`" -gt 1 ]; do sleep 1 ;done
} # atualiza - Atualiza a lista de arquivos de mídias
function check_mail(){
dialog --stdout --title "MocpList - Fetchmail" \
--infobox "Checando ${GMAIL:=email}..." \
3 60
fetchmail -c > $CHMAIL.1 2>/dev/null
local -i RETORNO=$?
grep -q "INBOX" $CHMAIL.1 2>/dev/null
if [ "$?" = 0 ]; then
cp $CHMAIL.1 $CHMAIL
rm $CHMAIL.1
fi # atualiza arquivo
# obtém estado da inbox
GMAIL="`cut -d' ' -f6 $CHMAIL`"
TOT_MAIL="`cut -d' ' -f1 $CHMAIL`"
local -i VISTO="`cut -d' ' -f3 $CHMAIL|sed 's/[()]//g'`"
NEW_MAIL=$((${TOT_MAIL:=0} - ${VISTO:=-1}))
if [ "$RETORNO" -eq 11 ]; then
let NEW_MAIL=-1*$NEW_MAIL
fi
if [ "$NEW_MAIL" -gt 0 ] && [ "` mocp -Q "%state"`" != "PLAY" ] && [ "$TALK" = "on" ]; then
local S= # plural
[ "$NEW_MAIL" -gt 1 ] && S="s"
espeak -vpt+f4 "Você tem $NEW_MAIL email$S não lido$S." &>/dev/null
fi # anuncia número de emails não lidos
return $RETORNO
} # check_mail - faz checagem de email pelo fetchmail, retorna retorno do fetchmail.
function info_mail(){
local TEXT=$(printf "Checked at `ls -l $CHMAIL|sed 's/ */ /g'|cut -d' ' -f 6-8|sed -r 's/ [0-9][0-9]:/,&/'`" &2>/dev/null)
dialog --stdout --title "MocpList - Fetchmail" \
--backtitle "Informações da caixa de email ($GMAIL)" \
--msgbox "INBOX ($GMAIL): ${NEW_MAIL/-/!}/$TOT_MAIL\n$TEXT" \
6 60
} # info_mail - exibe informações da caixa de entrada.
function restart_player(){
dialog --stdout --sleep 5 \
--backtitle "Reiniciando serviço..." \
--title "Reiniciando o serviço Moc Player..." \
--infobox "$(printf "`mocp -S`")" 0 0
} # restart_player - reinicia serviço moc player
function setup(){
local -i RETORNO=3 # retorno do dialog
local -i LINHAS=0 # número de entradas
local VALUES= # entradas do dialog
# === Alteração do Arquivo de Configuração - Entradas ==================================================
while [ "$RETORNO" -eq 3 ]; do
VALUES=$(dialog --stdout --ok-label "Ok" \
--extra-button --extra-label "File Setup" \
--backtitle "Configurações - Alteração de parâmetros" \
--title "MocpList - Configurações" \
--form "Modifique os campos abaixos conforme a sua escolha:" \
0 0 0 \
"Quantidade de mídias (1-9999):" 1 1 "$MAX_FILA" 1 37 45 4 \
"Mídias com proximidades (1-99):" 2 1 "$VIZINHOS" 2 37 45 2 \
"Tamanho de cada seção (1-99):" 3 1 "$SECAO" 3 37 45 2 \
"Locutor (on/off):" 4 1 "$TALK" 4 37 45 3 \
"Difusão (on/off):" 5 1 "$DIFUSAO" 5 37 45 3 \
"Checagem de email (on/off):" 6 1 "$CHK_MAIL" 6 37 45 3 \
"Comando gerador de texto (difusão):" 7 1 "$COMANDO" 7 37 45 60 \
"Mensagem principal de difusão:" 8 1 "$MENSAGEM" 8 37 45 60)
RETORNO="$?"
if [ "$RETORNO" = 3 ]; then
dialog --stdout \
--title "Configurações ($CONF)" \
--backtitle "Arquivo de configurações" \
--textbox $CONF \
0 0
VALUES=
fi # exibe arquivo de configuração
LINHAS="`printf "$VALUES\n"|wc -l`"
[ -z "$VALUES" ] && LINHAS=0
done # alteração do arquivo de configuração - entradas =================================================
# === Filtragem e Armazenamento Dos Valores ============================================================
if [ "$LINHAS" -gt 0 ]; then
local -a LABELS=("TAM_FILA" "NEIGHBOR" "NEIGHBORHOOD" "TALKER" "BROADCAST" "MAIL" "COMMAND" "MESSAGE")
local -a VALORES=("$MAX_FILA" "$VIZINHOS" "$SECAO" "$TALK" "$DIFUSAO" "$CHK_MAIL" "$COMANDO" "$MENSAGEM")
local -i TAM=$(cat $CONF|wc -l) # número de linhas do arquivo de configuração
local -i NUMBER_LINE=0 # posição da linha no arquivo
local SELECT="`printf "$VALUES\n"|head -1|grep "^[0-9]*$"|sed 's/^00*//'`" # entrada selecionada
if [ "${SELECT:=0}" -gt 0 ]; then
MAX_FILA=$SELECT
VALORES[0]=$SELECT
fi # set MAX_FILA
if [ "$LINHAS" -ge 2 ]; then
SELECT="`printf "$VALUES\n"|head -2|tail -1|grep "^[0-9]*$"|sed 's/^00*//'`"
if [ "${SELECT:=0}" -gt 0 ]; then
VIZINHOS=$SELECT
VALORES[1]=$SELECT
fi
fi # set VIZINHOS
if [ "$LINHAS" -ge 3 ]; then
SELECT="`printf "$VALUES\n"|head -3|tail -1|grep "^[0-9]*$"|sed 's/^00*//'`"
if [ "${SELECT:=0}" -gt 0 ]; then
[ "$SELECT" -lt "$VIZINHOS" ] && SELECT=$VIZINHOS
SECAO=$SELECT
VALORES[2]=$SELECT
fi
fi # set SECAO
if [ "$LINHAS" -ge 4 ]; then
SELECT="`printf "$VALUES\n"|head -4|tail -1`"
case "$SELECT" in
on|ON)
TALK="on"; VOZ="on"
VALORES[3]="on";;
off|OFF)
TALK="off"; VOZ="off"
VALORES[3]="off";;
esac
fi # set TALK on/off
if [ "$LINHAS" -ge 5 ]; then
SELECT="`printf "$VALUES\n"|head -5|tail -1`"
case "$SELECT" in
on|ON)
DIFUSAO="on"
VALORES[4]="on";;
off|OFF)
DIFUSAO="off"
VALORES[4]="off";;
esac
fi # set DIFUSAO on/off
if [ "$LINHAS" -ge 6 ]; then
SELECT="`printf "$VALUES\n"|head -6|tail -1`"
case "$SELECT" in
on|OFF)
CHK_MAIL="on"
VALORES[5]="on";;
off|OFF)
CHK_MAIL="off"
VALORES[5]="off";;
esac
fi # set CHK_MAIL on/off
if [ "$LINHAS" -ge 7 ]; then
SELECT="`printf "$VALUES\n"|head -7|tail -1`"
type "`echo $SELECT|sed "s; .*$;;"`" &>/dev/null
if [ "$?" = 0 ]; then
COMANDO=$SELECT
VALORES[6]=$SELECT
else VALORES[6]=
fi
fi # set COMANDO
if [ "$LINHAS" -eq 8 ]; then
MENSAGEM="`printf "$VALUES\n"|tail -1`"
VALORES[7]=""$MENSAGEM""
else VALORES[7]=
MENSAGEM=
fi # set MENSAGEM
cp $CONF $CONF.1
for i in $(seq 0 $((${#LABELS[@]}-1))); do
NUMBER_LINE=$(cat $CONF.1| grep -n "^${LABELS[$i]}[ ]*=.*"|tail -1|cut -f1 -d: 2>>$TMP_LOG)
if [ -z "$NUMBER_LINE" ] || [ "$NUMBER_LINE" -eq 0 ]; then
let TAM++
NUMBER_LINE=$TAM
fi # add line
head -$(($NUMBER_LINE - 1)) $CONF.1 >$CONF.2
if [ "$i" -eq "$((${#LABELS[@]}-1))" ]; then
printf "${LABELS[$i]} = \"${VALORES[$i]}\"\n" >>$CONF.2
else printf "${LABELS[$i]} = ${VALORES[$i]}\n" >>$CONF.2
fi # insere aspas (") como separador de texto em BROADCAST
tail -$(($TAM - $NUMBER_LINE)) $CONF.1 >>$CONF.2
mv $CONF.2 $CONF.1
done # edita o arquivo de configuração
mv $CONF.1 $CONF
fi # filtragem e armazenamento dos valores =============================================================
return $RETORNO
} # setup - permite a reconfiguração de parâmetros de busca, retorna retorno do dialog.
function split_std(){
local TEXT="`echo "$3"|sed "s;|;\n;g"`\n"
local STRING=
local -i TAM=`printf "$TEXT"|wc -l`
local -i i
SELECAO=
for i in `seq 1 $TAM`; do
STRING="`printf "$TEXT"|head -${i}|tail -1`"
SELECAO="$SELECAO|$1.*$STRING.*|$2.*$STRING.*"
done
SELECAO="`echo "$SELECAO"|sed "s;^|;;"`"
} # split_std - formata padrões de busca de acordo com os campos a serem usados
function change_profile(){
local -i RETORNO=3 # retorno do dialog
local -i LINHAS=0 # número de entradas
local ENTRADA= # entradas do dialog
local FRAME_ART_CP="$FRAME_ART" # cópias de restauração de valores
local FRAME_TIT_CP="$FRAME_TIT" # //
local FRAME_ALB_CP="$FRAME_ALB" # //
local FRAME_YER_CP="$FRAME_YER" # //
local FRAME_CON_CP="$FRAME_CON" # //
local FRAME_ALL_CP="$FRAME_ALL" # //
while [ "$RETORNO" -eq 3 ]; do # ==========================================================
ENTRADA=$(dialog --stdout --ok-label "Ok" \
--extra-button --extra-label "Genre List" \
--title "$1" \
--backtitle "MocpList - Busca e Enfileiramento" \
--form "Forneça expressões que combinem com a busca desejada:" \
0 0 0 \
"Artista, Banda:" 1 1 "${FRAME_ART:-${DICA[0]}}" 1 18 50 99 \
"Título:" 2 1 "${FRAME_TIT:-${DICA[1]}}" 2 18 50 99 \
"Álbum:" 3 1 "${FRAME_ALB:-${DICA[2]}}" 3 18 50 99 \
"Ano:" 4 1 "${FRAME_YER:-${DICA[3]}}" 4 18 50 99 \
"Gênero:" 5 1 "${FRAME_CON:-${DICA[4]}}" 5 18 50 99 \
"Outros:" 6 1 "${FRAME_ALL:-${DICA[5]}}" 6 18 50 99 \
)
RETORNO="$?"
if [ "$RETORNO" = 3 ]; then
dialog --stdout \
--title "Genres List" \
--backtitle "MocpList - Lista de códigos dos gêneros músicais" \
--textbox $GENRE_LIST \
0 0
ENTRADA=
fi
LINHAS="`printf "$ENTRADA\n"|wc -l`"
[ -z "$ENTRADA" ] && LINHAS=0
done # alteração das variáveis de casamento de padrão ======================================
# === Filtragem de entradas ================================================================
if [ "$LINHAS" -gt 0 ]; then
# seleção de entrada:
local SELECT="`printf "$ENTRADA\n"|head -1|sed 's/[ ][ ]*/ /g; s/[ ][ ]*$//'`"
[ "$SELECT" = "${DICA[0]}" ] && SELECT=""
FRAME_ART="$SELECT"
if [ -z "$SELECT" ]; then
PADRAO[0]=
else #PADRAO[0]="Artist: .*$SELECT.* |^TPE.*: .*$SELECT.*$"
split_std "Artist: " "^TPE.*: " "$SELECT"
PADRAO[0]="$SELECAO"
fi # formatação 'artista/banda'
if [ "$LINHAS" -ge 2 ]; then
SELECT="`printf "$ENTRADA\n"|head -2|tail -1|sed 's/[ ][ ]*/ /g; s/[ ][ ]*$//'`"
[ "$SELECT" = "${DICA[1]}" ] && SELECT=""
if [ -z "$SELECT" ]; then
PARDAO[1]=
else split_std "Title: " "^TIT.*: " "$SELECT"
PADRAO[1]="$SELECAO"
fi
FRAME_TIT="$SELECT"
else FRAME_TIT=
fi # formatação 'título'
if [ "$LINHAS" -ge 3 ]; then
SELECT="`printf "$ENTRADA\n"|head -3|tail -1|sed 's/[ ][ ]*/ /g; s/[ ][ ]*$//'`"
[ "$SELECT" = "${DICA[2]}" ] && SELECT="" && FRAME_ALB=""
if [ -z "$SELECT" ]; then
PADRAO[2]=
else split_std "Album: " "^TALB.*: " "$SELECT"
PADRAO[2]="$SELECAO"
fi
FRAME_ALB="$SELECT"
else FRAME_ALB=
fi # Formatação 'álbum'
if [ "$LINHAS" -ge 4 ]; then
SELECT="`printf "$ENTRADA\n"|head -4|tail -1|sed 's/[ ][ ]*/ /g; s/[ ][ ]*$//'`"
[ "$SELECT" = "${DICA[3]}" ] && SELECT=""
if [ -z "$SELECT" ]; then
PADRAO[3]=
else split_std "Year: " "^TYER.*: " "$SELECT"
PADRAO[3]="$SELECAO"
fi
FRAME_YER="$SELECT"
else FRAME_YER=
fi # Formatação 'ano'
if [ "$LINHAS" -ge 5 ]; then
SELECT="`printf "$ENTRADA\n"|head -5|tail -1|sed 's/[ ][ ]*/ /g; s/[ ][ ]*$//'`"
[ "$SELECT" = "${DICA[4]}" ] && SELECT=""
if [ -z "$SELECT" ]; then
PADRAO[4]=
else split_std "Genre: " "^TCON.*: " "$SELECT"
PADRAO[4]="$SELECAO"
fi
FRAME_CON="$SELECT"
else FRAME_CON=
fi # Formatação 'gênero'
if [ "$LINHAS" -eq 6 ]; then
SELECT="`printf "$ENTRADA\n"|tail -1|sed 's/[ ][ ]*/ /g; s/[ ][ ]*$//'`"
[ "$SELECT" = "${DICA[5]}" ] && SELECT=""
if [ -z "$SELECT" ]; then
PADRAO[5]=
else PADRAO[5]="`echo $SELECT|sed 's/^|//g; s/|$//g'`"
fi
FRAME_ALL="$SELECT"
else FRAME_ALL=
fi # Formatação 'outros'
else FRAME_ART="$FRAME_ART_CP"
FRAME_TIT="$FRAME_TIT_CP"
FRAME_ALB="$FRAME_ALB_CP"
FRAME_YER="$FRAME_YER_CP"
FRAME_CON="$FRAME_CON_CP"
FRAME_ALL="$FRAME_ALL_CP"
fi # filtragem de entradas =================================================================
return $RETORNO
} # change_profile - permite alterar o perfil do padrão de busca, retorna retorno do dialog.
function set_voice(){
local TEXT="$1" # texto a ser analisado
local -i TAM=`cat $WORDS_ES|wc -l` # tamanho do arquivo com expressões em alguma língua
local -i SUM_ES=0 # quantidade de expressões em espanhol encontrada
local -i SUM_EN=0 # quantidade de expressões em inglês encontrada
local -i x=0 # aux. de iteração
local WORD= # expressão regular de um idioma
[ -z "$TEXT" ] && return 0
for x in $(seq 1 $TAM); do
WORD="`head -$x $WORDS_ES|tail -1`"
echo "$TEXT"|grep -qiE "$WORD" && let SUM_ES++
done # conta ocorrência de expressões em espanhol
TAM=`cat $WORDS_EN|wc -l`; SUM_EN=0
for x in $(seq 1 $TAM); do
WORD="`head -$x $WORDS_EN|tail -1`"
echo "$TEXT"|grep -qiE "^$WORD" && let SUM_EN++
done # conta ocorrência de expressões em inglês
# ingles=$SUM_EN; espanhol=$SUM_ES ### depurando...
if [ "$(($SUM_ES + $SUM_EN))" -gt 0 ]; then
if [ "$SUM_EN" -gt "$SUM_ES" ]; then
return 2
else return 3
fi
else return 1
fi # elege um dos idiomas ou mantém o default
} # set_voice - elege idioma do locutor
function get_data_and_spk(){
mocp -i > $DATA_MEDIA 2>/dev/null
if [ "$?" -eq 0 ]; then
TRACK="`grep "^File:" $DATA_MEDIA|sed 's/File: *//'`" # TRACK on play
else restart_player
return 0
fi # set data or restart moc
# === Atualiza Tags e Anúncia e Elege Idioma ===============================================================
if [ "$TRACK1" != "$TRACK" ]; then
# === Elege Idioma para o Locutor ==================================================================
if [ "$TALK" = "on" ]; then
set_voice "$TRACK"
case "$?" in
1) VOZ="pt";;
2) VOZ="en-us";;
3) VOZ="es-la";;
*) VOZ="on";;
esac
fi # elege idioma ==================================================================================
id3v2 -l "${TRACK:=}" 2>>$TMP_LOG|sed '/^PRIV.*:/d'|grep -v "^COMM.*:.*[0-9A-F]\{8,\}" >$DATA_ID3
ARTIST="`grep "^TPE1.*: " $DATA_ID3|sed "s/^TPE1.*: *//"`"
SONG_TITLE="`grep "^TIT2.*: " $DATA_ID3|sed "s/^TIT2.*: *//"`"
YEAR="`grep "^TYER.*: " $DATA_ID3|sed "s/^TYER.*: *//"`"
ALBUM="`grep "^TALB.*: " $DATA_ID3|sed "s/^TALB.*: *//"`"
GENRE="`grep "^TCON.*: " $DATA_ID3|sed "s/^TCON.*: *//"`"
ARTIST="${ARTIST:=$(grep "^Artist:" $DATA_MEDIA|sed 's/^Artist: *//')}"
SONG_TITLE="${SONG_TITLE:=$(grep "^SongTitle:" $DATA_MEDIA|sed 's/^SongTitle: *//')}"
ALBUM="${ALBUM:=$(grep "^Album:" $DATA_MEDIA|sed 's/^Album: *//')}"
YEAR="${YEAR:=$(grep "^.*Year: *" $DATA_ID3|sed "s/^.*Year: *//"|sed "s/,.*$//")}"
GENRE="${GENRE:=$(grep "^.*Genre: *" $DATA_ID3|sed "s/^.*Genre: *//"|sed "s/[ ]*$//g")}"
TITLE="$ARTIST - $SONG_TITLE"
echo $TITLE|grep -qE "[[:alnum:]]" || TITLE="`echo $TRACK|sed 's;^/.*/[ 0-9]*;;'| \
sed 's/[MmOoFfAa][PpGgLlVv][34GgVvIi]$//'`" # título alternativo
TRACK1="$TRACK"
fi # atualiza tags e elege idioma =========================================================================
local -i TIME_LEFT="$(grep TimeLeft: $DATA_MEDIA| sed 's/^.* //; s/00*:00/0:01/; s/://; s/^.0//; s/^00*//')"
# Configura Locutor ========================================================================================
if [ "$TIME_LEFT" -gt 3 ] && [ "$TIME_LEFT" -lt 7 ]; then
# Executa o Locutor ================================================================================
if [ "$TALK" = "on" ]; then
local CITE= # citação do player (mudo por default)
local -i RND=$RANDOM
killall -9 espeak &>/dev/null
if [ $(($RND % 100)) -le 50 ];then
if [ "$VOZ" = "en-us" ]; then
CITE="$FRASE_EN"
else CITE="$FRASE_PT"
fi # seleção de pronúncia
fi # escolhe se anúncia créditos moc
espeak -p0 -v$VOZ+m1 "$CITE$TITLE..." &>/dev/null
if [ "$(($RANDOM % 100))" -gt "$PROB" ]; then
if [ "$DIFUSAO" = "on" ]; then
local -i PAUSADO=0
mocp -i|grep -q "State: PLAY" && mocp -P && PAUSADO=1
if [ "$(($RANDOM % 100))" -gt 80 ]; then
local VOICE=
TEXTO="`command $COMANDO`"
set_voice "$TEXTO"
case "$?" in
1) VOICE="pt";;
2) VOICE="en-us";;
3) VOICE="es-la";;
*) VOICE="pt";;
esac
echo "$TEXTO"|espeak -v${VOICE}+m4 &>/dev/null
else espeak -vpt+f4 "$MENSAGEM" &>/dev/null
fi # escolhe aleatóriamente a frase de difusão
[ "$PAUSADO" -eq 1 ] && mocp -U
fi # difusão de mensagens
else CITE="`date "+%H horas, %M minutos"|sed 's/^0//'|sed -r 's/(.*, )0(.*)/\1\2/'`"
espeak -vpt+f4 "$HOSTNAME: $CITE" &>/dev/null
if [ "$NEW_MAIL" -gt 0 ]; then
local S= # plural
[ "$NEW_MAIL" -gt 1 ] && S="s"
espeak -vpt+m4 "Você tem $NEW_MAIL email$S não lido$S." &>/dev/null
fi # anuncia número de emails não lidos
fi # elege anúncio de horas, ou difusão/citação
fi # TALK TRACK in playing =========================================================================
fi # configura saída de voz sintetizada ====================================================================
if [ "$TRACK0" != "$TRACK" ]; then
TRACK0=$TRACK
return 0
else return 1
fi # verifica troca da mídia em execução
} # get_data_and_spk - obtém dados da mídia em reprodução e anuncia titulo em voz sintetizada
function enfileirar(){
local -i PERCENTUAL=$2 # limitador da partição (com uma casa decimal)
local -i TT_VAR=`cat $TT_VARRIDOS` # total acumulado de ficheiros pesquisados
local -i TT_INDEX="`cat $INDEX 2>>$TMP_LOG|wc -l`" # total de índices a serem pesquisados
local -i PONTEIRO=0 # ponteiro inicial do segmento
local -i LINE_SELECT=0 # índice contido no segmento
local -i PROXIMO=0 # contador de vizinhos enfileirados
local -i CONTADOR=0 # ponteiro do segmento em varrimento
local -i VARRIDOS=0 # contador de índices pesquisados da partição
local -i PERC_BUSCA=0 # estado da busca e limitador de partição
local MEDIA_SELECTED= # mídia selecionada
local ID3= # armazena dados id3v2
if [ "$1" != "no" ]; then
local -i TT_FILA=0 # reinicia ńumero de enfileirados
else
local -i TT_FILA=$(cat $TOT_FILA) # restaura número de enfileirados
fi # número de enfileirados
printf "" > $CHECKEDS # limpa lista auxiliar
# === V A R R E D U R A D A P A R T I Ç A O ============================================================================
while [ "$PERC_BUSCA" -le "$PERCENTUAL" ] && [ "$VARRIDOS" -lt "$TT_INDEX" ]; do
PONTEIRO=$((1 + (($RANDOM + `date +%N|sed -e 's/^00*//g'`) % $TT_INDEX))) # ponteiro randomizado
PROXIMO=0; CONTADOR=0
# === V A R R E D U R A D O S E G M E N T O ====================================================================
while [ "$CONTADOR" -lt "$SECAO" ] && [ "$PONTEIRO" -le "$TT_INDEX" ]; do
[ "`cat $SINAL`" -eq 0 ] && return 2 # interrupção por sinal
LINE_SELECT="`head -$PONTEIRO $INDEX|tail -1`" # seleciona índice a pesquisar
# === C H E C A G E M D E I N D I C E S ================================================================
grep -q "^$LINE_SELECT$" $CHECKEDS # checa se índice já foi pesquisado
if [ "$?" -ne 0 ]; then
MEDIA_SELECTED="`head -$LINE_SELECT $FICHEIROS|tail -1`" # seleciona mídia apontada pelo índice
ID3="`id3v2 -l "$MUSICA/$MEDIA_SELECTED"|grep -E "$FILTRO"`" # obtém tags id3 da mídia
# === V E R I F I C A C A S A M E N T O D E P A D R O E S ====================================
echo "$ID3"|grep -qiE "${PADRAO[0]}"
if [ "$?" -eq 0 ] || [ "${PADRAO[0]}" = "" ]; then
echo "$ID3"|grep -qiE "${PADRAO[1]}"
if [ "$?" -eq 0 ] || [ "${PADRAO[1]}" = "" ]; then
echo "$ID3"|grep -qiE "${PADRAO[2]}"
if [ "$?" -eq 0 ] || [ "${PADRAO[2]}" = "" ]; then
echo "$ID3"|grep -qiE "${PADRAO[3]}"
if [ "$?" -eq 0 ] || [ "${PADRAO[3]}" = "" ]; then
echo "$ID3"|grep -qiE "${PADRAO[4]}"
if [ "$?" -eq 0 ] || [ "${PADRAO[4]}" = "" ]; then
echo "$ID3"|grep -qiE "${PADRAO[5]}"
if [ "$?" -eq 0 ] || [ "${PADRAO[5]}" = "" ]; then
# === E N F I L E I R A D E M I D I A ==========
if [ "$TT_FILA" -lt "$MAX_FILA" ]; then
mocp -a "$MUSICA/$MEDIA_SELECTED" || restart_player &>/dev/null
if [ "`mocp -Q %state 2>/dev/null`" = "STOP" ]; then
[ "$TALK" = "on" ] && espeak -p0 -vpt+f4 "Reproduzindo..." &>/dev/null
mocp -p 2>/dev/null
sleep .5
fi # inicia a reprodução
let TT_FILA++; let PROXIMO++
echo $TT_FILA > $TOT_FILA
[ "$PROXIMO" -ge "$VIZINHOS" ] && CONTADOR=$SECAO
else return 1 # conclusão do enfileiramento
fi # enfileiramento de mídia =======================
fi # other
fi # genre
fi # year
fi # album
fi # title
fi # artist/band ===================================================================================
echo "$LINE_SELECT" >> $CHECKEDS
fi # checagem ==============================================================================================
let PONTEIRO++ # move ponteiro do segmento
let CONTADOR++
done # varredura do seguimento =====================================================================================
VARRIDOS="`cat $CHECKEDS|wc -l`" || exit 1
PERC_BUSCA=$((($VARRIDOS + $TT_VAR)*1000/$TT_FICHEIROS))
echo $PERC_BUSCA >$PERC_OUT # (exibido na tela principal)
done # varredura da partição ===============================================================================================
echo "$(($TT_VAR + $VARRIDOS))" > $TT_VARRIDOS # variável restaurável
test "`cat $TT_VARRIDOS`" -lt "$TT_FICHEIROS"
return $? # retorna 1 se concluído, 2 se interrompido e 0 se não concluído
} # enfileira - pesquisa na partição em construção e enfileira mídias
function auto_enqueueur(){
if [ "$AUTO" != "auto" ];then
estado_sub_pid
change_profile "AUTO ENFILEIRAR $MAX_FILA mídias ao 'playlist'..."
if [ "$?" -eq 0 ]; then
AUTO="auto"
else AUTO="no-auto"
fi # ativa o modo auto se confirmado
else AUTO="no-auto"
fi # alterna modo automático
} # auto_enqueueur - toggle auto/no-auto
function hash_list(){
local LIMPAR="$1" # limpar fila (yes/no)
seq 1 $TT_FICHEIROS > $INDEX || exit 1 # lista de índices a serem varridos
local -ai PARTICAO=(`seq 50 50 950` 999 1000) # limitadores de partições (percentuais com uma casa decimal)
local -i LEN=${#PARTICAO[@]} # número de partições (20 + 1 partições)
local -i i=0 # variável de incremento
echo 0 > $TT_VARRIDOS # total geral de índices pesquisados
echo 0 > $PERC_OUT # percentual da varrredura
echo 1 > $SINAL # flag de interrupção de busca e enfileiramento
echo 0 > $TOT_FILA # número de enfileirados
if [ "$TALK" = "on" ]; then
espeak -p0 -vpt+f4 "$HOSTNAME: Enfileirando $MAX_FILA mídias.: " &>/dev/null
test -n "$FRAME_ART" && espeak -p0 -vpt+f4 "Artista: $FRAME_ART" &>/dev/null
test -n "$FRAME_TIT" && espeak -p0 -vpt+f4 "Título: $FRAME_TIT" &>/dev/null
test -n "$FRAME_ALB" && espeak -p0 -vpt+f4 "Álbum: $FRAME_ALB" &>/dev/null
test -n "$FRAME_YER" && espeak -p0 -vpt+f4 "Ano: $FRAME_YER" &>/dev/null
test -n "$FRAME_CON" && espeak -p0 -vpt+f4 "Gênero: $FRAME_CON" &>/dev/null
test -n "$FRAME_ALL" && espeak -p0 -vpt+f4 "Outros: $FRAME_ALL" &>/dev/null
fi # anuncia enfileiramento
for ((i;i<$LEN;i++)); do
# === BEFORE =============================================================
[ "$i" -gt 0 ] && LIMPAR="no" # mantém playlist após primeira iteração
# === ENFILEIRA enfileirar <yes|no|auto> <partição> =====================
enfileirar "$LIMPAR" ${PARTICAO[$i]}
# === AFTER ==============================================================
if [ "$?" -eq 0 ]; then
sed 's/^/\^/' $CHECKEDS|sed 's/$/\$/' > $CHECKEDS.1
grep -vf $CHECKEDS.1 $INDEX > $INDEX.1
mv $INDEX.1 $INDEX
else break # termina se concluído ou interrompido por sinal
fi # elimina partição pesquisada do vetor de índices
done # pesquisa em cada partição construída em tempo de busca e enfileiramento
echo -1 > $SUB_PID
[ "$TALK" = "on" ] && espeak -p0 -vpt+f4 "Busca encerrada." &>/dev/null
} # hash_list - faz o particionamento dos índices e enfileira mídias casadas
function set_list(){
# Parâmetros:
# 1) limpar? <yes|no|auto>
# 2) frase do dialog
local -i RET=1 # retorno
TT_FICHEIROS="`cat $FICHEIROS|wc -l`"
if [ "$1" = "auto" ]; then
[ "`cat $SUB_PID`" -le 0 ] && RET=0
else estado_sub_pid && change_profile "$2" && RET=0
fi # permite interromper e reiniciar o enfileiramento
if [ "$RET" -eq 0 ]; then
if [ "$1" != "no" ]; then
mocp -s &>/dev/null
mocp -c &>/dev/null
fi # interrompe e limpa playlist
hash_list $1& 2>>$TMP_LOG
echo $! > $SUB_PID
fi # enfileira
} # set_list - permite reconfiguração da forma de busca e enfileira arquivos
function estado_sub_pid(){
local -i RET=0
if [ "`cat $SUB_PID`" -gt 0 ]; then
dialog --stdout \
--title "Atenção!" --defaultno \
--yesno "Existi um processo de enfileiramento aberto. A conclusão do mesmo pode demorar alguns minutos. \
\n\nVocê deseja terminá-lo?" \
12 60
if [ "$?" -eq 0 ]; then
dialog --stdout \
--title "MocpList: Encerrando busca..." \
--infobox "\nAguarde! Encerrando procedimento..." \
7 40
echo "0" > $SINAL
local -i DEAD="`cat $SUB_PID`"
while [ "${DEAD:=0}" -gt 0 ]; do sleep 1; DEAD="`cat $SUB_PID`" ;done
else RET=1
fi # modifica sinal e aguarda encerramento
fi # verifica se procedimento está em execução
return $RET
} # estado_sub_pid - verifica e permite encerrar processo de busca em execução
function display_info(){
# parâmetro 1: refresh
get_data_and_spk 2>> $TMP_LOG
if [ "$?" -eq 0 ] || [ "$1" -eq 0 ]; then
local STATUS="ocioso"
local FILE="`echo $TRACK|sed 's;.*/M[úu]sica/;../;'`"
[ "`cat $SUB_PID`" -gt 0 ] && STATUS="`cat $PERC_OUT`% concluído."
if [ -z "$TITLE" ]; then
MODO="Waiting"
TEXTO="Aguardando"
else MODO="Playing -"
TEXTO="Reproduzindo $TITLE"
fi # textos da sobre o estado do tocador
# TEXTO="[$espanhol|$ingles] $TEXTO" ### depurando...
TEXTO="$TEXTO...\n\nArtista: ${ARTIST}\nTítulo: ${SONG_TITLE}\nÁlbum: ${ALBUM}\nAno: ${YEAR}"
TEXTO="$TEXTO\nGênero: ${GENRE}\nArquivo: ${FILE:=}"
TEXTO="$TEXTO\n\nEstado da pesquisa: $(echo $STATUS|sed -r "s/(.*)(.\%).*/\1,\2/"|sed "s/^,/0,/")\nEnfileiramento: `cat $TOT_FILA`/$MAX_FILA"
TEXTO="$TEXTO\nPalavras chaves: {`echo "(${FRAME_ART:-${DICA[0]}}) & (${FRAME_TIT:-${DICA[1]}}) & (${FRAME_ALB:-${DICA[2]}}) & (${FRAME_YER:-${DICA[3]}}) & (${FRAME_CON:-${DICA[4]}}) & (${FRAME_ALL:-${DICA[5]}})"`}"
dialog --stdout --no-collapse --trim --tab-correct \
--backtitle " .::: <s>et :: <l>ist :: <i>nfo :: <b>ack :: <n>ext :: <p>ause :: <h>elp :: <q>uit :::" \
--title "MocpList - Talk
Script Iptables ( Passou em Testes )
Script para calcular o valor fatorial de um numero
Instalando OCR apps no seu Debian.
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
IA chega ao desktop e impulsiona produtividade no mundo Linux
Novos apps de produtividade, avanços em IA e distros em ebulição agitam o universo Linux
Como instalar o repositório do DBeaver no Ubuntu
Como instalar o Plex Media Server no Ubuntu
Digitando underscore com "shift" + "barra de espaços"
Como ativar a lixeira e recuperar aquivos deletados em um servidor Linux
Como mudar o nome de dispositivos Bluetooth via linha de comando
Programa fora de escala na tela do pc (16)
Fedora KDE plasma 42 X Módulo de segurança BB (Warsaw-2) (1)
O programa assinador digital (1)









