Skip to content

Commit

Permalink
solve conflict with master
Browse files Browse the repository at this point in the history
  • Loading branch information
Gil Brechbuhler committed Aug 18, 2016
2 parents 20dc06e + 64eb9f8 commit 0c12d46
Show file tree
Hide file tree
Showing 40 changed files with 1,100 additions and 83 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Expand Up @@ -107,3 +107,9 @@ ebu_tt_live/bindings/raw

# Test export files from file system carriage
test_export/

# Node.js file
node_modules/

# Precompiled js file
ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.js
21 changes: 19 additions & 2 deletions .travis.yml
Expand Up @@ -2,20 +2,37 @@ language: python

python:
- '2.7'


before_install:
- openssl aes-256-cbc -K $encrypted_f18bb5b3c3d4_key -iv $encrypted_f18bb5b3c3d4_iv -in publish-key.enc -out ~/.ssh/publish-key -d
- chmod u=rw,og= ~/.ssh/publish-key
- echo "Host github.com" >> ~/.ssh/config
- echo " IdentityFile ~/.ssh/publish-key" >> ~/.ssh/config
- sudo apt-get -qq update
- sudo apt-get install graphviz
- git --version
- git remote set-url origin git@github.com:ebu/ebu-tt-live-toolkit.git
- git fetch origin -f gh-pages:gh-pages

install:
- pip install pip==8.1.2
- make
- python setup.py develop
- pip install coveralls
- pip install ghp-import

script:
- pyxbgen --binding-root=./ebu_tt_live/bindings -m __init__ --schema-root=./ebu_tt_live/xsd1.1/ -r -u ebutt_live.xsd
- python setup.py test
- export PR=https://api.github.com/repos/$TRAVIS_REPO_SLUG/pulls/$TRAVIS_PULL_REQUEST
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo `curl -s $PR | jq -r .head.ref`; fi)
- echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH"

after_success:
- coveralls

- python setup.py build_sphinx
- if [ $BRANCH == "master" ]; then ghp-import -n -p -m "Update gh-pages." docs/build/html; fi

notifications:
slack:
secure: RLs+ufYg4HcZfaTl73tTKKVja8DJ9LGk1WO+7B1qa4Fgpv0c/3uXcM+6tvDXllTlqcfLHgum0vbzvE4yapo0em0g/m75t1pEfkh5Pfrcas8IKAM9jg/xycWdYoAkKLRvNOcS4amO29FlzOHFaSSjX+V8JK8Mpm+QM2eGnqIbJokaXgBf/bQxHqGSRvYCeSisEG0f79Mn/0v5OOlbvmetFfvcQVNZDtgpA1CDbvK99F/vQT3qZ04Rh/vRnlcZyH9PEp/TEEJ0yX0NhHYEDnuBKPc86Ack/YCQpT12Ej2xTWjgoUrqv1pcr+h0ltYPXnnCyETrlbeLgNIMUsGW579MThqXekBZ7byRK2DMfjyL5+UgPSmTOIzEg7Qbc1u0r1bUuEi7nsJ5Vf65QeIAcewVASOUKmda9ag0MidTR/VoAsMtf5MzbDifSa1aBHRxZJToshNJVY9V8/lJLdwsbqsG2H+8v8ZuzyRLNiaFhNQTZQWpRXMipvbTDnnVxwpeFiLAqAwEKO9KIyGijqv2yeVvi4WtYvwzM7/1y/ycu7kTDFemKKuKmW2rzzBKJ30vo79ufMQCmn0riKkpaNxBf8R3EUEr86A9yuFpo6/Qc47i3PkeD7MszDqhEAfxl1+sQssWXOdVy6ALFb7RZ6EczpPvAjYLLO0aPa8OPaZjy3aJr+8=
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Expand Up @@ -58,6 +58,8 @@ Structure of the testing directory
│ └*.py - Python files with the BDD handlers
└─*.py - Other python based tests unrelated to BDD

For BDD tests we use [pytest-bdd](https://pypi.python.org/pypi/pytest-bdd). Beware that some BDD steps are defined in the `testing/bdd/conftest.py` file because they are used by multiple feature files.


## Configuration files

Expand Down
16 changes: 16 additions & 0 deletions Makefile
Expand Up @@ -3,6 +3,22 @@
init:
pip install --upgrade -r requirements.txt
pyxbgen --binding-root=./ebu_tt_live/bindings -m __init__ --schema-root=./ebu_tt_live/xsd1.1/ -r -u ebutt_live.xsd
ifeq ("$(wildcard node_modules)","")
npm install nunjucks
else
npm update nunjucks
endif
node_modules/nunjucks/bin/precompile ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.xml > ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.js

initnpm:
ifeq ("$(wildcard node_modules)","")
npm install nunjucks
else
npm update nunjucks
endif

template:
node_modules/nunjucks/bin/precompile ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.xml > ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.js

test:
python setup.py test
Expand Down
17 changes: 14 additions & 3 deletions README.md
Expand Up @@ -32,7 +32,9 @@ and assumes the environment variables that the activation script sets):

source ./env/bin/activate

After having created the python virtual environment and having activated it the package
To build the project you will also need node.js. Please read the instructions for your system [here](https://nodejs.org/en/download/package-manager/).

After having created the python virtual environment, having activated it and having installed node.js the package
can be built by typing make if you have GNU build tooling on your system.

make
Expand All @@ -45,6 +47,9 @@ Alternatively:

pyxbgen -r --binding-root=./ebu_tt_live/bindings -m __init__ --schema-root=./ebu_tt_live/xsd1.1/ -u ebutt_live.xsd

npm install nunjucks
node_modules/nunjucks/bin/precompile ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.xml > ebu_tt_live/ui/user_input_producer/template/user_input_producer_template.js

After this you are supposed to be able to launch the command line tools this python package
provides i.e.:

Expand All @@ -54,10 +59,10 @@ Windows users
=============

Windows is not the best friend of Makefiles. So there is a make.bat file for those who would like to develop using
Windows. Assuming python 2.7 and virtualenv is installed and are on the PATH.
Windows. Assuming python 2.7 and virtualenv is installed and are on the PATH. To build the project you will also need node.js. Please read the instructions for your system [here](https://nodejs.org/en/download/package-manager/). Then run :

make

This will make sure a virtual environment is created and activated and installs all the tools into it.

After that the following command should work:
Expand Down Expand Up @@ -94,6 +99,12 @@ The simple consumer connects to the producer or later on in the pipeline, assumi

ebu-simple-consumer

The user input consumer script is intended to receive data from the user input producer. The user input producer is a user interface that allows users to create documents
and to send them live (see the documentation for details). To run it, just run `ebu-user-input-consumer` and open the file `ebu_tt_live/ui/user_input_producer/user_input_producer.html` file.

ebu-user-input-consumer


Documentation
=============

Expand Down
9 changes: 9 additions & 0 deletions docs/source/ebu_tt_live.scripts.rst
Expand Up @@ -41,3 +41,12 @@ scripts Package
:undoc-members:
:show-inheritance:


:mod:`ebu_user_input_consumer` Module
---------------------------------

.. automodule:: ebu_tt_live.scripts.ebu_user_input_consumer
:members:
:undoc-members:
:show-inheritance:

1 change: 1 addition & 0 deletions docs/source/overview.rst
Expand Up @@ -4,3 +4,4 @@ Overview of the EBU-TT live toolkit.
.. toctree::
nodes_and_carriage_mechanisms
validation
user_input_producer
21 changes: 21 additions & 0 deletions docs/source/user_input_producer.rst
@@ -0,0 +1,21 @@
User input producer
===================

The user input producer is composed of a user interface written in javascript, the user interface is defined in the file `ebu_tt_live/ui/user_input_producer/user_input_producer.html`. It works with Javascript, JQuery_ and nunjucks_.

Demo
----

To test the user input producer, setup the environment as indicated in the `README.md` file at the root of the project. Then launch the ``ebu-user-input-consumer`` script and open the `ui/user_input_producer/user_input_producer.html` file in your browser. Click on the ``Connect`` button on the HTML page; the default URL should work: if you changed it in the `ebu_tt_live/script/ebu-user-input-consumer.py` file, then enter your custom URL, just be careful that the carriage uses websocket. If you have not already created a sequence, then create one with the corresponding button, set its options and select it in the dropdown box that allows you to choose a sequence identifier.

There are three ways of sending documents :
* `Send document on click on "Send" button` will issue a new document each time you clik the "Send" button.
* `Send document on scheduled time` replaces the "Send" button by an input box and a "Schedule" button. You have two options, using a "local" clock, which is the time of your computer or using a "media" clock, which is a clock starting at `00:00:00.0` when you click on "Synchronize" button. Times have to be entered using `hh:mm:ss` format in the "Scheduled time" input. When you click on "Schedule" the current document state is set to be sent at the given time. You can now change any field to schedule a new document without waiting.
* `Send documents asynchronously` will send a new document every `x` seconds, taking your modifications on-the-go.

You can type subtitle's text in the `Subtitles text` box. Each time a new document is being sent it should be logged by the ``ebu-user-input-consumer`` script.

.. _JQuery: https://jquery.com/
.. _nunjucks: https://mozilla.github.io/nunjucks/


4 changes: 3 additions & 1 deletion ebu_tt_live/carriage/filesystem.py
Expand Up @@ -63,7 +63,6 @@ class FilesystemProducerImpl(ProducerCarriageImpl):

_manifest_path = None
_dirpath = None
_manifest_file = None
_manifest_content = None
_manifest_time_format = None

Expand Down Expand Up @@ -93,6 +92,9 @@ def resume_producing(self):
break

def emit_document(self, document):
if self._manifest_path is None:
manifest_filename = "manifest_" + document.sequence_identifier + ".txt"
self._manifest_path = os.path.join(self._dirpath, manifest_filename)
# Handle there the switch and checks to handle the string format to use
# for times in the manifest file depending on your time base.
filename = '{}_{}.xml'.format(document.sequence_identifier, document.sequence_number)
Expand Down
22 changes: 22 additions & 0 deletions ebu_tt_live/carriage/forwarder_carriage.py
@@ -0,0 +1,22 @@
from .base import CombinedCarriageImpl


class ForwarderCarriageImpl(CombinedCarriageImpl):

_consumer_carriage = None
_producer_carriage = None

def __init__(self, consumer_carriage, producer_carriage):
self._consumer_carriage = consumer_carriage
self._producer_carriage = producer_carriage

def register(self, node):
self._node = node
self._consumer_carriage.register(node)
self._producer_carriage.register(node)

def emit_document(self, document):
self._producer_carriage.emit_document(document)

def on_new_data(self, data):
self._consumer_carriage.on_new_data(data)
29 changes: 29 additions & 0 deletions ebu_tt_live/carriage/test/test_forwarder_carriage.py
@@ -0,0 +1,29 @@
from unittest import TestCase
from mock import MagicMock
from ebu_tt_live.carriage.forwarder_carriage import ForwarderCarriageImpl


class TestForwarderCarriageImpl(TestCase):

def setUp(self):
self.consumer_impl = MagicMock()
self.producer_impl = MagicMock()
self.node = MagicMock()

def test_register(self):
forwarder_impl = ForwarderCarriageImpl(self.consumer_impl, self.producer_impl)
forwarder_impl.register(self.node)
self.consumer_impl.register.assert_called_with(self.node)
self.producer_impl.register.assert_called_with(self.node)

def test_emit_document(self):
forwarder_impl = ForwarderCarriageImpl(self.consumer_impl, self.producer_impl)
document = MagicMock()
forwarder_impl.emit_document(document)
self.producer_impl.emit_document.assert_called_with(document)

def test_on_new_data(self):
forwarder_impl = ForwarderCarriageImpl(self.consumer_impl, self.producer_impl)
data = MagicMock()
forwarder_impl.on_new_data(data)
self.consumer_impl.on_new_data.assert_called_with(data)
1 change: 1 addition & 0 deletions ebu_tt_live/node/consumer.py
Expand Up @@ -36,6 +36,7 @@ def process_document(self, document):
computed_end_time=document.computed_end_time
))
self._sequence.add_document(document)
log.info(document.get_xml())

@property
def reference_clock(self):
Expand Down
28 changes: 28 additions & 0 deletions ebu_tt_live/node/distributing.py
@@ -0,0 +1,28 @@
from .base import Node
import logging


log = logging.getLogger(__name__)


class DistributingNode(Node):

_reference_clock = None

def __init__(self, node_id, carriage_impl, reference_clock):
super(DistributingNode, self).__init__(node_id, carriage_impl)
self._reference_clock = reference_clock

def process_document(self, document):
log.info(document)
log.info(" " + str(document.sequence_identifier) + "_" + str(document.sequence_number))
log.info(document.get_xml())
self._carriage_impl.emit_document(document)

@property
def reference_clock(self):
return self._reference_clock

@reference_clock.setter
def reference_clock(self, value):
self._reference_clock = value
14 changes: 14 additions & 0 deletions ebu_tt_live/node/test/test_distributing.py
@@ -0,0 +1,14 @@
from unittest import TestCase
from mock import MagicMock
from ebu_tt_live.node.distributing import DistributingNode


class TestDistributingNode(TestCase):

def test_process_document(self):
carriage = MagicMock()
reference_clock = MagicMock()
node = DistributingNode('distributing_node', carriage, reference_clock)
document = MagicMock()
node.process_document(document)
carriage.emit_document.assert_called_with(document)
48 changes: 48 additions & 0 deletions ebu_tt_live/scripts/ebu_user_input_consumer.py
@@ -0,0 +1,48 @@
import logging
from argparse import ArgumentParser
from .common import create_loggers

from ebu_tt_live.node import SimpleConsumer
from ebu_tt_live.clocks.local import LocalMachineClock
from ebu_tt_live.twisted import TwistedConsumer, UserInputServerProtocol, UserInputServerFactory
from ebu_tt_live.carriage.twisted import TwistedConsumerImpl
from twisted.internet import reactor


log = logging.getLogger('ebu_simple_consumer')


parser = ArgumentParser()

parser.add_argument('-c', '--config', dest='config', metavar='CONFIG')


def main():
args = parser.parse_args()
create_loggers()
log.info('This is a Simple Consumer example')

consumer_impl = None

consumer_impl = TwistedConsumerImpl()

reference_clock = LocalMachineClock()
reference_clock.clock_mode = 'local'

simple_consumer = SimpleConsumer(
node_id='simple-consumer',
carriage_impl=consumer_impl,
reference_clock=reference_clock
)

factory = UserInputServerFactory(
url='ws://127.0.0.1:9001',
consumer=TwistedConsumer(
custom_consumer=consumer_impl
)
)
factory.protocol = UserInputServerProtocol

factory.listen()

reactor.run()

0 comments on commit 0c12d46

Please sign in to comment.