Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Центр помощи
  • » Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре [RSS Feed]

#1 Фев. 28, 2013 11:40:10

Nikoil
Зарегистрирован: 2013-02-27
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Нужна помощь.Нужно реализовать функцию вопроизведения звукового фала по кругу.
Пример после нажатия на кнопку клавиатуры up непрерывно играет wav файл до тех пор пока кнопку up не отпустят.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Based on http://www.marsohod.org/index.php/projects/plata1/205-carctrlandr
import os
import BaseHTTPServer
from threading import Thread
import urlparse
import time
import string
try:
    import android
    droid = android.Android()
except ImportError:
    def mediaPlay(path):
        print "PLAY", path
    import mock
    droid = mock.Mock()
    droid.mediaPlay = mediaPlay
HOST_NAME = ''
PORT_NUMBER = 9090
COMMAND_SEND_INTERVAL = 1.0  # seconds
COMMAND_TIMEOUT = COMMAND_SEND_INTERVAL * 2
PAGE_TEMPLATE = '''
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>DroidBot Remote Control</title>
</head>
<FRAMESET ROWS="67%,33%">
<FRAME SRC="frame_a.html">
<FRAME SRC="frame_b.html">
</FRAMESET>
</html>
'''
PAGE_TEMPLATE_A = '''
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<center>
<iframe scrolling="no" width="640" height="480" src ="http://%s:8080/videofeed">No iframes?</iframe>
</center>
</body>
</html>
'''
PAGE_TEMPLATE_B = string.Template('''
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>DroidBot Remote Control</title>
<style type="text/css">
    #action {
        background:yellow;
        border:0px solid #555;
        color:#555;
        width:0px;
        height:0px;
        padding:0px;
    }
    #joystick {
        background: black;
        color: white;
        width: 100%;
        height: 100%;
        overflow: hidden;
        padding: 0;
        margin: 0;
        -webkit-user-select: none;
        -moz-user-select: none;
    }
    .btn{
        width: 7em;
        height: 2em;
    }
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//jeromeetienne.github.com/virtualjoystick.js/virtualjoystick.js"></script>
<script>
$(document).ready(function(){
    function CommandSender(cmdInterval){
        this.cmdInterval = cmdInterval;
        this.lastCmd = "";
        this.lastState = "";
        this.lastTime = new Date();
    }
    CommandSender.prototype.run = function(){
        var $this = this;
        setInterval(function(){
            $this.updateState($this.lastState, $this.lastCmd);
        }, this.cmdInterval);
    }
    CommandSender.prototype.updateState = function(state, cmd){
        if((new Date() - this.lastTime) < this.cmdInterval &&
            cmd == this.lastCmd && state == this.lastState)
            return;
        if (state == "begin" && cmd){
            this.sendCommand(state, cmd);
        }
        else if (state != this.lastState) {
            this.sendCommand("end", cmd);
        }
        this.lastState = state;
        this.lastCmd = cmd;
        this.lastTime = new Date();
    }
    CommandSender.prototype.sendCommand = function(state, cmd){
        $.post('command/' + state + ':' + cmd, function(resp){
            console.log(resp);
        });
    }
    var cmdInterval = ${COMMAND_SEND_INTERVAL};
    (function buttonsHandler(){
        var sender = new CommandSender(cmdInterval);
        $(".btn").mousedown(function(){
            sender.updateState("begin", $(this).data("command"));
        }).mouseup(function(){
            sender.updateState("end", $(this).data("command"));
        }).mouseleave(function(){
            sender.updateState("end", "");
        });
        sender.run();
    })();
    (function keyBoardHandler(){
        var sender = new CommandSender(cmdInterval);
        var arrow = {37: 'left', 38: 'up', 39: 'right', 40:'down'};
        $(document).keydown(function (e) {
            var keyCode = e.keyCode || e.which;
            var cmd = arrow[keyCode];
            if (cmd)
                sender.updateState("begin", cmd);
        }).keyup(function (e) {
            sender.updateState("end", "");
        });
        sender.run();
    })();
    
    (function joystickHandler(){
        var joystick  = new VirtualJoystick({
            container	: document.getElementById('joystick'),
            mouseSupport	: true
        });
        var sender = new CommandSender(cmdInterval);
        setInterval(function(){
            var cmd = ""
            var state = "begin";
            if(joystick.up()){
                cmd = "up";
            } else if (joystick.down()) {
                cmd = "down";
            } else if (joystick.left()) {
                cmd = "left";
            } else if (joystick.right()) {
                cmd = "right";
            } else {
                state = "end";
            }
            sender.updateState(state, cmd);
        }, 1/30 * 1000);
    })();
});
</script>
</head>
<body>
<center>
    <table border=0>
        <tr>
            <td></td>
            <td><button class="btn" data-command="up">Up</button></td>
            <td></td>
        </tr>
        <tr>
            <td><button class="btn" data-command="left">Left</button></td>
            <td></td>
            <td><button class="btn" data-command="right">Right</button></td>
        </tr>
        <tr>
            <td></td>
            <td><button class="btn" data-command="down">Down</button></td>
            <td></td>
        </tr>
    </table>
    <div id="joystick">Joystick area. Press and drag (touch or mouse). Or use keyboard arrows</div>
</center>
</body>
</html>
''').safe_substitute(COMMAND_SEND_INTERVAL=int(COMMAND_SEND_INTERVAL * 1000))
class CarControllerThread(Thread):
    path_to_audio = '/mnt/sdcard/droid_car/'
    command_to_audio = {
        'up': 'up.wav',
        'down': 'down.wav',
        'left': 'left.wav',
        'right': 'right.wav',
    }
    def __init__(self, timeout=1):
        super(CarControllerThread, self).__init__()
        self.timeout = timeout
        self.pool_timeout = timeout / 3.0
        self.current_state = ""
        self.current_command = ""
        self.last_cmd_timestamp = time.time()
    def run(self):
        while True:
            elapsed = time.time() - self.last_cmd_timestamp
            if self.current_state == "begin" and elapsed > self.timeout:
                self.update_state("end", "")
            time.sleep(self.pool_timeout)
    def update_state(self, state, command):
        self.last_cmd_timestamp = time.time()
        if state == self.current_state and command == self.current_command:
            return
        self.current_state = state
        self.current_command = command
        if state == "end":
            print "PAUSE"
            droid.mediaPlaySetLooping(False)
            droid.mediaPlayPause()
        elif state == "begin":
            print "PLAY", command
            audio = self.command_to_audio.get(command)
            if audio:
                droid.mediaPlay(os.path.join(self.path_to_audio, audio))
                droid.mediaPlaySetLooping(True)
            else:
                print "wrong command:", command
class DroidHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html; charset=utf-8")
        self.end_headers()
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html; charset=utf-8")
        self.end_headers()
        url = urlparse.urlsplit(self.path)
        print url.path
        if url.path == '/frame_a.html':
            ip, port = self.headers.get('Host').split(":", 2)
            self.wfile.write(PAGE_TEMPLATE_A % ip)
        elif url.path == '/frame_b.html':
            self.wfile.write(PAGE_TEMPLATE_B)
        else:
            self.wfile.write(PAGE_TEMPLATE)
    def do_POST(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain; charset=utf-8")
        self.end_headers()
        if self.path.startswith("/command/"):
            try:
                #/command/state:up
                state, cmd = self.path.split("/")[-1].split(":")
            except ValueError:
                print "ERROR", self.path
                self.wfile.write("fail")
                return
            controller.update_state(state, cmd)
            self.wfile.write("ok")
        elif self.path.startswith("/ping"):
            self.wfile.write("pong")
controller = CarControllerThread(COMMAND_TIMEOUT)
controller.start()
try:
    droid.wakeLockAcquireBright()
    droid.webcamStart(0, 10, 9091)
    droid.webcamAdjustQuality(0, 10)
except Exception as e:
    print "Webcam error", e
my_srv = BaseHTTPServer.HTTPServer((HOST_NAME, PORT_NUMBER), DroidHandler)
print 'web server running on port %s' % PORT_NUMBER
my_srv.serve_forever()

Код взят отсюда http://www.marsohod.org/index.php/projects/plata1/205-carctrlandr
для применения в этом проекте http://4pda.ru/forum/index.php?showtopic=435445

Буду очень признателен тем кто поможет

Отредактировано Nikoil (Март 4, 2013 12:35:05)

Офлайн

#2 Март 1, 2013 15:28:02

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Забавная штука. Как раз хотел под Android что-нибудь написать.

https://gist.github.com/reclosedev/5064616

Файлы из Sound command v02.rar в path_to_audio = ‘/mnt/sdcard/droid_car/’
скрипт в /mnt/sdcard/sl4a/scripts/

Как в виде .apk распространять не знаю, но вроде есть способы.

Офлайн

#3 Март 2, 2013 14:12:47

Nikoil
Зарегистрирован: 2013-02-27
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Даже не знаю как описать на сколько я рад
Есть потери некоторых звуков - но я сделаю их немножко длинней и одинаковыми по времени воспроизведения и сдлеаю инструкцию с видеообзором на 4pda.
Для апк это не подойдет - но как версия для управления с пк отличный вариант.
Еще раз спасибо.

Офлайн

#4 Март 2, 2013 19:16:23

Nikoil
Зарегистрирован: 2013-02-27
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Сдел видео.Звук играет несколко циклов хорошо, а потом интервал. Несколько циклов и интервал.Повторяется на всех командах.
http://www.youtube.com/watch?v=uoGBsIYU5Zk&feature=youtu.be

Это можно исправить?

Отредактировано Nikoil (Март 2, 2013 19:39:28)

Офлайн

#5 Март 2, 2013 20:41:46

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Похоже, баг Android
https://code.google.com/p/android/issues/detail?id=18756

Кстати, скиньте новые аудио файлы.

Отредактировано reclosedev (Март 2, 2013 20:42:10)

Офлайн

#6 Март 2, 2013 21:36:47

Nikoil
Зарегистрирован: 2013-02-27
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

http://4pda.ru/forum/dl/post/2633134/Sound+command+v03.rar

А если звуковой файл сдлеть длинней примерно 20 секунд с цикличностью (первые 2-3 прокрутки идут без задержки) А действия сделать так:
действие нажал кнопку - трек играет по кругу , а функция отпустил кнопку - стоп воспроизведения трека.

(и команд будет передаваться меньше 1ая start play 2ая stop play) и нагрузка на android меньше.

Это как вариант.Т.к. может быть такое что одна из команд не дойдет до устройства.

Отредактировано Nikoil (Март 2, 2013 21:52:34)

Офлайн

#7 Март 3, 2013 09:19:32

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Nikoil
А если звуковой файл сдлеть длинней примерно 20 секунд с цикличностью (первые 2-3 прокрутки идут без задержки)
Да это поможет, но между этими N секундами интервал все равно останется. Думаю 20 сек много, файл 2 МБ получается, может и 10 секунд хватит для команды?
Nikoil
А действия сделать так:
действие нажал кнопку - трек играет по кругу , а функция отпустил кнопку - стоп воспроизведения трека.
(и команд будет передаваться меньше 1ая start play 2ая stop play) и нагрузка на android меньше.
Сначала так и сделал.
Nikoil
Это как вариант.Т.к. может быть такое что одна из команд не дойдет до устройства.
Да, по Wi-fi команды могут теряться (при тестах терялись). Именно поэтому команда и передается с некоторым интервалом, пока кнопка нажата, чтобы можно было отличить потерю команды стоп от очень долгого нажатия.

Т.е. сейчас, когда приходит команда, запускается зацикленное (средствами android) проигрывание файла. Если за время COMMAND_TIMEOUT секунд не приходит новая команда, воспроизведение останавливается. Если приходит та же команда, что сейчас выполняется, ничего не происходит (точнее записывается время), если приходит команда стоп, то текущее воспроизведение останавливается. Это все не должно сильно грузить android.

Но можно чуть увеличить интервал отправки команды и таймаут (см. изменения в коде, по той же ссылке), чтобы уменьшить объем передаваемых данных по сети.

Вообще, тут бы лучше подошел UDP, но тогда нужно было бы писать ГУИ клиент под несколько платформ, а браузерный даже на андроиде должен работать.

Отредактировано reclosedev (Март 3, 2013 09:24:38)

Офлайн

#8 Март 3, 2013 13:41:58

Nikoil
Зарегистрирован: 2013-02-27
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Работает лучше.Звуковые файлы по 10 секунд.На неделе протестирую на практике( с платформой)

Офлайн

#9 Март 4, 2013 12:33:26

Nikoil
Зарегистрирован: 2013-02-27
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Заметил проблему.Сбит центр джойстика - прикрепил фото №1.(код в шапке заменил на ваш с моими маленькими изменениями)
Убрал прокрутку в видео окне. Отцентровал кнопки управления и окно видео.

——————–

И что если сделать iframe по вертикали?Сделал набросок на фото.
При таком расположении станет удобно управлять даже с телефона, а на пк тач панель просто можно свернуть в ручную если будет мешать .Левое окно как вариант в авто масштаб.Только вот кнопки управления up,down,left,right нужно будет переместить из iframe B в iframe A.






Отредактировано Nikoil (Март 4, 2013 13:03:57)

Прикреплённый файлы:
attachment 1.jpg (112,3 KБ)

Офлайн

#10 Март 4, 2013 18:03:35

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре

Nikoil
Заметил проблему.Сбит центр джойстика - прикрепил фото №1.(код в шапке заменил на ваш с моими маленькими изменениями)
Убрал прокрутку в видео окне. Отцентровал кнопки управления и окно видео.
Да тоже видел. virtualjoystick.js ориентируется на координаты страницы, а не контейнера. Поэтому нужно или код менять (что не хочется) или в iframe его засовывать (сделал).

Nikoil
И что если сделать iframe по вертикали?Сделал набросок на фото.
При таком расположении станет удобно управлять даже с телефона, а на пк тач панель просто можно свернуть в ручную если будет мешать .Левое окно как вариант в авто масштаб.Только вот кнопки управления up,down,left,right нужно будет переместить из iframe B в iframe A.
Сделал без фреймов, т.к. с ними геморой.
Не стал заморачиваться с возможностью изменения размеров колонок (как у фреймов), но вроде есть решения.
Ссылка та же.

Офлайн

  • Начало
  • » Центр помощи
  • » Нужна помощь.Фунция воспроизведения wav по кругу при удерживании клавиши up на клавиатуре[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version