iPhone: Áudios à vontade

by Bruno Milare on April 21, 2011

Fazendo uma pesquisa rápida de como tocar sons em uma aplicação de iPhone encontrei um tutorial muito simples que funcionou ‘quase’ como eu gostaria.

A biblioteca utilizada nesse tutorial foi a AVAudioPlayer, e me pareceu bastante simples executar um único som, o problema é que eu gostaria de algo mais abrangente e dinâmico, eu queria um player de audio que executasse qualquer som com apenas um método, que gerenciasse meus arquivos de som, e não carregasse eles novamente, caso já tivessem sido tocados. Com essa ideia na cabeça eu criei a classe AudioPlayer.

Com um objeto dessa classe instaciado ele atuará como o nome já diz, como um player de áudio, você pode escolher o som que vai tocar, ele verifica se o arquivo já foi tocado anteriormente, se já, só reproduz, se não coloca ele na lista, enfim, gerencia os audios de sua aplicação.

Criando o AudioPlayer

Antes de mais nada é preciso adicionar o AVFoundation framework em sua aplicação, no XCode4 faça:

1. Na árvore de arquivos clique no seu projeto.
2. Na barra superior da janela central clique em Build Phases.
3. Expanda o item Link Binary With Libraries.
4. Clique no sinal de ‘+’ e procure por AVFoundation.framework
5. Adicione o framework ao seu projeto.

Como é uma classe bastante simples, vou colocar os códigos diretamente aqui.

Crie os arquivos AudioPlayer.h e AudioPlayer.m e coloque os respectivos códigos abaixo:

AudioPlayer.h

#import <Foundation/Foundation.h>
#import <AVFoundation/AVAudioPlayer.h>

@class AVAudioPlayer;

@interface AudioPlayer : NSObject {
    NSMutableDictionary *audioSlots;
}

@property (retain, nonatomic) NSMutableDictionary* audioSlots;

- (void) playFile:(NSString*) filename ofType:(NSString*) type nTimes:(NSInteger) times;
- (void) stopPlayingFile:(NSString*) filename;
- (void) stopPlayingFilesLike:(NSString*) name;
- (BOOL) isPlayingFile: (NSString*) filename;
- (void) muteAll;
- (void) clearStoredAudios;
- (id) init;

@end

AudioPlayer.m

#import "AudioPlayer.h"
@implementation AudioPlayer
@synthesize audioSlots;

- (id) init
{
    self = [super init];
    if (self) {
        audioSlots =  [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (void) playFile:(NSString*) filename ofType:(NSString*) type nTimes:(NSInteger) times
{
    AVAudioPlayer *currentSlot = [audioSlots objectForKey:filename];
    if (currentSlot == nil) {
        NSString *filePath = [[NSBundle mainBundle] pathForResource: filename ofType: type];
        NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
        currentSlot = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
        [audioSlots setObject:currentSlot forKey:filename];
        [currentSlot prepareToPlay];
        [fileURL release];
        [currentSlot release];
    }
   
    currentSlot.numberOfLoops = times;
   
    [currentSlot play];
}

- (void) stopPlayingFile:(NSString*) filename
{
    AVAudioPlayer *currentSlot = [audioSlots objectForKey:filename];
    if (currentSlot != nil) {
        [currentSlot stop];
    }
}

- (BOOL) isPlayingFile: (NSString*) filename
{
    AVAudioPlayer *currentSlot = [audioSlots objectForKey:filename];
    if (currentSlot != nil) {
        return currentSlot.playing;
    }
    return NO;
}

- (void) stopPlayingFilesLike:(NSString*) name
{
    NSRange textRange;
   
    for (NSString *slotKey in [audioSlots allKeys]) {
        textRange =[[slotKey lowercaseString] rangeOfString:[name lowercaseString]];
        if(textRange.location != NSNotFound)
        {
            [[audioSlots objectForKey:slotKey] stop];
        }
  }
}

- (void) muteAll
{    
    for (NSString *slotKey in [audioSlots allKeys]) {
        [[audioSlots objectForKey:slotKey] stop];
  }
}

- (void) clearStoredAudios
{
    [self muteAll];
    [audioSlots removeAllObjects];
}

- (void) dealloc
{
    [self muteAll];
    [audioSlots release];
    [super dealloc];
}

@end

Utilizando o AudioPlayer

Isso é fácil, basta instanciar um objeto da classe AudioPlayer:

audioPlayer = [[AudioPlayer alloc] init];

Os nomes dos métodos são bastante intuitivos, o que vale explicar é que o AudioPlayer utiliza o nome do arquivo como chave do dicionário de AVAudioPlayers, eu pensei nessa abordagem porque fica muito mais fácil você gerencia-los assim.

Por exemplo, eu tenho 3 arquivos tocando: MusicBack.mp3, SoundClick.wav e o SoundFoo.mp3, se eu crio uma regra de negócio onde existe a diferença entre som e música, eu posso facilmente parar todos os sons chamando o método:

audioPlayer.stopPlayingFilesLike: @"Sound";

Você pode tocar o arquivo de som que você quiser, só basta chamar:

audioPlayer.playFile:@"SoundBar" ofType:@"mp3" nTimes:1

Lembrando que se você colocar o parâmetro nTimes = -1, o som ficará tocando em loop.

Exemplo

AudioPlayerDemo

O exemplo da foto acima pode ser encontrado no meu github.

[]s

Bruno.

iPhone: Splash Screen

by Bruno Milare on April 19, 2011

Seguindo o meu aprendizado orientado a demanda, me deparei com o problema de ter que criar uma splash screen para uma aplicação que carregava muito rapidamente.

Splash screen ? Oras, isso deve ser fácil, vou dar uma pesquisada e logo arrumo uma solução razoável.

Pois é, eu estava errado, não no ponto de ser fácil, porque é, mas na questão de achar rapidamente uma solução, ainda mais para XCode 4. Existem diversas maneiras de se fazer isso, só que sinceramente, existem umas que além de não funcionarem, desrespeitam qualquer boa prática.

Um exemplo disso que eu vi, foi o cara colocar a imagem Default.png, que é a imagem que a aplicação exibe quando o aplicativo está carregando, e colocar ele para dormir pelo tempo que ele julgue necessário a imagem ficar aparecendo. Eu acredito que essa não seja a maneira correta, porque você está perdendo uma liberdade utilizando a imagem Default.png para isso, além do que deixar a aplicação dormindo não é uma boa ideia por definição. =P

Deixando de lado essas abordagens, e qualquer comentário, sobre a necessidade ou não de uma splash screen, vamos a solução utilizada.

Read the rest of this entry »

iPhone: Aprendendo Objective-C

by Bruno Milare on April 6, 2011

Resolvi, por nenhum motivo aparente a desenvolver em Objective-C e vou contar um pouco da minha experiência e a salada que saiu disso.

Na última semana me engajei a desenvolver um joguinho para iPhone, talvez deixei-me levar pelo modismo, mas isso não importa. Minha ideia inicial era a seguinte:

Vou fazer algo simples que aplique algum conceito também simples e que me agregue conhecimento e gere algo tangível, o que é difícil quando você está começando a aprender alguma coisa.

Walker

Esse foi o nome do meu joguinho, que dá uma ideia muito sugestiva do que o “jogo” faz. Esse aplicativo foi feito utilizando a biblioteca gráfica Cocos2D e o algoritmo de Dijkstra para o menor caminho. A ideia é a seguinte:

Existe um mapa de Tiles, que nada mais é que um grafo (visivelmente uma matriz) onde cada nó desse grafo está conectado com seus dois vizinhos verticais e seus dois vizinhos horizontais.

Você pode colocar no mapa, atráves da gaveta no canto superior esquerdo, três tipos de Tiles (Grama, Pedra e Parede), fechando a gaveta e tocando em algum ponto do mapa o personagem vai andar no mapa de acordo com a dificuldade de seus obstáculos. simples.

Segue um vídeo da aplicação rodando (ele está aqui, só demora um pouquinho para carregar, rs).

O fonte ficou uma bagunça só, desrespeitei várias diretrizes, mas de qualquer maneira ele pode ser encontrado no meu github: github.com/milare/walker

Eu fico por aqui.

Abraços !

Bruno.

Motivação

by Bruno Milare on February 7, 2011

Nos últimos dias venho pensando muito em motivação, não sei se muito porque a minha anda tendo altos e baixos, muito provavelmente é por causa disso sim, mas comecei a questionar as coisas que me deixam motivado e as que não.

Perambulando pela internet eu achei esse vídeo, onde Dan Pink fala um pouco sobre o que ele escreveu em seu livro Motivação 3.0 (Drive), como as mudanças de paradigma em relação a motivação, que ocorreram através das décadas, que a ciência comprova e que nem sempre são aplicadas.

Enfim, me identifiquei muito, vale a pena conferir…

É isso aí.

Bruno.

Não escreva métodos em seus módulos com self.

by Márcio Gasparotto on February 5, 2011

É normal encontrar métodos implementados dentro de módulos acompanhados pelo self, geralmente usamos isso quando queremos tornar esse método um método de instância do módulo, já vi implementações bem grandes com vários métodos e todos eles acompanhados do self antes do nome do método. mas isso é algo que podemos abstrair e manter nossa implementação de módulos mais simples e limpa.

Veja alguns exemplos:
Read the rest of this entry »