Python in actionscript
Hi there,
Total forum newbie here -- apologies if this post is
mischaracterized.
We're working on way to call a Python script via Flash Lite
or embed it inside a Flash application. Is there an easy way to
just call it from within actionscript?
Thanks.
you can use loadVariables() or loadVariablesNum() from flash
lite to call server-side script
Similar Messages
-
Using Ruby in place of Actionscript
I love flash (design tools, stage / layout concepts, etc.),
but I hate actionscript. I've been a programmer for about 10 years
now, programming in everything from C to C#, java, php, perl, ruby,
and actionscript. Actionscript is by far my least favorite of the
group. It is a clumsy language (just have a look at the way
actionscript 2 handled method closures on callbacks) and I'd prefer
to use another scripting language in place of it for my flash
development. Ruby would be an excellent replacement, offering
everything actionscript has to offer (object oriented, event
handling, etc.) with a number of additional features that come
through ruby core and the ruby gems (excellent date and time
libraries, database libraries, file handling libraries, etc.).
Does anyone with an in-depth knowledge of actionscript and
flash know what it would take to achieve some sort of common
language API that would allow such a substitution? If the ruby on
rails guys came across a solution allowing them to leverage the
benefits of ruby (superior language to actionscript) with the
benefits of the flash platform (superior visual control to
html/ajax), flash would be unstoppable.ryanmohr,
> The actionscript developers seem to enjoy leaving the
> core libs unfinished so others can produce utility
classes
> to finish the job they should have done on their own.
Again, fair enough. :) On the other hand, regarding the
missing String
manipulation utilities ...
> but why not just offer it built in? It would take what,
a
> full five minutes for them to write?
... hey, if all it takes is five minutes of someone's time,
why not craft
together a utils library and share it? You could make a
positive
difference. :) In that line of thinking, it's not even the
size that
matters. Moses Gunesh, for example, put together an elaborate
and popular
tweening engine, Fuse (
http://www.mosessupposes.com/Fuse/),
and shared the
wealth. Note: by proximity to a casual statement on a String
utils class,
I risk implying that Fuse is just a five-minute exercise in
simplicity,
which is not *at all* the case. I'm only pointing out that
good libraries
can make a helpful difference in people's workaday lives. If
the
functionality you want isn't available, roll your own! :)
> You are correct that there is no arguing taste, but if
you
> took the time to learn ruby well you would come back
> to actionscript very disappointed.
Even if I do "appear to be very knowledgable ... [on] the
inner-working
of Flash itself," I don't claim to know much on the
inner-working of Adobe.
I guess it depends on one's point of view -- and to my point
of view,
ActionScript keeps getting better and better.
I think there's more than just taste to consider. For the
type of
programming I like to do -- where the end result is (ideally,
to me) making
cartoon characters move in response to user input, Ruby might
leave me dry
(Flash is strongly suited to vector graphics, sound effects,
video footage,
etc.). My multimedia career started with Macromedia Director,
whose
programming language is Lingo, a very AppleScript-like
language. My guess
is that you wouldn't much care for it at all. From there, I
moved,
reluctantly at first, to Flash, where my programming skill
grew in-step with
the increasing maturity of ActionScript. There was a time,
essentially AS1,
when ActionScript was practically identical to JavaScript,
and I enjoyed
getting to know both. JavaScript led me to regular
expressions, which
fascinated me for fully two years before I got any good at
it. I'm pleased
as punch that AS3 supports regex natively. AS2 brought the
"class"
keyword -- and OOP in general -- to the forefront of my mind,
which led to
brief excursions into Java and C#. I've played a bit with
Python, PHP, and
a handful of other languages. To a certain extent,
programming is
programming: it's the syntax that changes, not the challenge
and fun of
problem solving within a given set of constraints (like the
language
itself). In that regard, it doesn't really matter to me what
language I'm
using, so much as a general answer to the question, "Does
this platform
allow me -- encourage me -- to participate in the kinds of
projects I like?"
Even if I found another language, such as Ruby, more
convenient, it might
not facilitate the sorts of projects I enjoy. To go out on a
limb and make
an extreme example, Ruby, for all its elegance, wouldn't help
me if I had a
passion for programming LCD wristwatches. Because I "grew up"
on
ActionScript, I also have something of a nostalgia for its
particular
quirks. I personally happen to find ActionScript more
palatable than
Lingo -- so I can see some of your points.
> The more I get to know actionscript 3 in detail the more
> I'm convinced those that adamantly support it just don't
> know any better.
I don't know if you consider me one of those who adamantly
supports AS3
or not, and it doesn't really matter. You yourself said that
ActionScript
isn't a bad language -- only that Ruby, in your estimation,
is that much
better. Well, good! I'm glad you've found a language that
pleases your
palate. :) If you were to change your mind and decide, after
all, that
ActionScript actually is a "bad language," it wouldn't be any
skin off my
nose. See, if I step away from ActionScript toward something
else, it means
I'm stepping away from a platform that has continued to
intrigue me for
eight years. If ActionScript were still where it was in the
Flash 4 days,
I'd probably be whistling a different tune. ;)
David Stiller
Adobe Community Expert
Dev blog,
http://www.quip.net/blog/
"Luck is the residue of good design." -
How can I convert an ActionScript 2 website to ActionScript3?
I have a website which currently uses Action Script 2.
When I change the Publish settings from Flash 7 to Flash 9
and from ActionScript 2 to ActionScript 3, then publish the file, I
get the following warning:
WARNING: Actions on button or MovieClip instances are not
supported in ActionScript 3.0. All scripts on object instances will
be ignored.
What can I do to correct this error?
Is there a simple tutorial that explains how to make the
changes?
I subscribe to Lynda.com but I haven't seen useful there.
I should warn you that I am a beginner when it comes to
coding.
Thank youHi NickLW,
In AS3 there's (like the error mentions) no attaching script
to
instances directly. You probably have something like:
on(release){
gotoAndPlay( 5 );
well, atleast the "on( something )" part...
That's a nono in AS3.
You'd have to change it to code in a keyFrame in the timeline
like:
my_btn.addEventListener( MouseEvent.CLICK, onClick );
function onClick( e:MouseEvent )
gotoAndPlay( 5 )
where my_btn is the instancename of the button.
Look for migration from as2 to as3 in available resources
(like:
http://www.mandalatv.net/fcny/)
Sure there's no mention on the Lynda courses?
NickLW wrote:
> I have a website which currently uses Action Script 2.
> When I change the Publish settings from Flash 7 to Flash
9 and from
> ActionScript 2 to ActionScript 3, then publish the file,
I get the following
> warning:
>
> WARNING: Actions on button or MovieClip instances are
not supported in
> ActionScript 3.0. All scripts on object instances will
be ignored.
>
> What can I do to correct this error?
> Is there a simple tutorial that explains how to make the
changes?
> I subscribe to Lynda.com but I haven't seen useful
there.
> I should warn you that I am a beginner when it comes to
coding.
>
> Thank you
>
Manno Bult
http://www.aloft.nl -
Unable to capture stdout, stderr from python.
I am trying to read the stdout and stderr of a python program.
When I invoke anything else apart from python my class works fine.
The python program takes ca 1 sec to start. It then prints one line of text, then it prints a promt and waits for input from user.
I tryed with another program that behaves in the same way and there I got the first line. Not the prompt, that not a python but a native C program.
I have tried using BufferedReader but without sucess.
My class looks like this.
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Executer extends Thread {
//read standard out output of the external executable
//in seperate thread to avoid I/O deadlocks
final int BUFFER = 2048;
Process p;
BufferedInputStream in;
OutputStream out;
StringBuffer strbuf;
String[] cmdarr = null;
public Executer(String path) {
this.cmdarr = new String[] { path };
public Executer(String[] path) {
this.cmdarr = path;
public void run() {
try {
System.out.println("doing call");
p = Runtime.getRuntime().exec(cmdarr);
in = new BufferedInputStream(p.getInputStream());
strbuf = new StringBuffer();
out = p.getOutputStream();
int i;
byte[] buf = new byte[BUFFER];
String str;
while ((i = in.read(buf, 0, BUFFER)) != -1)
System.out.write(buf, 0, i);
} catch (IOException e) {
e.printStackTrace();
public int killProcess() throws InterruptedException {
p.destroy();
try {
in.close();
System.out.println("Closed");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return p.waitFor();
}Any ideas is appreciated.When Runtime Exec Won't - a good article on running processes from a Java program...
Hope that helps;
lutha -
Can't access object using "id" or "name" if created with actionscript
How can you register an instance of an object with actionscript so that it's id or name value is accessible?
I included a simple example where a Button is created using mxml and in the same way it is created using actionscript. The actionscript object is inaccessible using it's "id" and "name" property.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler(event:FlexEvent):void
import spark.components.Button;
var asBtn:Button = new Button();
asBtn.label = "actionscript";
asBtn.x = 200;
asBtn.id = "asButton";
asBtn.name = "asButtonName";
addElement(asBtn);
trace("mxmlButton="+this["mxmlButton"].label); // returns: mxml label
//trace("mxmlButton="+this["asButton"].label); // returns runtime error: ReferenceError: Error #1069: Property asButton not found on TestId and there is no default value.
//trace("mxmlButton="+this["asButtonName"].label); // returns runtime error: ReferenceError: Error #1069: Property asButtonName not found on TestId and there is no default value.
]]>
</fx:Script>
<s:Button
id="mxmlButton"
label="mxml label"
alpha="0.8"/>
</s:Application>Hi Dan,
It is a very rare occurrence when I miss not being able to access an object (object property, really) using the ["name"] notation for objects created using actionscript.
In MXML the compiler is conveniently adding an attribute to the class with the same name as the id, so you can conveniently refer to it using the [] notation. While we explicitly specify an application container to use, the MXML compiler creates a custom container which is a derivative of the base container and to that it adds properties for the children declared in MXML. I guess it also effectively calls "addElement" for us when the container is being constructed.
Your example assumes that using "addElement" to add the button to the application container is the same as declaring a variable (ie property ). It isn't, so there's no point in looking for an property of the name "as3Button" using the [] notation, because it doesn't exist. The container is managing a collection of children in it's display list and that's not the same as being accessible as properties of the container.
Generally speaking, accessing properties using the ["name"] syntax isn't necessary.
Paul
[edit: you may wonder why "addElement" doesn't conveniently also add the "id" attribute to be an property of the container class. Unfortunately, it can't because the container class would need to be dynamic and it's not. A further complication would be that adding properties at runtime would invite naming clashes at runtime with associated mayhem. MXML can do this because the compiler generates the class and can trap name duplication at compile time.
Great question, BTW.
-last edit changed my "attributes" to be "properties" in line with Adobe's terminology] -
Hi,
I'm new to both mac and LabView, so it may well be something obvious I'm missing.
I'm trying to use System Exec (http://zone.ni.com/reference/en-XX/help/371361L-01/glang/system_exec/ with LabVIEW 2014 on Mac OS X Mavericks) to call a python script to do some image processing after taking some data and saving images via LabView.
My problem is that I cannot figure out how to point it to the correct version/install of python to use, as it seems to use the pre-installed 2.7.5 apple version no matter whether that's set to be my default or not (and hence, it can't see my SciPy, PIL etc. packages that come with my Anaconda install).
It doesn't seem to matter whether I have certain packages installed for 2.7 accessable via the terminal, the LabView System Exec command line can't seem to find them either way and throws up an error if a script is called that imports them.
I've tried changing the working directory to the relevant anaconda/bin folder, I've also tried
cd /Applications/anaconda/bin; python <file.py>
as the CL input to system exec, but it's not wanting to use anything other than the apple install. I've tried Anaconda installs with both python 2.7 and 3.4, so it doesn't seem to be down to the 3.* compatibility issues alone.
Printing the python version to a string indicator box in LV via python script gives the following:
2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]
Whereas via the terminal, the default version is the anaconda install I'd like to use, currently
Python 3.4.1 |Anaconda 2.1.0 (x86_64)| (default, Sep 10 2014, 17:24:09)
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
I can do which python3.4 on the sys exec CL input to get the correct /anaconda/bin location, but if I try python3.4 <file.py>, I just get a Seg fault.
I've found examples for System Exec use and instructions for calling python scripts with specific versions, but neither works with Mac (frustratingly).
I've also tried editing the Path Environment Variable, and tried getting rid of the python 2.7 install entirely, but none of these work either (the latter just causing errors all over the shop).
So, in summary
I'd just like to know how to specify the python version LabView uses and to have use of the corresponding python libraries.
Either python version (2 or 3) will do, I'd just like to be able to use my libraries which came with Anaconda which I'll be writing my scripts with (which I installed as the correct packages are only compatible with a specific python version on Mac, which is not the specific version that Xcode was compatible with, argh).
All packages work normally when using the Anaconda version with the terminal or with Spyder.
Is there a function I can use other than System Exec? What am I missing?
Please help.janedoe777 wrote:
Accidental. Also, that's not terribly helpful.
What exactly does that mean?
I'm not debating whether it was accidental or intentional. It certainly isn't helpful to post the same message twice.
It is helpful to point out this message is a duplicate so people don't waste their time answering this one if you are already being helped in the other one. -
Hello,
I am attempting to use python (with ctypes) to control my USB-6009. The goal is to write out an analog voltage and then read in the voltage through an analog input with ability to change the number of points averaged and the number of times this is repeated(sweeps) averaging the analog input array. The issue is that as we increase the number of times the voltage ramp is repeated (sweeps) we get a time out error (nidaq call failed with error -200284: 'Some or all of the samples requested have not yet been acquired). This has us confused because the sweeps are in a larger loop and the Daq function should be the same if there are 10 sweeps (works) or 1000 sweeps (crashes). Any insight would be greatly appreciated. I have included the code below for reference.
import ctypes
import numpy
from time import *
from operator import add
nidaq = ctypes.windll.nicaiu # load the DLL
# Setup some typedefs and constants
# to correspond with values in
# C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h
# Scan Settings
aoDevice = "Dev2/ao0"
aiDevice = "Dev2/ai0"
NumAvgPts = 10
NumSweeps = 50
NumSpecPts = 100
filename = '12Feb15_CO2 Test_12.txt'
Readrate = 40000.0
Samplerate = 1000
StartVolt = 0.01
FinalVolt = 1.01
voltInc = (FinalVolt - StartVolt)/NumSpecPts
# the typedefs
int32 = ctypes.c_long
uInt32 = ctypes.c_ulong
uInt64 = ctypes.c_ulonglong
float64 = ctypes.c_double
TaskHandle = uInt32
# the constants
DAQmx_Val_Cfg_Default = int32(-1)
DAQmx_Val_Volts = 10348
DAQmx_Val_Rising = 10280
DAQmx_Val_FiniteSamps = 10178
DAQmx_Val_GroupByChannel = 0
def CHK_ao( err ):
"""a simple error checking routine"""
if err < 0:
buf_size = 100
buf = ctypes.create_string_buffer('\000' * buf_size)
nidaq.DAQmxGetErrorString(err,ctypes.byref(buf),buf_size)
raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(buf.value)))
if err > 0:
buf_size = 100
buf = ctypes.create_string_buffer('\000' * buf_size)
nidaq.DAQmxGetErrorString(err,ctypes.byref(buf),buf_size)
raise RuntimeError('nidaq generated warning %d: %s'%(err,repr(buf.value)))
def CHK_ai(err):
"""a simple error checking routine"""
if err < 0:
buf_size = NumAvgPts*10
buf = ctypes.create_string_buffer('\000' * buf_size)
nidaq.DAQmxGetErrorString(err,ctypes.byref(buf),buf_size)
raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(buf.value)))
def Analog_Output():
taskHandle = TaskHandle(0)
(nidaq.DAQmxCreateTask("",ctypes.byref(taskHandle )))
(nidaq.DAQmxCreateAOVoltageChan(taskHandle,
aoDevice,
float64(0),
float64(5),
DAQmx_Val_Volts,
None))
(nidaq.DAQmxCfgSampClkTiming(taskHandle,"",float64(Samplerate),
DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,
uInt64(NumAvgPts))); # means we could turn in this to continuously ramping and reading
(nidaq.DAQmxStartTask(taskHandle))
(nidaq.DAQmxWriteAnalogScalarF64(taskHandle, True, float64(10.0), float64(CurrentVolt), None))
nidaq.DAQmxStopTask( taskHandle )
nidaq.DAQmxClearTask( taskHandle )
def Analog_Input():
global average
# initialize variables
taskHandle = TaskHandle(0)
data = numpy.zeros((NumAvgPts,),dtype=numpy.float64)
# now, on with the program
CHK_ai(nidaq.DAQmxCreateTask("",ctypes.byref(taskHandle)))
CHK_ai(nidaq.DAQmxCreateAIVoltageChan(taskHandle,aiDevice,"",
DAQmx_Val_Cfg_Default,
float64(-10.0),float64(10.0),
DAQmx_Val_Volts,None))
CHK_ai(nidaq.DAQmxCfgSampClkTiming(taskHandle,"",float64(Readrate),
DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,
uInt64(NumAvgPts)));
CHK_ai(nidaq.DAQmxStartTask(taskHandle))
read = int32()
CHK_ai(nidaq.DAQmxReadAnalogF64(taskHandle,NumAvgPts,float64(10.0),
DAQmx_Val_GroupByChannel,data.ctypes.data,
NumAvgPts,ctypes.byref(read),None))
#print "Acquired %d points"%(read.value)
if taskHandle.value != 0:
nidaq.DAQmxStopTask(taskHandle)
nidaq.DAQmxClearTask(taskHandle)
average = sum(data)/data.size
Thanks,
Erin
Solved!
Go to Solution.This forum is for LabVIEW questions.
-
USB-6009, mac OS 10.6.8 and python
Hello!
I am using USB-6009 under mac OS 10.6.8 and python.
I am trying to run the following commmand:
analogOutputTask = nidaqmx.AnalogOutputTask(name='MyAOTask')
I get the following message
File "/Applications/PsychoPy2.app/Contents/Resources/lib/python2.7/nidaqmx/libnidaqmx.py", line 180, in CALL
AttributeError: 'NoneType' object has no attribute 'DAQmxCreateTask'
Any help would be very mch appreciated,
Thanks
j.Hello Jamyamdy,
Honestly, I am not too sure about this, but were you able to acquire data before or is this your first trial?
From the usb-6009 product page, it says the following.
For Mac OS X and Linux users, download the NI-DAQmx Base driver software and program the USB-6009 with NI LabVIEW or C.
http://sine.ni.com/nips/cds/view/p/lang/en/nid/201987
Regards, -
Is there a way of changing the alpha value of a symbol in its own timeline without ActionScript
I'm trying to make an animated banner ad where radio waves emanate from a device as they fade in and fade out.
I got it working, then realized I'd like the radio wave animation to loop repeatedly while the text in the ad comes in and out, so I thought maybe it should be a symbol and have the animation take place in its own timeline.
Problem is, when I make the symbol and double click to enter its timeline, the color effect menu disappears.
I don't feel comfortable in ActionScript yet. Is there no other way to do what I want?
Can I create the radio waves as a separate animation file, then import it into the main animation?You should be able to make seperate keyframes and then modify the alpha of any MovieClip or Graphic objects within that keyframe. After that right click somewhere between the keyframes on the timeline and select "Create Classic Tween".
NOTE: You have to have the keyframe selected on the timeline to be able to modify properties. So if you have a keyframe on frame 1, frame 10 and frame 20 set the alpha on frame 1 at 100%, frame 10 at 0% and frame 20 at 100% and it will fill in the blanks.
EDIT:
If the objects in your inner symbol are not a MovieClip or Graphic select all and then Right Click and select "Convert to Symbol" to make them one. -
Passing null/empty values from a actionscript VO to a Coldfusion ORM object
This is the situation.
If you have an actionscript VO that binds to a Coldfusion ORM object via the RemoteClass metadata and some of the values are not set, null, or empty strings and you pass it from Flex to Coldfusion then the Coldfusion deserialization barfs saying the values are not acceptable date values (for type="date") or valid emails (for validation="email") or other such validations, even if required="false" on the property.
For instance, if you have the following actionscript VO:
package vo
[RemoteClass(alias="com.companyname.Person")]
[Bindable]
public class Person
public var person_id:Number;
public var last_name:String;
public var first_name:String;
public var email:String;
public var created_date:date;
public function Person() {}
And you have the corresponding Coldfusion component:
<cfcomponent displayname="person" output="false"
alias="com.companyname.Person"
schema="dbo" persistent="true"
table="PERSON">
<cfproperty name="person_id" type="numeric" fieldtype="id" validate="integer" required="true" column="PERSON_ID"/>
<cfproperty name="last_name" type="string" column="LAST_NAME" required="true"/>
<cfproperty name="first_name" type="string" required="true" column="FIRST_NAME"/>
<cfproperty name="email" type="string" validate="email" required="false" column="EMAIL"/>
<cfproperty name="date_created" type="date" required="false" column="DATE_CREATED"/>
</cfcomponent>
Then if you pass the actionscript VO as is to Coldfusion, the deserialization complains that you do not have a valid email or a valid date for date_created. This is bad, bad, bad. Essentially if you have a validation of certain types (email being one) or a date property, or probably some other cases, then you essentially can not make it not required, it automatically makes it required because the Coldfusion serializer considers null/empty values as invalid dates or emails. But the serializer should not care for values that are not required, there has to be a way to pass null/empty values to these data types, but apparently there's not. If you pass an empty string ("") you still have the same problem. I know Coldfusion does not have null values, but there has to be a way to do this, otherwise it defeats the purpose of having required="false" and some kind of validation on the property.
There seems to be two ways around it. One is to override the implicit setters for the properties on the Coldfusion side and check for 0 length values yourself, then set the property if it is not, or create your own validation routine. I ended up creating my own validation function since I didn't want to have to write a setter function for everyone of these cases and I can pass back user friendly validation messages.
Have other people encountered this problem? How have you gotten around it? Thanks.I realize that I didn't clarify that I am using ColdFusion
for getting the data. This class was generated by the Create CFC
wizard in Flex Builder.
package com.generated
[Managed]
[RemoteClass(alias="components.generated.clients.Clients")]
public class Clients
public var clientid:Number = 0;
public var clientfirstname:String = "";
public var clientlastname:String = "";
public var clientaddress1:String = "";
public var clientaddress2:String = "";
public var clientcity:String = "";
public var clientstate:String = "";
public var clientzip:String = "";
public var clientphone:String = "";
public var clientemail:String = "";
public function Clients()
} -
Hi All,
I have updated my mediacenter. Now tv_grab_nl_py does not work anymore:
[cedric@tv ~]$ tv_grab_nl_py --output ~/listings.xml --fast
File "/usr/bin/tv_grab_nl_py", line 341
print 'tv_grab_nl_py: A grabber that grabs tvguide data from tvgids.nl\n'
^
SyntaxError: invalid syntax
[cedric@tv ~]$
the version of python on the mediacenter (running arch linux):
[cedric@tv ~]$ python
Python 3.1.2 (r312:79147, Oct 4 2010, 12:35:40)
[GCC 4.5.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
I have copied the file to my laptop, there it looks like it's working:
./tv_grab_nl_py --output ~/listings.xml --fast
Config file /home/cedric/.xmltv/tv_grab_nl_py.conf not found.
Re-run me with the --configure flag.
cedric@laptop:~$
the version of python on my laptop (running arch linux):
cedric@laptop:~$ python
Python 2.6.5 (r265:79063, Apr 1 2010, 05:22:20)
[GCC 4.4.3 20100316 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
the script I'm trying to run:
[cedric@tv ~]$ cat tv_grab_nl_py
#!/usr/bin/env python
# $LastChangedDate: 2009-11-14 10:06:41 +0100 (Sat, 14 Nov 2009) $
# $Rev: 104 $
# $Author: pauldebruin $
SYNOPSIS
tv_grab_nl_py is a python script that trawls tvgids.nl for TV
programming information and outputs it in XMLTV-formatted output (see
http://membled.com/work/apps/xmltv). Users of MythTV
(http://www.mythtv.org) will appreciate the output generated by this
grabber, because it fills the category fields, i.e. colors in the EPG,
and has logos for most channels automagically available. Check the
website below for screenshots. The newest version of this script can be
found here:
http://code.google.com/p/tvgrabnlpy/
USAGE
Check the web site above and/or run script with --help and start from there
HISTORY
tv_grab_nl_py used to be called tv_grab_nl_pdb, first released on
2003/07/09. The name change was necessary because more and more people
are actively contributing to this script and I always disliked using my
initials (I was just too lazy to change it). At the same time I switched
from using CVS to SVN and as a result the version numbering scheme has
changed. The lastest official release of tv_grab_nl_pdb is 0.48. The
first official release of tv_grab_nl_py is 6.
QUESTIONS
Questions (and patches) are welcome at: paul at pwdebruin dot net.
IMPORTANT NOTES
If you were using tv_grab_nl from the XMLTV bundle then enable the
compat flag or use the --compat command-line option. Otherwise, the
xmltvid's are wrong and you will not see any new data in MythTV.
CONTRIBUTORS
Main author: Paul de Bruin (paul at pwdebruin dot net)
Michel van der Laan made available his extensive collection of
high-quality logos that is used by this script.
Michael Heus has taken the effort to further enhance this script so that
it now also includes:
- Credit info: directors, actors, presenters and writers
- removal of programs that are actually just groupings/broadcasters
(e.g. "KETNET", "Wild Friday", "Z@pp")
- Star-rating for programs tipped by tvgids.nl
- Black&White, Stereo and URL info
- Better detection of Movies
- and much, much more...
Several other people have provided feedback and patches (these are the
people I could find in my email archive, if you are missing from this
list let me know):
Huub Bouma, Roy van der Kuil, Remco Rotteveel, Mark Wormgoor, Dennis van
Onselen, Hugo van der Kooij, Han Holl, Ian Mcdonald, Udo van den Heuvel.
# Modules we need
import re, urllib2, getopt, sys
import time, random
import htmlentitydefs, os, os.path, pickle
from string import replace, split, strip
from threading import Thread
from xml.sax import saxutils
# Extra check for the datetime module
try:
import datetime
except:
sys.stderr.write('This script needs the datetime module that was introduced in Python version 2.3.\n')
sys.stderr.write('You are running:\n')
sys.stderr.write('%s\n' % sys.version)
sys.exit(1)
# XXX: fix to prevent crashes in Snow Leopard [Robert Klep]
if sys.platform == 'darwin' and sys.version_info[:3] == (2, 6, 1):
try:
urllib2.urlopen('http://localhost.localdomain')
except:
pass
# do extra debug stuff
debug = 1
try:
import redirect
except:
debug = 0
pass
# globals
# compile only one time
r_entity = re.compile(r'&(#x[0-9A-Fa-f]+|#[0-9]+|[A-Za-z]+);')
tvgids = 'http://www.tvgids.nl/'
uitgebreid_zoeken = tvgids + 'zoeken/'
# how many seconds to wait before we timeout on a
# url fetch, 10 seconds seems reasonable
global_timeout = 10
# Wait a random number of seconds between each page fetch.
# We want to be nice and not hammer tvgids.nl (these are the
# friendly people that provide our data...).
# Also, it appears tvgids.nl throttles its output.
# So there, there is not point in lowering these numbers, if you
# are in a hurry, use the (default) fast mode.
nice_time = [1, 2]
# Maximum length in minutes of gaps/overlaps between programs to correct
max_overlap = 10
# Strategy to use for correcting overlapping prgramming:
# 'average' = use average of stop and start of next program
# 'stop' = keep stop time of current program and adjust start time of next program accordingly
# 'start' = keep start time of next program and adjust stop of current program accordingly
# 'none' = do not use any strategy and see what happens
overlap_strategy = 'average'
# Experimental strategy for clumping overlapping programming, all programs that overlap more
# than max_overlap minutes, but less than the length of the shortest program are clumped
# together. Highly experimental and disabled for now.
do_clump = False
# Create a category translation dictionary
# Look in mythtv/themes/blue/ui.xml for all category names
# The keys are the categories used by tvgids.nl (lowercase please)
cattrans = { 'amusement' : 'Talk',
'animatie' : 'Animated',
'comedy' : 'Comedy',
'documentaire' : 'Documentary',
'educatief' : 'Educational',
'erotiek' : 'Adult',
'film' : 'Film',
'muziek' : 'Art/Music',
'informatief' : 'Educational',
'jeugd' : 'Children',
'kunst/cultuur' : 'Arts/Culture',
'misdaad' : 'Crime/Mystery',
'muziek' : 'Music',
'natuur' : 'Science/Nature',
'nieuws/actualiteiten' : 'News',
'overige' : 'Unknown',
'religieus' : 'Religion',
'serie/soap' : 'Drama',
'sport' : 'Sports',
'theater' : 'Arts/Culture',
'wetenschap' : 'Science/Nature'}
# Create a role translation dictionary for the xmltv credits part
# The keys are the roles used by tvgids.nl (lowercase please)
roletrans = {'regie' : 'director',
'acteurs' : 'actor',
'presentatie' : 'presenter',
'scenario' : 'writer'}
# We have two sources of logos, the first provides the nice ones, but is not
# complete. We use the tvgids logos to fill the missing bits.
logo_provider = [ 'http://visualisation.tudelft.nl/~paul/logos/gif/64x64/',
'http://static.tvgids.nl/gfx/zenders/' ]
logo_names = {
1 : [0, 'ned1'],
2 : [0, 'ned2'],
3 : [0, 'ned3'],
4 : [0, 'rtl4'],
5 : [0, 'een'],
6 : [0, 'canvas_color'],
7 : [0, 'bbc1'],
8 : [0, 'bbc2'],
9 : [0,'ard'],
10 : [0,'zdf'],
11 : [1, 'rtl'],
12 : [0, 'wdr'],
13 : [1, 'ndr'],
14 : [1, 'srsudwest'],
15 : [1, 'rtbf1'],
16 : [1, 'rtbf2'],
17 : [0, 'tv5'],
18 : [0, 'ngc'],
19 : [1, 'eurosport'],
20 : [1, 'tcm'],
21 : [1, 'cartoonnetwork'],
24 : [0, 'canal+red'],
25 : [0, 'mtv-color'],
26 : [0, 'cnn'],
27 : [0, 'rai'],
28 : [1, 'sat1'],
29 : [0, 'discover-spacey'],
31 : [0, 'rtl5'],
32 : [1, 'trt'],
34 : [0, 'veronica'],
35 : [0, 'tmf'],
36 : [0, 'sbs6'],
37 : [0, 'net5'],
38 : [1, 'arte'],
39 : [0, 'canal+blue'],
40 : [0, 'at5'],
46 : [0, 'rtl7'],
49 : [1, 'vtm'],
50 : [1, '3sat'],
58 : [1, 'pro7'],
59 : [1, 'kanaal2'],
60 : [1, 'vt4'],
65 : [0, 'animal-planet'],
73 : [1, 'mezzo'],
86 : [0, 'bbc-world'],
87 : [1, 'tve'],
89 : [1, 'nick'],
90 : [1, 'bvn'],
91 : [0, 'comedy_central'],
92 : [0, 'rtl8'],
99 : [1, 'sport1_1'],
100 : [0, 'rtvu'],
101 : [0, 'tvwest'],
102 : [0, 'tvrijnmond'],
103 : [1, 'tvnoordholland'],
104 : [1, 'bbcprime'],
105 : [1, 'spiceplatinum'],
107 : [0, 'canal+yellow'],
108 : [0, 'tvnoord'],
109 : [0, 'omropfryslan'],
114 : [0, 'omroepbrabant']}
# A selection of user agents we will impersonate, in an attempt to be less
# conspicuous to the tvgids.nl police.
user_agents = [ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)',
'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.9) Gecko/20071105 Firefox/2.0.0.9',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9',
'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.8) Gecko/20071022 Ubuntu/7.10 (gutsy) Firefox/2.0.0.8'
# Work in progress, the idea is to cache program categories and
# descriptions to eliminate a lot of page fetches from tvgids.nl
# for programs that do not have interesting/changing descriptions
class ProgramCache:
A cache to hold program name and category info.
TVgids stores the detail for each program on a separate URL with an
(apparently unique) ID. This cache stores the fetched info with the ID.
New fetches will use the cached info instead of doing an (expensive)
page fetch.
def __init__(self, filename=None):
Create a new ProgramCache object, optionally from file
# where we store our info
self.filename = filename
if filename == None:
self.pdict = {}
else:
if os.path.isfile(filename):
self.load(filename)
else:
self.pdict = {}
def load(self, filename):
Loads a pickled cache dict from file
try:
self.pdict = pickle.load(open(filename,'r'))
except:
sys.stderr.write('Error loading cache file: %s (possibly corrupt)' % filename)
sys.exit(2)
def dump(self, filename):
Dumps a pickled cache, and makes sure it is valid
if os.access(filename, os.F_OK):
try:
os.remove(filename)
except:
sys.stderr.write('Cannot remove %s, check permissions' % filename)
pickle.dump(self.pdict, open(filename+'.tmp', 'w'))
os.rename(filename+'.tmp', filename)
def query(self, program_id):
Updates/gets/whatever.
try:
return self.pdict[program_id]
except:
return None
def add(self, program):
Adds a program
self.pdict[program['ID']] = program
def clear(self):
Clears the cache (i.e. empties it)
self.pdict = {}
def clean(self):
Removes all cached programming before today.
Also removes erroneously cached programming.
now = time.localtime()
dnow = datetime.datetime(now[0],now[1],now[2])
for key in self.pdict.keys():
try:
if self.pdict[key]['stop-time'] < dnow or self.pdict[key]['name'].lower() == 'onbekend':
del self.pdict[key]
except:
pass
def usage():
print 'tv_grab_nl_py: A grabber that grabs tvguide data from tvgids.nl\n'
print 'and stores it in XMLTV-combatible format.\n'
print 'Usage:'
print '--help, -h = print this info'
print '--configure = create configfile (overwrites existing file)'
print '--config-file = name of the configuration file (default = ~/.xmltv/tv_grab_py.conf'
print '--capabilities = xmltv required option'
print '--desc-length = maximum allowed length of programme descriptions in bytes.'
print '--description = prints a short description of the grabber'
print '--output = file where to put the output'
print '--days = # number of days to grab'
print '--preferredmethod = returns the preferred method to be called'
print '--fast = do not grab descriptions of programming'
print '--slow = grab descriptions of programming'
print '--quiet = suppress all output'
print '--compat = append tvgids.nl to the xmltv id (use this if you were using tv_grab_nl)'
print '--logos 0/1 = insert urls to channel icons (mythfilldatabase will then use these)'
print '--nocattrans = do not translate the grabbed genres into MythTV-genres'
print '--cache = cache descriptions and use the file to store'
print '--clean_cache = clean the cache file before fetching'
print '--clear_cache = empties the cache file before fetching data'
print '--slowdays = grab slowdays initial days and the rest in fast mode'
print '--max_overlap = maximum length of overlap between programming to correct [minutes]'
print '--overlap_strategy = what strategy to use to correct overlaps (check top of source code)'
def filter_line_identity(m, defs=htmlentitydefs.entitydefs):
# callback: translate one entity to its ISO Latin value
k = m.group(1)
if k.startswith("#") and k[1:] in xrange(256):
return chr(int(k[1:]))
try:
return defs[k]
except KeyError:
return m.group(0) # use as is
def filter_line(s):
Removes unwanted stuff in strings (adapted from tv_grab_be)
# do the latin1 stuff
s = r_entity.sub(filter_line_identity, s)
s = replace(s,' ',' ')
# Ik vermoed dat de volgende drie regels overbodig zijn, maar ze doen
# niet veel kwaad -- Han Holl
s = replace(s,'\r',' ')
x = re.compile('(<.*?>)') # Udo
s = x.sub('', s) #Udo
s = replace(s, '~Q', "'")
s = replace(s, '~R', "'")
# Hmm, not sure if I understand this. Without it, mythfilldatabase barfs
# on program names like "Steinbrecher &..."
# We most create valid XML -- Han Holl
s = saxutils.escape(s)
return s
def calc_timezone(t):
Takes a time from tvgids.nl and formats it with all the required
timezone conversions.
in: '20050429075000'
out:'20050429075000 (CET|CEST)'
Until I have figured out how to correctly do timezoning in python this method
will bork if you are not in a zone that has the same DST rules as 'Europe/Amsterdam'.
year = int(t[0:4])
month = int(t[4:6])
day = int(t[6:8])
hour = int(t[8:10])
minute = int(t[10:12])
#td = {'CET': '+0100', 'CEST': '+0200'}
#td = {'CET': '+0100', 'CEST': '+0200', 'W. Europe Standard Time' : '+0100', 'West-Europa (standaardtijd)' : '+0100'}
td = {0 : '+0100', 1 : '+0200'}
pt = time.mktime((year,month,day,hour,minute,0,0,0,-1))
timezone=''
try:
#timezone = time.tzname[(time.localtime(pt))[-1]]
timezone = (time.localtime(pt))[-1]
except:
sys.stderr.write('Cannot convert time to timezone')
return t+' %s' % td[timezone]
def format_timezone(td):
Given a datetime object, returns a string in XMLTV format
tstr = td.strftime('%Y%m%d%H%M00')
return calc_timezone(tstr)
def get_page_internal(url, quiet=0):
Retrieves the url and returns a string with the contents.
Optionally, returns None if processing takes longer than
the specified number of timeout seconds.
txtdata = None
txtheaders = {'Keep-Alive' : '300',
'User-Agent' : user_agents[random.randint(0, len(user_agents)-1)] }
try:
#fp = urllib2.urlopen(url)
rurl = urllib2.Request(url, txtdata, txtheaders)
fp = urllib2.urlopen(rurl)
lines = fp.readlines()
page = "".join(lines)
return page
except:
if not quiet:
sys.stderr.write('Cannot open url: %s\n' % url)
return None
class FetchURL(Thread):
A simple thread to fetch a url with a timeout
def __init__ (self, url, quiet=0):
Thread.__init__(self)
self.quiet = quiet
self.url = url
self.result = None
def run(self):
self.result = get_page_internal(self.url, self.quiet)
def get_page(url, quiet=0):
Wrapper around get_page_internal to catch the
timeout exception
try:
fu = FetchURL(url, quiet)
fu.start()
fu.join(global_timeout)
return fu.result
except:
if not quiet:
sys.stderr.write('get_page timed out on (>%s s): %s\n' % (global_timeout, url))
return None
def get_channels(file, quiet=0):
Get a list of all available channels and store these
in a file.
# store channels in a dict
channels = {}
# tvgids stores several instances of channels, we want to
# find all the possibile channels
channel_get = re.compile('<optgroup label=.*?>(.*?)</optgroup>', re.DOTALL)
# this is how we will find a (number, channel) instance
channel_re = re.compile('<option value="([0-9]+)" >(.*?)</option>', re.DOTALL)
# this is where we will try to find our channel list
total = get_page(uitgebreid_zoeken, quiet)
if total == None:
return
# get a list of match objects of all the <select blah station>
stations = channel_get.finditer(total)
# and create a dict of number, channel_name pairs
# we do this this way because several instances of the
# channel list are stored in the url and not all of the
# instances have all the channels, this way we get them all.
for station in stations:
m = channel_re.finditer(station.group(0))
for p in m:
try:
a = int(p.group(1))
b = filter_line(p.group(2))
channels[a] = b
except:
sys.stderr.write('Oops, [%s,%s] does not look like a valid channel, skipping it...\n' % (p.group(1),p.group(2)))
# sort on channel number (arbitrary but who cares)
keys = channels.keys()
keys.sort()
# and create a file with the channels
f = open(file,'w')
for k in keys:
f.write("%s %s\n" % (k, channels[k]))
f.close()
def get_channel_all_days(channel, days, quiet=0):
Get all available days of programming for channel number
The output is a list of programming in order where each row
contains a dictionary with program information.
now = datetime.datetime.now()
programs = []
# Tvgids shows programs per channel per day, so we loop over the number of days
# we are required to grab
for offset in range(0, days):
channel_url = 'http://www.tvgids.nl/zoeken/?d=%i&z=%s' % (offset, channel)
# For historic purposes, the old style url that gave us a full week in advance:
# channel_url = 'http://www.tvgids.nl/zoeken/?trefwoord=Titel+of+trefwoord&interval=0×lot='+\
# '&station=%s&periode=%i&genre=&order=0' % (channel,days-1)
# Sniff, we miss you...
if offset > 0:
time.sleep(random.randint(nice_time[0], nice_time[1]))
# get the raw programming for the day
total = get_page(channel_url, quiet)
if total == None:
return programs
# Setup a number of regexps
# checktitle will match the title row in H2 tags of the daily overview page, e.g.
# <h2>zondag 19 oktober 2008</h2>
checktitle = re.compile('<h2>(.*?)</h2>',re.DOTALL)
# getrow will locate each row with program details
getrow = re.compile('<a href="/programma/(.*?)</a>',re.DOTALL)
# parserow matches the required program info, with groups:
# 1 = program ID
# 2 = broadcast times
# 3 = program name
parserow = re.compile('(.*?)/.*<span class="time">(.*?)</span>.*<span class="title">(.*?)</span>', re.DOTALL)
# normal begin and end times
times = re.compile('([0-9]+:[0-9]+) - ([0-9]+:[0-9]+)?')
# Get the day of month listed on the page as well as the expected date we are grabbing and compare these.
# If these do not match, we skip parsing the programs on the page and issue a warning.
#dayno = int(checkday.search(total).group(1))
title = checktitle.search(total)
if title:
title = title.group(1)
dayno = title.split()[1]
else:
sys.stderr.write('\nOops, there was a problem with page %s. Skipping it...\n' % (channel_url))
continue
expected = now + datetime.timedelta(days=offset)
if (not dayno.isdigit() or int(dayno) != expected.day):
sys.stderr.write('\nOops, did not expect page %s to list programs for "%s", skipping it...\n' % (channel_url,title))
continue
# and find relevant programming info
allrows = getrow.finditer(total)
for r in allrows:
detail = parserow.search(r.group(1))
if detail != None:
# default times
start_time = None
stop_time = None
# parse for begin and end times
t = times.search(detail.group(2))
if t != None:
start_time = t.group(1)
stop_time = t.group(2)
program_url = 'http://www.tvgids.nl/programma/' + detail.group(1) + '/'
program_name = detail.group(3)
# store time, name and detail url in a dictionary
tdict = {}
tdict['start'] = start_time
tdict['stop'] = stop_time
tdict['name'] = program_name
if tdict['name'] == '':
tdict['name'] = 'onbekend'
tdict['url'] = program_url
tdict['ID'] = detail.group(1)
tdict['offset'] = offset
#Add star rating if tipped by tvgids.nl
tdict['star-rating'] = '';
if r.group(1).find('Tip') != -1:
tdict['star-rating'] = '4/5'
# and append the program to the list of programs
programs.append(tdict)
# done
return programs
def make_daytime(time_string, offset=0, cutoff='00:00', stoptime=False):
Given a string '11:35' and an offset from today,
return a datetime object. The cuttoff specifies the point where the
new day starts.
Examples:
In [2]:make_daytime('11:34',0)
Out[2]:datetime.datetime(2006, 8, 3, 11, 34)
In [3]:make_daytime('11:34',1)
Out[3]:datetime.datetime(2006, 8, 4, 11, 34)
In [7]:make_daytime('11:34',0,'12:00')
Out[7]:datetime.datetime(2006, 8, 4, 11, 34)
In [4]:make_daytime('11:34',0,'11:34',False)
Out[4]:datetime.datetime(2006, 8, 3, 11, 34)
In [5]:make_daytime('11:34',0,'11:34',True)
Out[5]:datetime.datetime(2006, 8, 4, 11, 34)
h,m = [int(x) for x in time_string.split(':')];
hm = int(time_string.replace(':',''))
chm = int(cutoff.replace(':',''))
# check for the cutoff, if the time is before the cutoff then
# add a day
extra_day = 0
if (hm < chm) or (stoptime==True and hm == chm):
extra_day = 1
# and create a datetime object, DST is handled at a later point
pt = time.localtime()
dt = datetime.datetime(pt[0],pt[1],pt[2],h,m)
dt = dt + datetime.timedelta(offset+extra_day)
return dt
def correct_times(programs, quiet=0):
Parse a list of programs as generated by get_channel_all_days() and
convert begin and end times to xmltv compatible times in datetime objects.
if programs == []:
return programs
# the start time of programming for this day, times *before* this time are
# assumed to be on the next day
day_start_time = '06:00'
# initialise using the start time of the first program on this day
if programs[0]['start'] != None:
day_start_time = programs[0]['start']
for program in programs:
if program['start'] == program['stop']:
program['stop'] = None
# convert the times
if program['start'] != None:
program['start-time'] = make_daytime(program['start'], program['offset'], day_start_time)
else:
program['start-time'] = None
if program['stop'] != None:
program['stop-time'] = make_daytime(program['stop'], program['offset'], day_start_time, stoptime=True)
# extra correction, needed because the stop time of a program may be on the next day, after the
# day cutoff. For example:
# 06:00 - 23:40 Long Program
# 23:40 - 00:10 Lala
# 00:10 - 08:00 Wawa
# This puts the end date of Wawa on the current, instead of the next day. There is no way to detect
# this with a single cutoff in make_daytime. Therefore, check if there is a day difference between
# start and stop dates and correct if necessary.
if program['start-time'] != None:
# make two dates
start = program['start-time']
stop = program['stop-time']
single_day = datetime.timedelta(1)
startdate = datetime.datetime(start.year,start.month,start.day)
stopdate = datetime.datetime(stop.year,stop.month,stop.day)
if startdate - stopdate == single_day:
program['stop-time'] = program['stop-time'] + single_day
else:
program['stop-time'] = None
def parse_programs(programs, offset=0, quiet=0):
Parse a list of programs as generated by get_channel_all_days() and
convert begin and end times to xmltv compatible times.
# good programs
good_programs = []
# calculate absolute start and stop times
correct_times(programs, quiet)
# next, correct for missing end time and copy over all good programming to the
# good_programs list
for i in range(len(programs)):
# Try to correct missing end time by taking start time from next program on schedule
if (programs[i]['stop-time'] == None and i < len(programs)-1):
if not quiet:
sys.stderr.write('Oops, "%s" has no end time. Trying to fix...\n' % programs[i]['name'])
programs[i]['stop-time'] = programs[i+1]['start-time']
# The common case: start and end times are present and are not
# equal to each other (yes, this can happen)
if programs[i]['start-time'] != None and \
programs[i]['stop-time'] != None and \
programs[i]['start-time'] != programs[i]['stop-time']:
good_programs.append(programs[i])
# Han Holl: try to exclude programs that stop before they begin
for i in range(len(good_programs)-1,-1,-1):
if good_programs[i]['stop-time'] <= good_programs[i]['start-time']:
if not quiet:
sys.stderr.write('Deleting invalid stop/start time: %s\n' % good_programs[i]['name'])
del good_programs[i]
# Try to exclude programs that only identify a group or broadcaster and have overlapping start/end times with
# the actual programs
for i in range(len(good_programs)-2,-1,-1):
if good_programs[i]['start-time'] <= good_programs[i+1]['start-time'] and \
good_programs[i]['stop-time'] >= good_programs[i+1]['stop-time']:
if not quiet:
sys.stderr.write('Deleting grouping/broadcaster: %s\n' % good_programs[i]['name'])
del good_programs[i]
for i in range(len(good_programs)-1):
# PdB: Fix tvgids start-before-end x minute interval overlap. An overlap (positive or
# negative) is halved and each half is assigned to the adjacent programmes. The maximum
# overlap length between programming is set by the global variable 'max_overlap' and is
# default 10 minutes. Examples:
# Positive overlap (= overlap in programming):
# 10:55 - 12:00 Lala
# 11:55 - 12:20 Wawa
# is transformed in:
# 10:55 - 11.57 Lala
# 11:57 - 12:20 Wawa
# Negative overlap (= gap in programming):
# 10:55 - 11:50 Lala
# 12:00 - 12:20 Wawa
# is transformed in:
# 10:55 - 11.55 Lala
# 11:55 - 12:20 Wawa
stop = good_programs[i]['stop-time']
start = good_programs[i+1]['start-time']
dt = stop-start
avg = start + dt / 2
overlap = 24*60*60*dt.days + dt.seconds
# check for the size of the overlap
if 0 < abs(overlap) <= max_overlap*60:
if not quiet:
if overlap > 0:
sys.stderr.write('"%s" and "%s" overlap %s minutes. Adjusting times.\n' % \
(good_programs[i]['name'],good_programs[i+1]['name'],overlap / 60))
else:
sys.stderr.write('"%s" and "%s" have gap of %s minutes. Adjusting times.\n' % \
(good_programs[i]['name'],good_programs[i+1]['name'],abs(overlap) / 60))
# stop-time of previous program wins
if overlap_strategy == 'stop':
good_programs[i+1]['start-time'] = good_programs[i]['stop-time']
# start-time of next program wins
elif overlap_strategy == 'start':
good_programs[i]['stop-time'] = good_programs[i+1]['start-time']
# average the difference
elif overlap_strategy == 'average':
good_programs[i]['stop-time'] = avg
good_programs[i+1]['start-time'] = avg
# leave as is
else:
pass
# Experimental strategy to make sure programming does not disappear. All programs that overlap more
# than the maximum overlap length, but less than the shortest length of the two programs are
# clumped.
if do_clump:
for i in range(len(good_programs)-1):
stop = good_programs[i]['stop-time']
start = good_programs[i+1]['start-time']
dt = stop-start
overlap = 24*60*60*dt.days + dt.seconds
length0 = good_programs[i]['stop-time'] - good_programs[i]['start-time']
length1 = good_programs[i+1]['stop-time'] - good_programs[i+1]['start-time']
l0 = length0.days*24*60*60 + length0.seconds
l1 = length1.days*24*60*60 + length0.seconds
if abs(overlap) >= max_overlap*60 <= min(l0,l1)*60 and \
not good_programs[i].has_key('clumpidx') and \
not good_programs[i+1].has_key('clumpidx'):
good_programs[i]['clumpidx'] = '0/2'
good_programs[i+1]['clumpidx'] = '1/2'
good_programs[i]['stop-time'] = good_programs[i+1]['stop-time']
good_programs[i+1]['start-time'] = good_programs[i]['start-time']
# done, nothing to see here, please move on
return good_programs
def get_descriptions(programs, program_cache=None, nocattrans=0, quiet=0, slowdays=0):
Given a list of programs, from get_channel, retrieve program information
# This regexp tries to find details such as Genre, Acteurs, Jaar van Premiere etc.
detail = re.compile('<li>.*?<strong>(.*?):</strong>.*?<br />(.*?)</li>', re.DOTALL)
# These regexps find the description area, the program type and descriptive text
description = re.compile('<div class="description">.*?<div class="text"(.*?)<div class="clearer"></div>',re.DOTALL)
descrtype = re.compile('<div class="type">(.*?)</div>',re.DOTALL)
descrline = re.compile('<p>(.*?)</p>',re.DOTALL)
# randomize detail requests
nprograms = len(programs)
fetch_order = range(0,nprograms)
random.shuffle(fetch_order)
counter = 0
for i in fetch_order:
counter += 1
if programs[i]['offset'] >= slowdays:
continue
if not quiet:
sys.stderr.write('\n(%3.0f%%) %s: %s ' % (100*float(counter)/float(nprograms), i, programs[i]['name']))
# check the cache for this program's ID
cached_program = program_cache.query(programs[i]['ID'])
if (cached_program != None):
if not quiet:
sys.stderr.write(' [cached]')
# copy the cached information, except the start/end times, rating and clumping,
# these may have changed.
tstart = programs[i]['start-time']
tstop = programs[i]['stop-time']
rating = programs[i]['star-rating']
try:
clump = programs[i]['clumpidx']
except:
clump = False
programs[i] = cached_program
programs[i]['start-time'] = tstart
programs[i]['stop-time'] = tstop
programs[i]['star-rating'] = rating
if clump:
programs[i]['clumpidx'] = clump
continue
else:
# be nice to tvgids.nl
time.sleep(random.randint(nice_time[0], nice_time[1]))
# get the details page, and get all the detail nodes
descriptions = ()
details = ()
try:
if not quiet:
sys.stderr.write(' [normal fetch]')
total = get_page(programs[i]['url'])
details = detail.finditer(total)
descrspan = description.search(total);
descriptions = descrline.finditer(descrspan.group(1))
except:
# if we cannot find the description page,
# go to next in the loop
if not quiet:
sys.stderr.write(' [fetch failed or timed out]')
continue
# define containers
programs[i]['credits'] = {}
programs[i]['video'] = {}
# now parse the details
line_nr = 1;
# First, we try to find the program type in the description section.
# Note that this is not the same as the generic genres (these are searched later on), but a more descriptive one like "Culinair programma"
# If present, we store this as first part of the regular description:
programs[i]['detail1'] = descrtype.search(descrspan.group(1)).group(1).capitalize()
if programs[i]['detail1'] != '':
line_nr = line_nr + 1
# Secondly, we add one or more lines of the program description that are present.
for descript in descriptions:
d_str = 'detail' + str(line_nr)
programs[i][d_str] = descript.group(1)
# Remove sponsored link from description if present.
sponsor_pos = programs[i][d_str].rfind('<i>Gesponsorde link:</i>')
if sponsor_pos > 0:
programs[i][d_str] = programs[i][d_str][0:sponsor_pos]
programs[i][d_str] = filter_line(programs[i][d_str]).strip()
line_nr = line_nr + 1
# Finally, we check out all program details. These are generically denoted as:
# <li><strong>(TYPE):</strong><br />(CONTENT)</li>
# Some examples:
# <li><strong>Genre:</strong><br />16 oktober 2008</li>
# <li><strong>Genre:</strong><br />Amusement</li>
for d in details:
type = d.group(1).strip().lower()
content_asis = d.group(2).strip()
content = filter_line(content_asis).strip()
if content == '':
continue
elif type == 'genre':
# Fix detection of movies based on description as tvgids.nl sometimes
# categorises a movie as e.g. "Komedie", "Misdaadkomedie", "Detectivefilm".
genre = content;
if (programs[i]['detail1'].lower().find('film') != -1 \
or programs[i]['detail1'].lower().find('komedie') != -1)\
and programs[i]['detail1'].lower().find('tekenfilm') == -1 \
and programs[i]['detail1'].lower().find('animatiekomedie') == -1 \
and programs[i]['detail1'].lower().find('filmpje') == -1:
genre = 'film'
if nocattrans:
programs[i]['genre'] = genre.title()
else:
try:
programs[i]['genre'] = cattrans[genre.lower()]
except:
programs[i]['genre'] = ''
# Parse persons and their roles for credit info
elif roletrans.has_key(type):
programs[i]['credits'][roletrans[type]] = []
persons = content_asis.split(',');
for name in persons:
if name.find(':') != -1:
name = name.split(':')[1]
if name.find('-') != -1:
name = name.split('-')[0]
if name.find('e.a') != -1:
name = name.split('e.a')[0]
programs[i]['credits'][roletrans[type]].append(filter_line(name.strip()))
elif type == 'bijzonderheden':
if content.find('Breedbeeld') != -1:
programs[i]['video']['breedbeeld'] = 1
if content.find('Zwart') != -1:
programs[i]['video']['blackwhite'] = 1
if content.find('Teletekst') != -1:
programs[i]['teletekst'] = 1
if content.find('Stereo') != -1:
programs[i]['stereo'] = 1
elif type == 'url':
programs[i]['infourl'] = content
else:
# In unmatched cases, we still add the parsed type and content to the program details.
# Some of these will lead to xmltv output during the xmlefy_programs step
programs[i][type] = content
# do not cache programming that is unknown at the time
# of fetching.
if programs[i]['name'].lower() != 'onbekend':
program_cache.add(programs[i])
if not quiet:
sys.stderr.write('\ndone...\n\n')
# done
def title_split(program):
Some channels have the annoying habit of adding the subtitle to the title of a program.
This function attempts to fix this, by splitting the name at a ': '.
if (program.has_key('titel aflevering') and program['titel aflevering'] != '') \
or (program.has_key('genre') and program['genre'].lower() in ['movies','film']):
return
colonpos = program['name'].rfind(': ')
if colonpos > 0:
program['titel aflevering'] = program['name'][colonpos+1:len(program['name'])].strip()
program['name'] = program['name'][0:colonpos].strip()
def xmlefy_programs(programs, channel, desc_len, compat=0, nocattrans=0):
Given a list of programming (from get_channels())
returns a string with the xml equivalent
output = []
for program in programs:
clumpidx = ''
try:
if program.has_key('clumpidx'):
clumpidx = 'clumpidx="'+program['clumpidx']+'"'
except:
print program
output.append(' <programme start="%s" stop="%s" channel="%s%s" %s> \n' % \
(format_timezone(program['start-time']), format_timezone(program['stop-time']),\
channel, compat and '.tvgids.nl' or '', clumpidx))
output.append(' <title lang="nl">%s</title>\n' % filter_line(program['name']))
if program.has_key('titel aflevering') and program['titel aflevering'] != '':
output.append(' <sub-title lang="nl">%s</sub-title>\n' % filter_line(program['titel aflevering']))
desc = []
for detail_row in ['detail1','detail2','detail3']:
if program.has_key(detail_row) and not re.search('[Gg]een detailgegevens be(?:kend|schikbaar)', program[detail_row]):
desc.append('%s ' % program[detail_row])
if desc != []:
# join and remove newlines from descriptions
desc_line = "".join(desc).strip()
desc_line.replace('\n', ' ')
if len(desc_line) > desc_len:
spacepos = desc_line[0:desc_len-3].rfind(' ')
desc_line = desc_line[0:spacepos] + '...'
output.append(' <desc lang="nl">%s</desc>\n' % desc_line)
# Process credits section if present.
# This will generate director/actor/presenter info.
if program.has_key('credits') and program['credits'] != {}:
output.append(' <credits>\n')
for role in program['credits']:
for name in program['credits'][role]:
if name != '':
output.append(' <%s>%s</%s>\n' % (role, name, role))
output.append(' </credits>\n')
if program.has_key('jaar van premiere') and program['jaar van premiere'] != '':
output.append(' <date>%s</date>\n' % program['jaar van premiere'])
if program.has_key('genre') and program['genre'] != '':
output.append(' <category')
if nocattrans:
output.append(' lang="nl"')
output.append ('>%s</category>\n' % program['genre'])
if program.has_key('infourl') and program['infourl'] != '':
output.append(' <url>%s</url>\n' % program['infourl'])
if program.has_key('aflevering') and program['aflevering'] != '':
output.append(' <episode-num system="onscreen">%s</episode-num>\n' % filter_line(program['aflevering']))
# Process video section if present
if program.has_key('video') and program['video'] != {}:
output.append(' <video>\n');
if program['video'].has_key('breedbeeld'):
output.append(' <aspect>16:9</aspect>\n')
if program['video'].has_key('blackwhite'):
output.append(' <colour>no</colour>\n')
output.append(' </video>\n')
if program.has_key('stereo'):
output.append(' <audio><stereo>stereo</stereo></audio>\n')
if program.has_key('teletekst'):
output.append(' <subtitles type="teletext" />\n')
# Set star-rating if applicable
if program['star-rating'] != '':
output.append(' <star-rating><value>%s</value></star-rating>\n' % program['star-rating'])
output.append(' </programme>\n')
return "".join(output)
def main():
# Parse command line options
try:
opts, args = getopt.getopt(sys.argv[1:], "h", ["help", "output=", "capabilities",
"preferredmethod", "days=",
"configure", "fast", "slow",
"cache=", "clean_cache",
"slowdays=","compat",
"desc-length=","description",
"nocattrans","config-file=",
"max_overlap=", "overlap_strategy=",
"clear_cache", "quiet","logos="])
except getopt.GetoptError:
usage()
sys.exit(2)
# DEFAULT OPTIONS - Edit if you know what you are doing
# where the output goes
output = None
output_file = None
# the total number of days to fetch
days = 6
# Fetch data in fast mode, i.e. do NOT grab all the detail information,
# fast means fast, because as it then does not have to fetch a web page for each program
# Default: fast=0
fast = 0
# number of days to fetch in slow mode. For example: --days 5 --slowdays 2, will
# fetch the first two days in slow mode (with all the details) and the remaining three
# days in fast mode.
slowdays = 6
# no output
quiet = 0
# insert url of channel logo into the xml data, this will be picked up by mythfilldatabase
logos = 1
# enable this option if you were using tv_grab_nl, it adjusts the generated
# xmltvid's so that everything works.
compat = 0
# enable this option if you do not want the tvgids categories being translated into
# MythTV-categories (genres)
nocattrans = 0
# Maximum number of characters to use for program description.
# Different values may work better in different versions of MythTV.
desc_len = 475
# default configuration file locations
hpath = ''
if os.environ.has_key('HOME'):
hpath = os.environ['HOME']
# extra test for windows users
elif os.environ.has_key('HOMEPATH'):
hpath = os.environ['HOMEPATH']
# hpath = ''
xmltv_dir = hpath+'/.xmltv'
program_cache_file = xmltv_dir+'/program_cache'
config_file = xmltv_dir+'/tv_grab_nl_py.conf'
# cache the detail information.
program_cache = None
clean_cache = 1
clear_cache = 0
# seed the random generator
random.seed(time.time())
for o, a in opts:
if o in ("-h", "--help"):
usage()
sys.exit(1)
if o == "--quiet":
quiet = 1;
if o == "--description":
print "The Netherlands (tv_grab_nl_py $Rev: 104 $)"
sys.exit(0)
if o == "--capabilities":
print "baseline"
print "cache"
print "manualconfig"
print "preferredmethod"
sys.exit(0)
if o == '--preferredmethod':
print 'allatonce'
sys.exit(0)
if o == '--desc-length':
# Use the requested length for programme descriptions.
desc_len = int(a)
if not quiet:
sys.stderr.write('Using description length: %d\n' % desc_len)
for o, a in opts:
if o == "--config-file":
# use the provided name for configuration
config_file = a
if not quiet:
sys.stderr.write('Using config file: %s\n' % config_file)
for o, a in opts:
if o == "--configure":
# check for the ~.xmltv dir
if not os.path.exists(xmltv_dir):
if not quiet:
sys.stderr.write('You do not have the ~/.xmltv directory,')
sys.stderr.write('I am going to make a shiny new one for you...')
os.mkdir(xmltv_dir)
if not quiet:
sys.stderr.write('Creating config file: %s\n' % config_file)
get_channels(config_file)
sys.exit(0)
if o == "--days":
# limit days to maximum supported by tvgids.nl
days = min(int(a),6)
if o == "--compat":
compat = 1
if o == "--nocattrans":
nocattrans = 1
if o == "--fast":
fast = 1
if o == "--output":
output_file = a
try:
output = open(output_file,'w')
# and redirect output
if debug:
debug_file = open('/tmp/kaas.xml','w')
blah = redirect.Tee(output, debug_file)
sys.stdout = blah
else:
sys.stdout = output
except:
if not quiet:
sys.stderr.write('Cannot write to outputfile: %s\n' % output_file)
sys.exit(2)
if o == "--slowdays":
# limit slowdays to maximum supported by tvgids.nl
slowdays = min(int(a),6)
# slowdays implies fast == 0
fast = 0
if o == "--logos":
logos = int(a)
if o == "--clean_cache":
clean_cache = 1
if o == "--clear_cache":
clear_cache = 1
if o == "--cache":
program_cache_file = a
if o == "--max_overlap":
max_overlap = int(a)
if o == "--overlap_strategy":
overlap_strategy = a
# get configfile if available
try:
f = open(config_file,'r')
except:
sys.stderr.write('Config file %s not found.\n' % config_file)
sys.stderr.write('Re-run me with the --configure flag.\n')
sys.exit(1)
#check for cache
program_cache = ProgramCache(program_cache_file)
if clean_cache != 0:
program_cache.clean()
if clear_cache != 0:
program_cache.clear()
# Go!
channels = {}
# Read the channel stuff
for blah in f.readlines():
blah = blah.lstrip()
blah = blah.replace('\n','')
if blah:
if blah[0] != '#':
channel = blah.split()
channels[channel[0]] = " ".join(channel[1:])
# channels are now in channels dict keyed on channel id
# print header stuff
print '<?xml version="1.0" encoding="ISO-8859-1"?>'
print '<!DOCTYPE tv SYSTEM "xmltv.dtd">'
print '<tv generator-info-name="tv_grab_nl_py $Rev: 104 $">'
# first do the channel info
for key in channels.keys():
print ' <channel id="%s%s">' % (key, compat and '.tvgids.nl' or '')
print ' <display-name lang="nl">%s</display-name>' % channels[key]
if (logos):
ikey = int(key)
if logo_names.has_key(ikey):
full_logo_url = logo_provider[logo_names[ikey][0]]+logo_names[ikey][1]+'.gif'
print ' <icon src="%s" />' % full_logo_url
print ' </channel>'
num_chans = len(channels.keys())
channel_cnt = 0
if program_cache != None:
program_cache.clean()
fluffy = channels.keys()
nfluffy = len(fluffy)
for id in fluffy:
channel_cnt += 1
if not quiet:
sys.stderr.write('\n\nNow fetching %s(xmltvid=%s%s) (channel %s of %s)\n' % \
(channels[id], id, (compat and '.tvgids.nl' or ''), channel_cnt, nfluffy))
info = get_channel_all_days(id, days, quiet)
blah = parse_programs(info, None, quiet)
# fetch descriptions
if not fast:
get_descriptions(blah, program_cache, nocattrans, quiet, slowdays)
# Split titles with colon in it
# Note: this only takes place if all days retrieved are also grabbed with details (slowdays=days)
# otherwise this function might change some titles after a few grabs and thus may result in
# loss of programmed recordings for these programs.
if slowdays == days:
for program in blah:
title_split(program)
print xmlefy_programs(blah, id, desc_len, compat, nocattrans)
# save the cache after each channel fetch
if program_cache != None:
program_cache.dump(program_cache_file)
# be nice to tvgids.nl
time.sleep(random.randint(nice_time[0], nice_time[1]))
if program_cache != None:
program_cache.dump(program_cache_file)
# print footer stuff
print "</tv>"
# close the outputfile if necessary
if output != None:
output.close()
# and return success
sys.exit(0)
# allow this to be a module
if __name__ == '__main__':
main()
# vim:tw=0:et:sw=4
[cedric@tv ~]$
Best regards,
Cedric
Last edited by cdwijs (2010-11-04 18:44:51)Running the script by python2 solves it for me:
su - mythtv -c "nice -n 19 python2 /usr/bin/tv_grab_nl_py --output ~/listings.xml"
Best regards,
Cedric -
I am using Flash Builder 4.7 to build an Actionscript AIR project. The project embeds a number of png files from my local directory and I have been using absolute paths which all works fine.
I have a laptop with which I want to start developing the same project - I set up a git repository that both the laptop and main pc can pull from and so I can get the source where I need it and push it back to the central repository.
My problem is that the absolute paths for the embed commands don't work on the laptop as it has a different filesystem setup (Windows 8 with one drive as opposed to Windows 7 with a SSD and a data drive). I thought the solution would be as easy as using an environment variable to specify the path which could then point to a different physical directory on both machines, i.e:
[Embed(source = "DEVELOPER_RESOURCES/graphics/are/here.png"]
I did a bit of research and there was quite a lot mentioned about setting up resource directories using path variables which I worked through but I just can't get it to compile. The Actionscript compiler just won't find the png files however I specify the path. I tried something with a FLEX project and the compiler didn't complain but I think this is because the compiler for FLEX uses a different convention.
[Embed(source ="/Project Name/DEVELOPER_RESOURCES/graphics/are/here.png"] works with FLEX but not Actionscript.
So does anyone have a recipe for using the Embed command referencing assets using an environment variable that works across multiple machines with different file structures?I managed to find a solution on Windows which was to use symlinks and absolute paths. You an basically point one directory to another so I did something like:
mklink c:\developer_resources c:/the/local/path/to/my/resources
and then reference all resources as c:\developer_resources\...
Now as long as a developer machine has the right link (from c:\developer_resources to the place where the resources are kept) then it seems to work.
This doesn't however work for Mac and certainly isn't a solution for passing files between Mac and windows -
Creating a Popup in ActionScript vs Creating a Popup in MXML
Hello there
I think I need a little help with a couple of items. I'm using the Popup Library version 1.11 and I'm trying to open up a Popup (with an associated presentation model) which I have defined as follows.
view.popup.EditSection.mxml
view.popup.EditSectionPM.as
the view that opens the popup class (EditSection) dows the following in MXML, and it looks right, but it gives me limited access to the reference of the popup window. With MXML it looks like this http://grab.by/6Oaf
<popup:PopUpFactory id="editSectionPopup" reuse="true" modal="true">
<fx:Component>
<popupWindows:EditSection/>
</fx:Component>
<popup:behaviors>
<spark:ZoomAndFadeBehavior duration="1000"/>
<behavior:KeepCenteredBehavior/>
<behavior:CenterBehavior/>
<popup:AddPopUpToParsleyContext />
</popup:behaviors>
</popup:PopUpFactory>
instead of this, I've cobbled together the following ActionScript, but the popups look VASTLY different when they open. Here is the ActionScript.. the creationComplete runs the initializePopup() and the button click runs the openPopup().. this version looks like http://grab.by/6Oaz when opened.
It doesnt seem to honor the height, width, etc of the Class defining the popup, and when I click the different states, I get errors indicating that no such states exist... though they exist in the class
question: Why might Cairngorm be opening up the wrong (generic?) TitleWindow? What am i doing wrong here?
<fx:Script>
<![CDATA[
import com.adobe.cairngorm.popup.PopUpFactory;
import com.adobe.cairngorm.popup.PopUpWrapper;
import com.adobe.cairngorm.popup.behavior.CenterBehavior;
import com.adobe.cairngorm.popup.behavior.KeepCenteredBehavior;
import com.adobe.cairngorm.popup.behavior.spark.ZoomAndFadeBehavior;
import com.company.psa.docbuilder.adhoc.view.editsection.EditSection;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
private var wrapper:PopUpWrapper;
private var factory:PopUpFactory;
private var zoomAndFadeBehavior = new ZoomAndFadeBehavior();
public function initializePopup():void
var myEditSectionPopup:EditSection;
var myBehaviors:Array = new Array();
var myZAF = new ZoomAndFadeBehavior();
myBehaviors[0] = myZAF; // How do I set the duration?
myBehaviors[1] = new CenterBehavior()
myBehaviors[2] = new KeepCenteredBehavior();
factory = new PopUpFactory();
factory.popup = new ClassFactory(EditSection);
factory.reuse = false;
factory.modal = true;
factory.behaviors=myBehaviors;
// How do I reference the opened window?
public function openPopup () :void
factory.open = true;
]]>
</fx:Script>
Here is the definition of the EditSection.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:spicefactory="http://www.spicefactory.org/parsley"
xmlns:mx="library://ns.adobe.com/flex/mx"
enabled="true"
width.EditSectionState="500"
height.EditSectionState="350"
width.YesNoCancelState="320"
height.YesNoCancelState="200"
width.YesNoState="320"
height.YesNoState="200"
title="{pm.windowTitle}"
currentState="{pm.viewState}"
creationComplete="init()">
<fx:Metadata>
[Event(name="close", type="mx.events.CloseEvent")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import mx.controls.Alert;
import mx.core.mx_internal;
import mx.events.CloseEvent;
[Inject]
[Bindable]
public var pm:EditSectionPM;
protected function closeHandler(event:CloseEvent):void
pm.closeHandler(event);
trace("EditSection is closing");
public function init():void
]]>
</fx:Script>
<s:states>
<s:State name="EditSectionState"/>
<s:State name="YesNoCancelState"/>
<s:State name="YesNoState"/>
</s:states>
<fx:Declarations>
<spicefactory:Configure/>
</fx:Declarations>
<!-- Define the transition to animate the change of view state. -->
<s:transitions>
<s:Transition fromState="EditSectionState">
<s:Parallel>
<mx:Resize target="{this}"
duration="500"/>
</s:Parallel>
</s:Transition>
<s:Transition fromState="YesNoCancelState">
<s:Sequence>
<mx:Resize target="{this}"
duration="500"/>
</s:Sequence>
</s:Transition>
<s:Transition fromState="YesNoState">
<s:Sequence>
<mx:Resize target="{this}"
duration="500"/>
</s:Sequence>
</s:Transition>
</s:transitions>
<s:Label text="Hello There World"
left="10"
right="10"
top="10"
verticalAlign="middle"
textAlign="center"
click="pm.labelClickHandler(event)"/>
<mx:ControlBar width="50%"
left="10"
bottom="10"
height="40"
horizontalAlign="left"
verticalAlign="middle">
<mx:Button label="Cancel"
width="120"
click="dispatchEvent( new CloseEvent( CloseEvent.CLOSE ) )"
includeIn="EditSectionState"/>
<mx:Button label="Reset to Default"
width="140"
click="dispatchEvent( new CloseEvent( CloseEvent.CLOSE ) )"
includeIn="EditSectionState"/>
</mx:ControlBar>
<mx:ControlBar width="50%"
right="10"
bottom="10"
height="40"
horizontalAlign="right"
verticalAlign="middle">
<mx:Button label="Save"
width="140"
click="dispatchEvent( new CloseEvent( CloseEvent.CLOSE ) )"
includeIn="EditSectionState"/>
<mx:Button id="yesButton"
label="Yes"
width="60"
click="dispatchEvent( new CloseEvent( CloseEvent.CLOSE ) )"
includeIn="YesNoCancelState,YesNoState"/>
<mx:Button id="noButton"
label="No"
width="60"
click="dispatchEvent( new CloseEvent( CloseEvent.CLOSE ) )"
includeIn="YesNoCancelState,YesNoState"/>
<mx:Button id="cancelButton"
label="Cancel"
width="60"
click="dispatchEvent( new CloseEvent( CloseEvent.CLOSE ) )"
includeIn="YesNoCancelState"/>
</mx:ControlBar>
<s:RadioButton id="editSectionsCheckbox"
y="30"
label="Edit Sections"
selected="true"
click="pm.editSectionStateClickHandler(event)"
y.YesNoCancelState="24"
y.YesNoState="24"
width.YesNoState="99"
horizontalCenter.EditSectionState="-2"
y.EditSectionState="30"
width.EditSectionState="95"
horizontalCenter.YesNoCancelState="-7"
horizontalCenter.YesNoState="-3"/>
<s:RadioButton id="yesNoCancelCheckbox"
y="56"
label="Yes/No/Cancel"
click="pm.yesNoCancelStateClickHandler(event)"
y.YesNoCancelState="50"
y.YesNoState="50"
horizontalCenter.EditSectionState="-1"
y.EditSectionState="56"
horizontalCenter.YesNoCancelState="-3"
horizontalCenter.YesNoState="-3"/>
<s:RadioButton id="yesNoCheckbox"
y="76"
label="Yes/No"
click="pm.yesNoStateClickHandler(event)"
width="99"
y.EditSectionState="83"
horizontalCenter.EditSectionState="-1"
horizontalCenter.YesNoCancelState="-3"
horizontalCenter.YesNoState="-3"/>
</s:TitleWindow>
Here is the definition of EditSectionPM.as
/* Copyright 2010 */
/* All rights reserved. */
package com.company.psa.docbuilder.adhoc.view.editsection
import com.company.psa.docbuilder.adhoc.business.IDocumentConfigurationReceiver;
import com.company.psa.docbuilder.core.business.DocumentConfiguration;
import flash.events.MouseEvent;
import mx.controls.Alert;
import mx.events.CloseEvent;
public class EditSectionPM implements IDocumentConfigurationReceiver
[Bindable]
public var height:int=300;
[Bindable]
public var message:String="Spark Popup";
[Bindable]
public var viewState:String="EditSectionState";
[Bindable]
public var width:int=400;
[Bindable]
public var windowTitle:String="Edit: ";
[Bindable]
public var documentConfiguration:DocumentConfiguration;
public var isDirty:Boolean=false;
public var cancelVisible:Boolean=false;
// Implementing the notifier receiver design pattern
public function setDocumentConfiguration(argDocumentConfiguration:DocumentConfiguration):void
this.documentConfiguration=argDocumentConfiguration;
public function closeHandler(event:CloseEvent):void
trace("Close was clicked");
public function cancelHandler(event:CloseEvent):void
trace("Cancel was clicked");
public function resetHandler(event:CloseEvent):void
trace("Reset was clicked");
public function yesHandler(event:CloseEvent):void
trace("Yes was clicked");
public function noHandler(event:CloseEvent):void
trace("No was clicked");
public function editSectionStateClickHandler(event:MouseEvent):void
trace("Edit Section state selected (setting this in the PM)");
this.viewState="EditSectionState";
public function yesNoCancelStateClickHandler(event:MouseEvent):void
trace("Yes/No/Cancel state selected (setting this in the PM)");
this.viewState="YesNoCancelState";
public function yesNoStateClickHandler(event:MouseEvent):void
trace("Yes/No/Cancel state selected (setting this in the PM)");
this.viewState="YesNoState";
public function labelClickHandler(event:MouseEvent):void
trace("Label was clicked");
Alert.show("The Label"+event.toString() ,"You Clicked");Hi John,
If you're using Flex 4, the PopUpFactory isn't needed anymore, you can use the PopUpWrapper for everything. More info here: https://sourceforge.net/adobe/cairngorm/wiki/HowToUseCairngormPopup/
What's the reason you need a reference to the popup window? I ask because one very common reason is that users want to open and close it from elsewhere (i.e. a Presentation Model). For that, the popup library offers bindable property open, so all your behaviour object needs to do is to bind a Boolean to it and you don't need an extra view reference of the actual popup window. However, you could also get that if you listen to one of the open/close type events; inside each event object there's a popup property that points to the actual popup window. Regarding your AS usage, I didn't see anything wrong at first sight but maybe compare it the AS sample in the PopupTest project? But first, check if you really need to do it in AS as the MXML examples in PopupTest and on the how-to wiki read simpler IMHO.But also, let us know if it does'nt satisfy your use case.
Alex -
Flex 3 vs Flex 4 Preprocessor directives and code behind (External Actionscript file)
I have a framework that I've built that I want to use on Flex3 and Flex4.
I've added pre-processor directives as per this link (http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_21.html) and got my Flex 4 code to compile nicely.
I then went to flex 3 and discovered my sub-class of Application wouldn't compile because it was based off of spark. No problem, I'll add in a directive.
Except now my overridden class has duplicate code, specific to which SDK it is using.
No problem, I'll put all of the application class code in an Actionscript file and include it in both Application class declarations for each directive.
It works nicely in Flex 3, so I went to Flex 4, tried to compile and now I'm getting compiler errors saying things such as "The (private|public|protected) attribute may only be used on class property definitions." and "The (private|public|protected) attribute can only be used inside a package.
This same file works in Flex 3, but not in Flex 4.
What can I do to make the code compile in both places?
I'll work on a simple case so I can upload some code.Nevermind.
I got around this issue by renaming my sub-classed Application to "...Application".
Now I can use a directive to specify an import statement for the extends Application portion rather than specifiing the fully qualified spark.components.Application or mx.core.Application.
Lame - but done. -
Compability problem with Java and Python RSA algorithm implementation
I have client server application. Server is writtein in python, client in java. Client receives messages from server encrypted with RSA (http://stuvel.eu/rsa), and I'm unable to decrypt it. It seems that this is RSA algorithm compatibility problem. I'm using algorithm from java.security package, instatinating Cipher object like this: c = Cipher.getInstance("RSA"); . I noticed that this algorithm produces for input blocks of lengtrh <=117 ouput block of length 128. Server I guess uses the most triviall impelentation of RSA ( (1 byte is encrypted to 1 byte) So i want to make my java algorithm compatibile with this one which server uses. How to do that ? Do i have to instatinate Cipher object in different way ? Or use another library ?
azedor wrote:
First you said it was no good because it could only handle <= 117 byte inputs, now you say it is no good because it produces a 128-byte output. You're not making sense.First i said that this two RSA implementations are not compatibile, and first reason i noticed firstly is that Python imlementation for input of length N produces cryptogram of the same length. Not true. In general, the RSA encryption of any number of bytes less than the length of the modulus will produce a result of length near that of the modulus. When N is less than the length of the modulus, it is rare that N bytes of cleartext produces N bytes of ciphertext.
Java implementation for data block of length <=117 produces alwasy 128 bytes of output.Pretty much correct and very much desirable. This is primarily a function of the PKCS1 padding which is used to solve two basic problems. First, as I alluded to in my first response, it is the nature of the algorithm that leading zeros are not preserved and second when the cleartext is very small (a few bytes) the exponentiation does not roll over and it is easy to decrypt the result. Both these problems are addressed by PKCS1 padding.
>
>
After what sabre150 said i think of giving up idea of translating Python code to Java and considering to use another assymetric cryptography algorithms on both sides. Can you recommend me sth what should be compatibile with Python ?This seems to be at odds with your statement in reply #3 "Also have acces only to client code so i have to change sth in java." ! This statement is why I said "I suspect ... you have dug a deep hole".
In your position I would use the Python bindings for openssl. Once more, Google is your friend.
Maybe you are looking for
-
My iphone5, 7.0.3, has 725MB of Messages shown in Usage, but no messages in Message App. Where are they and how do I get rid of them
-
I have a comcast router connected to the airport extreme then on to airport express. Comcast just changed their router to bridge only. My airport extreme is flashing yellow w/ Double NAT status. The airport express is fine. Any suggestions on how
-
How to display hourglass while ADF view link is retrieving rows.
Hi All, I have an ADF panel which includes several interdependent ADF View Objects and View Links. The query of the top view object might return several rows, then once user navigates from 1st to second row and so on, the dependent (child) view links
-
After effects CC on maverick slow render because of PP CC Dynamic Link Footage
I put premiere pro CC edits in After Effects CC through dynamic Link every day. Since I upgraded my systems to Maverick and first installed the 12.0.1 and afterwards 12.1 the rendering of the After effects projects that have Dynamic Link Edits on the
-
When a website is slow or won't load, how do I stop it without exiting Firefox?
It was easy in earlier version. This has been so frustrating in the last year or two that I finally had to ask.