Aproximadamente 30 dias atrás iniciei meus serviços na iCert, onde estou desenvolvendo aplicações web integradas com aplicações Android nativas.
Em função disso e para testar o envio de apks para a Google play, como funciona o sistema de atualizações, dentre outras coisas, fiz uma pequena aplicação chamada
Tela azul da morte!
Citando a Google Play:
Encomode seus amigos com a clássica tela azul da morte.
Simule a tela azul da morte do windows 98.
Este é uma aplicativo muito legal para incomodar seus amigos, ative o aplicativo e passe o aparelho para alguém. O programa ficará aparecendo de tempos em tempos e incomodando a pessoa.
O aplicativo só para se o usuário sacudir bastante o aparelho a fim até acabar com todas as instâncias da tela azul da morte.
O aplicativo foi feito e testado em tablets de 7 e 10 polegadas, mas funciona em celulares.
Estou desenvolvendo um servidor PHP para a engine Unity3d. A ideia é ter serviços básicos como login, registro de acessos, highscores dentre outras coisas. Mas o conceito se expande no momento em que teremos uma aplicação web para análise e manutenção dos registros gerados pela Unity.
Em função dessa situação toda me motivei a criar de uma vez um serviço web que tenha um suporte alto a dispositivos móveis. Na verdade isto está muito relacionado com o fato de que meus futuros jogos rodarem em dispositivos móveis, graças a Unity3d.
Por fim, após alguns estudos, defini que não precisaria de algo muito complexo, mas que gostaria de utilizar orientação a objetos e dentro do possível utilizaria bibliotecas prontas.
Optei por não utilizar um framework 100% pronto para manter uma independência do código, pois servidores de jogos tem uma tendência muito alta a sofrerem ataques hackers, nesse caso, quanto mais “pessoal” o código, mas difícil de quebrar. Obviamente, desde que observe algumas técnicas básicas de segurança.
Em função destes objetivos fiz algumas escolhas.
PHP: é a linguagem que trabalho normalmente e conheço a fundo, 100% relacionada com aplicações webs.
DOM: bibliotecas padrão do php que tem objetivo principal de criar conteúdo html utilizando orientação a objetos.
PDO: Camada de abstração de conexão a base de dados.
Jquery e JqueryMobile : biblioteca javascript que garante o ótimo funcionando em diversos dispositivos móveis.
Obs.: A questão da implementação direta com a Unity3D ficará para outro artigo.
DOM – Document Object Model:
Dom é uma forma definida de acessar/criar elementos HTML. A estrutura DOM foi criada e é mantida pela W3C. Basicamente é uma forma orientadas a objetos de manipulação de elementos html/xml.
$doc=new DOMDocument("1.0");//cria o documento$div=$doc->createElement("div");//cria uma Div$div->setAttribute('style','padding: 10px; background-color: red');//adiciona um fundo vermelho a div$div->appendChild($doc->createTextNode('conteúdo da div'));//colocamos um texto dentro da div$span=$doc->createElement("span");//criamos um span$span->appendChild($doc->createTextNode('conteúdo do span'));//adicionamos um conteúdo ao span$span->setAttribute('style','padding: 10px; background-color: blue');//definimos o span com fundo azul$div->appendChild($span);//adicionamos o span dentro da div$doc->appendChild($div);//adicionamos a div ao elementoecho$doc->saveHTML();//efetuamos o output do html
O exemplo acima é bem simples, conforme comentado no código, nele criamos um documento Dom, criamos uma div e um span e atribuímos alguns estilos a ele. É obvio que esse não é um html válido, pois faltou toda a estrutura padrão do documento html, head, body e etc, mas é um exemplo válido.
Isto tudo é bem lega, mas na prática do dia a dia existe a tendência disso se tornar mais lento do que criar html direto.
É nesse ponto que entra a orientação a objetos.
class Div extends DomElement
{publicfunction __construct($id,$element=NULL,$class=NULL){
parent::__construct('div');global$doc;$doc->appendChild($this);$this->setAttribute('id',$id);$this->appendChild($element);$this->setAttribute('class',$class);}}
No exemplo cima criamos uma classe Div que extende um elemento DOM ( DomElement). Na prática fazer uma chamada de $doc->createElement(‘div’) ou efetuar um new DomElement(‘div’) da na mesma.
A única diferença é que no caso do new DomElement precisamos adicionar ele a um DomDocument, o que não é necessário no outro caso.
Com essa classe criada podemos criar uma div diretamente.
Nesse ponto poderíamos criar uma classe para cada tag html e após isso criar classes que agrupam funcionalidades. Como por exemplo uma classe Page que poderia fazer toda a criação de head, body, form criando toda a estrutura básica necessária para uma página.
Aqui começamos a ganhar produtividade.
PDO – PHP Data Object
PDO é uma camada de abstração de acesso a base de dados. Você pode fazer conexões com Mysql, Postgres, MSQL, SqLite e mais uma grande série de bancos.
O artigo acima ( em inglês) demonstra com clareza os motivos técnicos para usar PDO, com certeza vale a leitura, mas vou listar alguns aqui:
Compatibilidade com diversos bancos
Características contra sql injection.
Integração total com PHP ( bultin)
Tipos de retornos variados, inclusive classes próprias.
Brincando com PDO em 4 linhas:
$pdo=new Pdo('mysql:host=localhost;dbname=dbname','user','password');//conecta no banco$ret=$pdo->prepare('SELECT * from access LIMIT 1');//prepara o sql$ret->execute($args);//executa$dbData=$ret->fetchObject();//retorna o sql como um objeto stdClass
Muito simples e efetivo.
Juntando tudo:
<?phpclass Div extends DomElement
{publicfunction __construct($id,$element=NULL,$class=NULL){
parent::__construct('div');global$doc;$doc->appendChild($this);$this->setAttribute('id',$id);$this->appendChild($element);$this->setAttribute('class',$class);}}//parte do pdo$pdo=new Pdo('mysql:host=localhost;dbname=nome_do_banco','root','senha');$ret=$pdo->prepare('SELECT * from access LIMIT 1');$ret->execute($args);$dbData=$ret->fetchObject();global$doc;//parte do dom$doc=new DOMDocument("1.0");$div=$doc->createElement("div");$div->setAttribute('style','padding: 10px; background-color: red');$div->appendChild($doc->createTextNode('conteúdo da div'));$span=$doc->createElement("span");$span->appendChild($doc->createTextNode($dbData->useragent));$span->setAttribute('style','padding: 10px; background-color: blue');$div->appendChild($span);$doc->appendChild($div);$div2=new Div('myDiv',$doc->createTextNode('conteúdo interno'),'algumaClasse');$div2->setAttribute('style','background-color: green');echo$doc->saveHTML();?>
O código acima é 100% válido, desde que você configure uma base com uma tabela chamada access.
Jquery Mobile
Como terceira ferramenta nesse projeto utilizaríamos a poderosa biblioteca Jquery Mobile.
Utilizando atributos do tipo data (data-role por exemplo) a biblioteca jQuery mobile identifica tudo que é necessário para a sua página, o legal é que caso o navegador mobile não suporte javascript tudo continua funcionando, de forma mais simples, mas continua.
Repare como os formulários e aplicações ficam bonitos.
O video acima mostra um exemplo prático de um website feito com a tecnologia.
Conclusão:
No final utilizamos as nossas classe orientadas a objetos com DOM para gerar os nossos conteúdos html do jquery mobile.
Por fim temos segurança e abstração de banco de dados com PDO, temos html orientado a objetos com suporte a elementos complexos com DOM e temos conteúdo bonito e pronto para mobile com Jquery mobile.
Banco de dados, servidor e cliente. Tudo prontinho para por a mão na massa!
Gostaria de divulgar o meu protótipo do que será um jogo de luta.
Ele se chama (ao menos até o momento) Fists of Fate – Streets of Chaos, é um jogo de luta no estilo beat’n up/brawler. Ele contará com 8 personagens personagens jogáveis, 8 modos diferentes de jogo, evolução dos personagens e inimigos e mais uma série de coisas.
Mas hoje eu vim aqui para mostrar o primeiro video do protótipo 4, que é feito utilizando a Unity3D.
Esta versão já conta com 4 meses de desenvolvimento, obviamente contando só o tempo livre (o que sobra do trabalho/faculdade/vida pessoal).
Só para constar, antes estava fazendo o jogo 100% em java e em 2D, e estava dando bastante trabalho, por isso optamos por trocar pra Unity, segue o versão do protótipo 14 em Java.
Para constar, ontem a noite consegui compilar a primeira versão para Android, ficou levemente lenta, mas nada que algumas otimizações não resolvam.
Falar sobre a Unity3D é um problema, isto é um fato, existem tantas qualidades e o seu potencial é tão grande que é complicado definir por onde começar.
Mas enfim, Unity3D é um motor de jogos 3D (também serve perfeitamente para 2D), não é uma engine que algumas pessoas fizeram em um fim de semana, existe uma equipe de mais de 200 profisionais trabalhando dirariamente nas suas funcionalidades.
Escreva uma vez, compile diversas
Unity Editor
A Unity é um engine multi propósitos, ela permite o desenvolvimento de qualquer tipo de jogos para praticamente qualquer plataforma, ele possui recursos completos de física ( Phyx da Nvidia), partículas, sombras pré-prontas ou em tempo real.
Enfim nem vale a pena insistir em destacar todas as funcionalidades bult-in que ela tem, sem contar que novas funcionalidades podem ser construídas por qualquer um através de scripts e plugins.
A Unity possui documentação super completa, uma seria enorme de tutoriais, videos, forum, site de perguntas e respostas, e uma comunidade bem disposta e bem humorada.
De mobiles a AAA
Unity Xbox
A Unity suporta compilação de seus jogos para PC, MAC, Linux, webplayer próprio, flash, Android, iPhone, PS3, Wii e XBOx, e possivelmente mais algumas plataformas que nem sei que ela suporta. Existem diversos jogos públicados para as mais diversas plataformas, tem gente fazendo dinheiro com ela, com certeza.
A respeito disso, a Unity permite que qualquer pessoa lance jogos para PC, MAC e Linux sem pagar um pila pra ela, desde que sua empresa fature menos de 100 mil dólares por ano. Se você quiser lançar jogos para outras plataformas terá que abrir a carteira, mas a versão Android por exemplo, custa somente 400 dólares, um valor acessível podemos dizer, se comparado a licenças de outros softwares.
Formatos e arquivos
Unity Scene
A Unity suporta uma gama “fenomenal” de formatos, tem compatibilidade a diversos formatos 3D, Max, Maya, Blender, Sketchup, a sua programação pode ser feita utilizando Javascript, C# ou Boo (um tipo de Python), suporta “todos” formatos de imagens conhecidos e também audios.
Enfim, a Unity é maravilhosa, uma ótima escolha para quem quer fazer jogos AAA, indies, móbile ou seja lá o que for, seja um jogo de corrida, luta, RPG, ação, adventure, com ou sem recursos de redes.
Fiquem com um videozinho da capacidade gráfica do bichinho:
Por fim, vale a pena dar uma atenção para esse motor.
Este é o meu blog sobre desenvolvimento de jogos. Como não estou conseguindo manter os dois blogs, estou planejando.
Isto irá gerar mais artigos sobre jogos, tanto programação como criação e também vou aplicar um leiate totalmente novo para o blog, nos próximos dias teremos novidades.
Hoje vamos falar de um assunto delicado, conversão de softwares ISO-8859-1 para UTF-8. A uma primeira olhada parece uma tarefa bem simples, mas não é. Passamos recentemente por um caso real : a conversão do conhecido Gnuteca – software de gerenciamento de acervos e bibliotecas. Apos tudo ficar 100% funciona, vamos dividir um pouco de nossas experiências. A quem possa interessar o Gnuteca passou para UTF-8 a partir da versão 3.3 que será disponibilizada a público ainda em Fevereiro.
Codificação dos arquivos fonte
Para que tudo funcione corretamente primeiramente precisamos converter a codificação de todos arquivos de fonte, para isso utilizamos a ferramenta iconv, atraveś de um script.
O script shell/bash detectará arquivos em ISO e tentará a conversão para UTF. Sim, alguns arquivos podem gerar erro na conversão devido posuírem caracteres estranhos em seu fonte, nesses casos a conversão precisa ser manual.
for FILE in $(find-type f -regex"^.*\.\(php\)$");
doif[ $(file--mime"$FILE"|grep"iso-8859-1"|wc -l)-ne1];
thenecho"Arquivo não iso: $FILE";
elseecho-n"Convertendo $FILE ... "; iconv -f iso-8859-1-t utf-8"$FILE"-o/tmp/1; if[$?-ne0];
thenecho" Erro na conversão";
elseecho" Pronto."; mv/tmp/1$FILE; fi; fi;
done
Apache (virtualhost/php.ini)
MBString no PHP significa Multybite String, isto que adiciona suporte a caracteres UTF-8.
Mbstring.func_overload determinada a quantidade de funções padrão que devem ser substituídas pelas versões mb (multybite), no caso serão as definidas pelas codificações UTF;
Mbstring.internal_encoding determina a codificação interna utilizada pelo php, no caso UTF.
str_pad
Infelizmente mesmo ativando o func_overload a contagem de caracteres através do strpad não funciona corretamente, pois não existe função mb_strpad. Então precisamos criar nossa própria versão do str_pad, com os mesmos parâmetros do original, para compatibilidade.
/**
* StrPad compatível com UTF8.
*
* @param string $input texto original
* @param integer $pad_length quantidade de caracteres que ficará o pad
* @param string $pad_string string para efetuar o pad
* @param integer $pad_type tipo do pad
* @return string
*/public static function strPad($input,$pad_length,$pad_string=' ',$pad_type=STR_PAD_RIGHT){$diff=mb_strlen($input,'ISO-8859-1')-mb_strlen($input,'UTF-8');returnstr_pad($input,$pad_length+$diff,$pad_string,$pad_type);}
O código acima torna possível a utilização do str_pad em UTF-8.
Pode ser necessário fazer uma replace de str_pad por strPad em todo o sistema.
rpl 'str_pad(''strPad'*-R
Aplicar isso em todo o sistema pode ser desastroso, pois existem partes onde realmente é necessário manter o pad em ISO, como no caso do FPDF citado abaixo.
FFDF
A classe FPDF é um dos problemas específicos de classes que não suportam UTF-8, nesse caso temos que criar uma classe nova que extende a FPDF modificando o comportamento no __construct e __destruct.
No construct incluímos uma definição forçando o PHP a trabalhar como ISO.
function __construct($filePath=null,$orientation='P',$unit='mm',$format='A4'){//Necessário para pois a FPDF trabalha com ISO e utiliza funções de strings.ini_set('mbstring.internal_encoding','ISO-8859-1');
No destruct forçamos o PHP a UTF novamente.
function __destruct(){//Habilita novamente o UTF-8 que é o padrão do gnutecaini_set('mbstring.internal_encoding','UTF-8');}
Ainda necessitamos neste caso converter todo o texto passado para a classe para ISO. Para isso utilizamos a classe Gstring que detecta automaticamente qual a codificação do texto e converte para a codificação necessária.
publicfunction cell($w,$h,$txt,$border,$ln,$align,$fill,$link){
parent::Cell($w,$h, GString::construct($txt,'ISO-8859-1'),$border,$ln,$align,$fill,$link);}//Sobreescreve a função para alterar a codificaçãopublicfunction text($x,$y,$txt){
parent::Text($x,$y, GString::construct($txt,'ISO-8859-1'));}//Sobreescreve a função para alterar a codificaçãopublicfunction write($h,$txt,$link){
parent::Write($h, GString::construct($txt,'ISO-8859-1'),$link);}
Existem outras classes que somente funcionam em ISO no caso do Gnuteca tivemos que executar uma correção similar na classe GISORecord, que são especificamente registros em caracteres ISO.
GString
Montamos uma classe que trabalha automaticamente com string de qualquer codificação convertendo automaticamente para UTF-8 por padrão, ou outras codificações caso necessário, é muito mais segura que o utf8_encode/decode pois dectecta a codificação original, evitando assim um codificar uma string já codificada.
$string =new Gstring('meu texto em iso');echo$string;
O resultado será o texto convertido para UTF-8, isso ocorre graças ao método mágico __toString.
Como a classe original ainda não está disponível no repositório oficial, divido-a aqui. GString.class.php.
Header
Em alguns casos, caso persistam os problemas de codificação, nos casos específicos onde o browser não escolhe a codificação correta.
header("Content-type: text/html; charset=utf-8");
Base de dados – Postgres
A conversão da base de dados normalmente é bem simples. Um dump e uma restauração normalmente eficientes.
Mas isso nem sempre é o suficiente. Tivemos problemas com alguns caracteres estranhos, os sqls abaixo resolveram os casos específicos.
UPDATE gtcmaterial SET content =REPLACE(content, chr(160),'#')WHERE fieldid ='008'AND subfieldid ='a';
Outros problemas possíveis
Webservices normalmente aplicam conversão de codificação de forma automática, mas existem casos, onde as strings são serializadas, por exemplo, utiliza-se serialize, ou base64, nem sempre isso funciona de forma limpa então pode ser necessário aplicar algumas das sugestões anteriores.
Banco de dados nem sempre lida corretamente com ligação entre base ISO e UTF8, então em alguns casos precisamos efetuar a conversão manualmente.
2012 chegou e o 2011 se foi, com isso novos artigos sobre novos assuntos aparecem, neste artigo vamos falar sobre a parte básica da criação de plugins para o Inkcape, utilizando a linguagem Python para o desenvolvimento. Eu possuo pouco conhecimento em Python, todo o meu conhecimento se baseia na sintaxe básica da linguagem e um plugin para Gimp que desenvolvi, mas isso não é suficiente para impedir alguém de criar uma extensão para Inkscape.
Inicialmente, para criarmos uma extensão para Inkscape devemos saber onde de encontra a pasta com o conteúdo das extensões, ou seja com os cripts, normalmente essas pasta ficam em:
Linux:
Após isto teremos que criar dois arquivos plugin.inx e plugin.py onde plugin é o nome do plugin, uma observação importante é que eles não podem ficar dentro de pastas dentro da pasta extensions. Vale citar que os dois arquivos precisam de permissão de execucação (chmod +x plugin.inx).
O arquivo inx é o arquivo que define a interface inicial do plugin, sua interface (tela), parâmetros que vai receber e qual script python será chamado.
Já o arquivo py é o script python que será chamado.
Vamos começar com a descrição do arquivo inx, que basicamente é um XML com descrição do que o Inkscape deve fazer. Segue exemplo de extensão (comentada) que está sendo criada para o editor de cenários da Engine Nostaljia, que utilizará o Inkscape como base.
<inkscape-extension><_name>Nostaljia Scenario Attributes</_name><!-- Nome que aparecerá no inkscape--><id>Edit Scenario object</id><!--Não sei onde é usado--><dependencytype="executable"location="extensions">nostaljia.py</dependency><!-- o script python deve estar nas dependências--><dependencytype="executable"location="extensions">inkex.py</dependency><!--dependência padrão do python--><paramname="label"type="description">Apply some Nostaljia Scenario attributes to selected elements</param><paramname="layer"type="int"_gui-text="Layer">0</param><!-- parâmetros que aparecerão na interface--><paramname="solid"type="boolean"_gui-text="Solid">true</param><effect><object-type>all</object-type><effects-menu><submenu_name="Nostaljia"/><!-- Submenu no qual ele aparecerá dentro de Extensões--></effects-menu></effect><script><commandreldir="extensions"interpreter="python">nostaljia.py</command><!-- o script python que será chamado e qual interpretador o inkscape deve utilizar--></script></inkscape-extension>
Então através de poucas linhas conseguimos definir o que o Inkscape deve fazer, quais scripts incluir, qual chamar, onde colocar no menu e quais parâmetros criar.
Devemos descrever com um pouco mais de atenção a questão dos parâmetros:
Neste caso definimos como name o nome utilizado pelo inkscape, como type o tipo que deverá ser esse dado, e como _gui-text o texto que aparecerá na interface, e no caso true representa o valor padrão.
Abaixo vemos uma imagem do resultado do arquivo inx.
A execucão do arquivo inx
Pode ver que a palavra layer foi traduzida para camada através da opção _gui-text, entraremos em detalhes sobre tradução em outro artigo.
Vale citar que o arquivo inx é lido pelo Inkscape, no momento da abertura do programa, para que ele seja recarregado é necessário fechar e abrir novamente o programa.
Após o passo inicial de criação de arquivo inx iniciaremos a criação do arquivo py, arquivo este que é chamado e executado diretamente na hora de apertarmos em “Aplicar”, então podemos ir modificando e testando a sua execução.
Segue o exemplo do arquivo nostaljia.py, uma versão bem simples para demonstração:
import inkex
class C(inkex.Effect):
def__init__(self):
inkex.Effect.__init__(self)self.OptionParser.add_option("-l","--layer", action="store",type="int",dest="layer", default=32,help="Force some layer")self.OptionParser.add_option("-s","--solid", action="store",type="inkbool",dest="solid", default=1,help="Make it solid or not")def effect(self):
#inkex.errormsg("Esta eh uma mensagem de erro")forid, node inself.selected.iteritems():
node.set('solid',str(self.options.solid))ifself.options.layer!=0:
node.set('layer',str(self.options.layer))
c = C()
c.affect()
Importante:
Na construção da classe é importante sempre estender o efeito e fazer a interpretação (parser)de todos os campos criados pela interface, caso faça o parser de algum campo a mais ou a menos um erro será disparado.
class C(inkex.Effect):
def__init__(self):
inkex.Effect.__init__(self)self.OptionParser.add_option("-l","--layer", action="store",type="int",dest="layer", default=32,help="Force some layer")self.OptionParser.add_option("-s","--solid", action="store",type="inkbool",dest="solid", default=1,help="Make it solid or not")
Após isso na função de efeito o laço pelos itens selecionados ( self.selected.iteritems() ) após isso aplicamos a lógica da extensão que no caso adicionas os atributos solid e layer ao objeto de acordo com a situação. Vale lembrar que esses não são atributos lidos ou utilizados pelo Inkscape, mas sim pela Engine, e de forma muito inteligente o Inkscape manter este atributos durante a sua edição, caso um objeto seja copia dentro do programa estes atributos são copiados em conjunto.
def effect(self):
#inkex.errormsg("Esta eh uma mensagem de erro")forid, node inself.selected.iteritems():
node.set('solid',str(self.options.solid))ifself.options.layer!=0:
node.set('layer',str(self.options.layer))
Finalmente instanciamos a classe e chamamos a sua função:
c = C()
c.affect()
Vale citar que caso queiramos mandar uma mensagem de erro ao Inkscape podemos utilizar o comando abaixo:
inkex.errormsg("Esta eh uma mensagem de erro")
O inkex.py é o script básico do Inkscape para padrão, é o que faz a integração, mas outros ótimos scripts podem ser adicionados como o simplestyle.py que gera estilos para o Inkscape de forma simplificada.
Após a execucação do script podemos visualizar o editor de xml que os atributos citados foram adicionados ao retângulo.
Resultado da extensão
Poderiamos facilmente modificar as cores e posicionamentos dos elementos basicamente mexendo nos nodos via Dom, nodos que nada mais são do que os elementos no SVG.
Estava acessando minha galeria do Devianart e resolvi dividir este recurso legal com vocês!
Para quem não sabe o deviantart é um site muito antigo, onde se pode postar desenhos, fotos, textos, entre outros, basicamente um rede social de artistas.
Recentemente comprei uma tevelisão Sony Bravia! Uma belezinha de teve digital por assim dizer.
Descobri que ela tem uma série de recursos legais.
Além de permitir uma série de “canais” online, tocar arquivos mp3,mp4, e mais uma série de formatos, ela permite acesso a um servidor DLNA.
Definindo um servidor DLNA
Rede DLNA
DNLA significa Digital Living Network Allliance, algo como “Aliança Rede Digital Viva”, um servidor DLNA é um servidor de conteúdo multimedia criado pela Sony, com objetivo de compartilhar imagens, músicas e filmes (http://en.wikipedia.org/wiki/Digital_Living_Network_Alliance).
Já a Sony Bravia é um cliente DLNA ou seja ela pode acessar o conteúdo oferecido por um servidor. A imagem ao lado apresenta uma visualização de como funciona uma rede vivia digital.
Agora que entendemos como funciona um servidor DLNA transformaremos o nosso computador pessoal (desktop ou notebook) e um servidor DLNA, para isso utilizamos o software Mediatomb.
Para instalar o servidor no ubuntu simplesmente executamos:
sudo apt-get install mediatomb
Ao executar o mediatomb recebemos as mensagens abaixo, essa é a mensagem de um resultado padrão, que é 100% funcional para a TV.
MediaTomb UPnP Server version 0.12.1 - http://mediatomb.cc/
===============================================================================
Copyright 2005-2010 Gena Batsyan, Sergey Bostandzhyan, Leonhard Wimmer.
MediaTomb is free software, covered by the GNU General Public License version 2
2011-12-06 17:22:45 INFO: Loading configuration from: /home/trialforce/.mediatomb/config.xml
2011-12-06 17:22:45 INFO: Checking configuration...
2011-12-06 17:22:45 INFO: Setting filesystem import charset to UTF-8
2011-12-06 17:22:45 INFO: Setting metadata import charset to UTF-8
2011-12-06 17:22:45 INFO: Setting playlist charset to UTF-8
2011-12-06 17:22:45 WARNING: You enabled the YouTube feature, which allows you
to watch YouTube videos on your UPnP device!
Please check http://www.youtube.com/t/terms
By using this feature you may be violating YouTube
service terms and conditions!
2011-12-06 17:22:45 INFO: Configuration check succeeded.
2011-12-06 17:22:46 INFO: Initialized port: 49152
2011-12-06 17:22:46 INFO: Server bound to: 192.168.1.102
2011-12-06 17:22:47 INFO: MediaTomb Web UI can be reached by following this link:
2011-12-06 17:22:47 INFO: http://192.168.1.102:49152/
Isso mostra que o servidor está iniciado e o endereço http://192.168.100.110:49152 informa o endereço da interface web onde podemos configurar quais pastas serão compartilhadas através do Mediatomb.
Interface web do mediatomb. Simples de usar, mas não tão bonita ...
Na Bravia
Bravia internet video
Passo a passo para acessar os conteúdos na TV.
1. Na TV vamos em Home->Ajustes->configurações de rede para configurar a rede, vale lembrar que a TV vai precisar de um cabo de rede normal (aqueles azulzinhos) para entrar em rede.
2. Como segundo passo vamos ativar o servidor na TV, para isso vá em Home->Ajustes->Configuração de rede doméstica->Incluir/Omitir Serv. de Mídia, o servidor deve aparecer na lista, então é só ativar.
3. Feito isto vamos em Home->Mídia->videos->Mediatomb, no caso podemos escolher vídeos, músicas ou fotos.
Belezinha, tudo funcionando perfeito não é? NÃO!
A TV tem suporte limitados a codecs de vídeo, não é qualquer formato ou qualquer MP4 que vai funcionar não, e o mais legalzinho, não tem suporte nenhum a legendas SRT. Fudeu tudo?
Mencoder
Não, o mencoder tem a solução para gente! Instalamos ele usando:
Feito, esse comando mágico converte nosso vídeo para o formato exato da TV, e com muita qualidade, caso queira menos qualidade, ou seja vídeos de tamanho menor mudei o vbritate=4000 para um valor menor, normalmente uns 1500 deve ser o suficiente.
Beleza, com isso assisti o meu primeiro filme em hd!
Cowboys e Aliens, o filme não tava tão bom vil? Mas a qualidade da imagem tava magnifica!!
Quem tiver dúvidas fique a vontade para fazer perguntas nos comentários do post!
Exemplo de uso de javascript na biblioteca (não adianta nada se seu browser não suportar SVG):
E o código fonte do exemplo acima:
$svg= SVGDocument::getInstance();$svg->setTitle("Javascript example");#add some javascript functions
$svg->addScript("
function changeColor(evt, element)
{
destination = document.getElementById('destination');
if ( evt.ctrlKey )
{
destination.style.stroke = element.style.fill;
}
else
{
destination.style.fill = element.style.fill;
}
evt.preventDefault();
return false;
}
");#mount a simple color array
$colors[]='red';$colors[]='green';$colors[]='blue';$colors[]='yellow';$colors[]='orange';$colors[]='gray';$colors[]='black';$colors[]='white';$text= SVGText::getInstance(10,25,null,'Left click for fill - control click for stroke');$svg->addShape($text);foreach($colorsas$line=>$color){$rect= SVGRect::getInstance(($line*60)+10,40,null,50,50);$style=new SVGStyle();$style->setFill($color);$style->setStroke("darkGray",1);$rect->setStyle($style);$rect->addOnclick("return changeColor(evt,this);");$rect->addAttribute("onmouseover","this.style.stroke = 'lightGray';");$rect->addAttribute("onmouseout","this.style.stroke = 'gray';");$svg->addShape($rect);}$rect= SVGRect::getInstance(140,100,'destination',200,200);$style=new SVGStyle();$style->setFill('none');$style->setStroke("darkGray",5);$rect->setStyle($style);$svg->addShape($rect);$svg->output();
Segue abaixo relação completa do changelog:
VERSION 0.7 - Nov 16 2011
- Added support for line
- Added support for circle.
- Added support for ellipse.
- Added support for radial gradient.
- Added support for round rect.
- Added javascript support.
- Added support for title and description
Examples:
- Added javascript example.
- Added merge example.
- Added text replace.
- Addes Line graph example
Para todos que acompanham o blog, devem ter reparado na classe de SVG para PHP que criei, sendo que o que deu inicio a ela foi realmente um post aqui do blog sobre SVG.
Pois então, inseri a classe no PHPClasses e ela ganhou o Prêmio de inovação de Agosto de 2011.
Ah, também gostaria de agradecer as 40 mil visitas que o blog já possui.
Ando meio sumido do blog por um bom motivo (desta vez não é Nintendo Wii não), estou criando o protótipo do game Street of Chaos. Como o protótipo ainda não é uma versão de demonstração só ficaremos com uma screenshot por enquanto.
Sei que estou sendo chato querendo falar sobre a classe PHPSVG denovo, mas tem sido muito legal pra mim o feedback que estou recebendo, hoje recebi um email dizendo que minha classe está concorrendo a prêmio de inovação do PHP Classes:
SVG is a standard XML format for storing the definitions of two dimension vectorial graphics.
This class can be used to edit vectorial graphics by reading its definition from an SVG into objects that can be changed and then write it back to the SVG file.
Hoje quero divulgar o novo blog que estou montando com ajuda de amigos e colegas, se trata do Beat ‘n up Project, trata principalmente sobre desenvolvimento de jogos, mas o foco não é a programação, apesar que algumas coisas nesse sentido aparecerão, a ideia é falar sobre GDD Game Design Document, a bíblia do jogo no caso, falar sobre criação de jogos, enredos, histórias, esboços, arte, sons, jogabilidade, análise de outros jogos, no sentido de interpretação de GDD, também falaremos sobre o nosso Projeto de jogo o “Street of Chaos” ainda com nome provisório.
Hoje quero mostrar dois exemplos de fotos transformadas em pixel arte. Foi uns dos presentes de 2 anos de namoro que fiz pra minha garota. Tudo foi feito usando o GIMP.
As imagens ficam trocando entre um esboço da original e a pixel arte em si.
Todo software tem dependências, bibliotecas, pacotes, programas ou outras “coisas” da qual a aplicação depende.
Quando o software começa a ser instalado em diversos clientes, queremos que esses pré-requisitos estejam de acordo e precisamos de uma forma automatizada de garantir um mínimo de garantias de funcionamento.
É nesse ponto que entra o conceito de “Testes de dependências”, criamos via software, uma interface que verifica (“checa”) todas as dependências possíveis via software.
Utilizamos no Gnuteca uma classe chamada GDependencyCheck, nas seguintes linhas comentarei alguns detalhes dessa classe, vale citar que o código não deve ser copiado/colado, simplesmente serve como referência para uma implementação própria. Quando alguma classe do Gnuteca for citada (no fonte), ela terá um explicação ao lado citando a sua funcionalidade.
Então uma classe (Poderemos chamar de DependencyCheck) criamos um método que lista todas as verificações que serão feitas:
publicfunction listDependency(){$list[]=array('gdInstalled','Gd (Image library)');$list[]=array('yazInstalled','Yaz installed (used by Z3950)');$list[]=array('ldapInstalled','LDAP installed');$list[]=array('filePermission','Default file permission');$list[]=array('logPermission','Log write Permission');$list[]=array('linkedFiles','Gnuteca files that must be inside miolo/html/');$list[]=array('emailConfigured','Email is configured and sending');$list[]=array('printerSocket','Printer is using socket system');$list[]=array('gCron','GCron');...
Cada sub-array conta com a função e o nome do teste. A função acima retorna a listagem completa dos testes a serem efetuados.
O nome do teste é usado no formulário para mostrar os resultados de forma mais amigável
Seguindo a ideia criaremos cada uma das funções de verificação, no caso abaixo a função gdInstalled faz exatamente isso, verifica se a biblioteca de edição/criação de imagens está instalada.
/**
* Verifica se a biblioteca de imagem GD está instalada.
*
* @return <boolean>
*/publicfunction gdInstalled(){$this->setMessage( GD_VERSION );returnextension_loaded('gd')&&function_exists('gd_info');}
A funcionalidade abaixo mostra uma mensagem com a versão do GD (só irá aparecer caso exista um valor na constante) em seguida utilizamos a verificação extension_loaded, passando como parâmetro “GD“, isso retornará que a extensão do PHP está instalada, para termos certeza absoluta, verificamos através da função function_exists se a função “gd_info” existe, essa função é básica da biblioteca, se ela existe e a extensão está carregada a chance muito grande de tudo estar funcionando corretamente.
Podemos notar que essa função (gdInstalled) chama a função setMessage, que nada mais faz do que definir a propriedade message da classe, o corpo do método seria:
Seguindo a linha de raciocínio temos mais um exemplo, neste caso verificaremos se o formato do banco de dados (no caso Postgres), está definido corretamente.
/**
* Verifica se o estilo da data do banco de dados está definido corretamente
*
* @return <boolean>
*/publicfunction dateStyle(){$bus =new GBusiness();//classe genérica de regras de negocio do Gnuteca, permite a execução de SQLs.$result =$bus->executeSelect("SELECT setting from pg_settings where name = 'DateStyle';");//executamos o SQL especificado.$confirm ='ISO, DMY';//string que verifica o datestyle correto//caso a string de confirmação aparece no primeiro item do resultado quer dizer que o estilo da data está correto.$ok=stripos(' '.$result[0][0],$confirm)>0;if(!$ok){//caso o estilo não está correto informamos o usuário como corrigir$this->setMessage("Execute no banco de dados: ALTER DATABASE :DBNAME SET DateStyle TO 'ISO, DMY';");}return$ok ;//retornamos o resultado do teste}
Como pode ser notado pelos comentários, obtemos a classe que permite a execução de SQLS (GBusiness), executamos um select e comparamos o resultado com uma string que temos certeza que está correta.
É importante mostrar uma solução possível, caso seja uma resolução simples, como este caso: uma simples execução de um select resolve o problema. É interessante notar que o dateStyle do banco não é exportado junto com o dump do postgres, em função disto o teste deve confirmar se tudo está correto.
No caso do teste do GD não retornamos uma solução pois a instalação de uma extensão de PHP pode mudar drasticamente em cada sistema operacional.
No formulário (conforme imagem abaixo), obtemos a listagem de testes e um simples laço chamando a função especifica resolve o nosso problema.
$dependency=new DependencyCheck();//nossa classe que criamos$list=$dependency->listDependency();if(is_array($list))//confere se é um array, por segurança{foreach($listas$line=>$info){$function=$info[$line][0];//obtem o nome da função$result[]=$dependency->$function();//executa o teste}}
No caso do Gnuteca os testes são executados de forma assincrona via ajax (diferente do exemplo acima), mas o código acima deve ser o suficiente para execução.
De posse do array de resultado imprimimos-o na tela.
A mágica está no trecho abaixo:
$dependency->$function();
Magicamente o PHP intepreta o nome da variável e executa a função, maravilhas de linguagens de script.
Para o usuário/instalador o resultado abaixo é apresentado:
Resultado da execução de testes de dependências
O que tem acontecido na prática do dia a dia, é que os testes de dependências tem evitado muitas dores que cabeça que tínhamos em versões anteriores do software, e quando detectamos algum novo teste que merece ser feito (devido a feedbacks dos clientes e avaliações da equipe) acrescentamo-lo a listagem de dependências.
Resumindo: na versão 3.2 (Release Oficial do Gnuteca) temos cerca de 20 testes, já na atual versão de desenvolvimento ( não pronta) já constamos mais de 40 testes, quanto mais testes, mais certezas teremos de que tudo funciona como o esperado, e menos problemas os clientes ( e nós ) teremos, por fim resultado diretamente na qualidade da aplicação.
P.S.: Testes de dependências não ter nada a ver com testes unitários, que são basicamente testes que visam evitar erros do programador, devido a mudança de código, você faz um refactor no código e o teste unitário “garante” que isso não resultará em impactos negativos no sistema. Trataremos de testes unitários em outro artigo.
<?phprequire_once"../svglib/svglib.php";$svg= SVGDocument::getInstance('resource/apple.svg');//open to edit//$svg = SVGDocument::getInstance( ); //default read to use$rect= SVGRect::getInstance(0,5,'myRect','fill:#f2f2f2;stroke:#e1a100;',228,185);$rect->setWidth($svg->getWidth());//page width$svg->addShape($rect);$svg->addShape( SVGText::getInstance(22,50,'myText',"font-size:56px;font-style:normal;",'This is a text'));$svg->asXML('output/output.svg');//output to svg file$svg->export('output/output.png');//export as png$svg->export('output/thumb32x32.png',32,32);//export thumbnail$svg->output();//echo with header to browser ?>
Isso anima a continuar o projeto e deixar a classe ainda mais completa!
Este artigo visa ensinar a forma errada e porca, inclusive sem bom resultado de fazer pixel arte.
Acontece que é muito rápido de fazer e pode ser utilizado como “preview” da pixel arte final, ou como um imagem para ser trabalhada!
Obtemos como base a imagem abaixo, Superman, Batman e Wondernam ( gosto mais do Batman)
Como transformaremos isso em pixel arte em poucos passos?
Imagem do passo 1.
1º Passo: aumentar as áreas pretas, dessa forma o resultado final fica com mais cara de pixel arte, para isso amos em Cores-> Níveis, seguindo mais ou menos a idéia da imagem mesmo, puxando o bagulinho da esquerda mais pro centro a imagem se torna mais escura.
Imagem do passo 2.
2º Passo: Posterizar (Reduzir número de cores) – A funcionalidade de posterizar faz exatamente o proposto, reduz o número de cores da imagem, seguindo o exemplo acima, no caso conseguimos converter nossa imagem para cores indexadas (onde a imagem pode ter no máximo 256 cores). O resultado ficou bem rasoável.
Imagem do passo 3 (Tamanho real).
3º Passo: de posse da imagem anterior já indexada, reduzimos a imagem em 50% do tamanho, o redimensionamento com cores indexadas gera um resultado diferente do redimensionamento original. Essa imagem já “seria” um pixel arte em alta resolução, pois essa imagem tem nesse momento aproximadamente 100 cores.
Imagem do passo4 (Tamanho real).
4ª Passo: Continuando o processo reduzimos a imagem para largura de 320 pixels e deixamos o gimp manter a proporção, nesse momento conseguimos uma imagem com 60 cores, em um tamanho semelhante as resoluções de jogos antigos e celulares.
Você deve estar se perguntando, porque redimensionar duas vezes? Pois com cores indexadas ao reduzir muito a imagem de uma só vez o resultado não fica muito bom, esse é um dos segredos do FakePixelArt.
Nossa imagem está pronta, abaixo uma visualização duplicada para acompanharmos o resultado de perto.
Resultado final (duplicado).
Não é pixel arte de verdade, a partir dessa imagem poderíamos ajeitar ela até chegarmos ao ponto da pixel arte real, ou poderiamos utilizar essa como referência e ir desenhando em outra camada a nossa pixel arte real. É uma boa base para trabalhos.
Hoje queria divulgar um serviço de hd virtual muito útil, o dropbox.
Funciona como uma pasta no seu computador que fica ao mesmo tempo no servidor, faz backup automático, da para sincronizar entre vários computadores e vários sistemas, inclusive celular e tudo mais.
Também é possível acessar seus arquivos pela página do dropbox, existe uma pasta pública onde é possível disponibilizar seus arquivos para que outros usuários baixem eles.
Ainda existe o recursos de compartilhamento de pasta, onde você e um amigo com dropbox podem compartilhar e editar os mesmo arquivos.
O sistema ainda guarda histórico de cada modificação para que seja possível retornar a uma versão antiga, quase um micro svn.
Acima esta uma imagem tirada de meu desktop Ubuntu 11.04 com kde, mostrando o trayicon do dropbox, e a pasta dele, é possível notar que cada pasta exibe o estado de sincronização. Essa integração funciona perfeitamente no Gnome ou no Windows, tanto XP, como Vista ou 7.
Seja qual for o uso que você der para o dropbox, sem dúvida é uma boa ferramenta.
Se quiserem ganhar um espaço extra, usem o link abaixo:
Hoje vamos falar um pouco sobre as diferenças entre Gnome e Kde, mas não diferenças de projeto e ou de desenvolvimento, vamos falar sobre diferenças de usabilidade. Qual dos dois seria mais recomendado para um usuário leigo?? Por fim, qual é o melhor?
É difícil determinar qual é o melhor, pois isto está relacionado a opnião de cada pessoa.
Vamos começar citar algumas diferenças:
KDE
Menu principal: o menu principal do KDE é maravilhoso, tem suporte a busca por programas, favoritos, tem também o menu padrão dentro da aba aplicativos, bem completo.
Painéis: o suporte a painéis é completo, podendo colocar o tamanho e a posição necessária, todos os widgets podem ser incluídos nos painéis.
Widgets: o KDE tem grande quantidade de widgets prontos para uso, sem precisar de nenhuma instalação, apesar de ser simples de instalar novos. Adoro o suporte a widgets do KDE, o widget de notas tem me sido muito útil.
Temas: o KDE tem suporte completo a modificação de temas de forma intuitiva, também é muito simples adicionar novos temas através da interface.
Fundos de tela: possuí diversas formas de configurar fundo de tela, inclusive a opção de escolher uma ou mais pastas para que seja trocada as imagens de tempo em tempo.
Efeitos de desktop: o KDE possui efeitos de Desktops maravilhosos, que me parecem muito bem integrados ao sistema.
Painel de controle e configurações: O KDE possui um painel de controle integrado com possibilidade de configuração praticamente todo o sistema de forma facilitada.
Gnome:
Menu Principal: o menu principal do gnome é muito parecido com o menu tradicional do windows 98/XP funciona muito bem, é simples e funcional, infelizmente não tem a opção de busca.
Painéis: o suporte a painéis é completo é possível posicionar e redimensionar como a achar necessário. neste ponto é identico ao KDE, tem uns widgets de painel muito úteis.
Widgets: o Gnome não tem suporte nativo a widgets, mas existem pacotes que podem ser incluídos para adicionar essa facilidade, como por exemplo o screenlets.
Temas: o Gnome não tem suporte padrão a instalação de novos temas, é possível baixá-los através do site gnome-art e fazer a instalação, mas existe um aplicativo que faz isso pra você também que pode ser instalado.
Fundos de tela: o Gnome é mais limitado nos recursos de fundos de tela, é possível trocar as imagens de tempo em tempo, mas tem que ser em uma pasta específica e não tem como selecionar o tempo de troca de imagem.
Efeitos de desktop: o Gnome utiliza o compiz para ativar efeitos de desktop, ele deve ser instalado a parte, mas funciona muito bem.
Painel de controle e configurações: o painel de controle do Gnome é mais dividido em pequenos programas, onde cada um configura uma coisa, e existem opções que só podem ser modificadas em arquivos em linha de comando.
Conclusão:
Eu usei o Gnome por 4 anos, e passava todo o meu tempo instalando coisas para fazer funcionar tudo o que eu queria, enquanto alguns amigos eram bem contentes com as funcionalidades que já existiam.
Então troquei para o KDE e tudo que eu queria no Gnome estava disponível e pronto para uso no KDE, sem se esforçar nem instalar nem configurar.
Os dois são bem estáveis e funcionam corretamente, então se você não se preocupa muito com as “frescuras” e somente quer uma interface para uso o Gnome é ideal, caso queira toda uma série de funcionalidades e “frescuras” ( como eu) é melhor usar o KDE.