MocPList - Enfileirador de áudio e locutor em voz sintetizada
Publicado por Khayla Elias dos Santos (última atualização em 21/02/2019)
[ Hits: 2.674 ]
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
Remover espaços em branco em nomes de arquivos
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Cups: Mapear/listar todas as impressoras de outro Servidor CUPS de forma rápida e fácil
Criando uma VPC na AWS via CLI
Tem como instalar o gerenciador AMD Adrenalin no Ubuntu 24.04? (8)