MocPList - Enfileirador de áudio e locutor em voz sintetizada

Publicado por Khayla Elias dos Santos (última atualização em 21/02/2019)

[ Hits: 2.673 ]

Homepage: https://linktr.ee/khayla.elias

Download mocplist

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ões atualizadas deste 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


Esconder código-fonte

#!/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            # &#324;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 &#324;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

Scripts recomendados

Gravar CD de dados

Script que busca IP Livres em uma rede

Proteja sua rede com um simples script de firewall

Estatística dos MB's consumidos pela internet

Grep em loop infinito


  

Comentários
[1] Comentário enviado por khayla em 26/06/2018 - 18:06h

;) Mais detalhes ou atualizações podem ser obtidas em:
https://drive.google.com/drive/folders/1aTy4uEaCt5GVof9-P3HJEmX9tVv4t7gE

Khayla Elias dos Santos


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts