PyQt6 Create Playlist - qmediaplayer

How can I create playlist in PyQt6?
I can only set one media with setSource():
self.soundUrl = QUrl.fromLocalFile("4k-is-2.mp4")
self.player.setSource(self.soundUrl)

Related

Indesign render script need to target TextFrames within Rectangle objects

I am working on InDesign rendering script (.jsx) for rendering template (.indd) using InDesign Server (Version: 17.2). In my InDesign templates, there are Rectangle ([object Rectangle]) items, that further includes some TextFrames (more than one). When I try to access those TextFrames using [object Rectangle].allpageItems, it gives and empty array. How can I access those TextFrames from the [object Rectangle]? Further, can I get/find the InDesign element/item (TextFrame) using xmlTag name? If yes, then please provide the example by which we can find the item.
I suppose it should be something like this:
var doc = app.activeDocument;
var rectangle = doc.rectangles[0]; // get a first rectangle
var text_frame = rectangle.textFrames[0]; // get a textFrame inside of the rectangle
text_frame.select(); // select the text frame

TreeView Items dump pywinauto

how can dump alls items of TreeView
app = Application(backend="uia").connect(path = PathApp, class_name='TreeView')
image
https://ibb.co/WfQMyFQ
There is method .dump_tree() for top window specification.
app = Application(backend="uia").connect(path = PathApp, class_name='TreeView')
app.window(title="somesoft").dump_tree()

How could I create a music file using godot?

I'm trying to create a music game using godot, it's similar to playing a piano, the player presses keys, each key has a sound assigned, and the music plays. What I want is to have a kind of recorder inside the game to be able to save the melody created and export it to some file like mp3 or wav. I'm using gdScript and I've been researching about this but wasn't able to find anything.
This issue has two parts, first of all, we need to actually reproduce the audio, and second we need to record it and save it a file. And we have two options for playing the audio... Let us begin there.
Playing
Playing audio samples
As you probably know you can use AudioStreamPlayer(2D/3D) to play audio. If you have samples an instrument, you can set up multiple of these, one for each note. And then play them individually by calling play.
Alright, but what if you don't have a sample for each note? Just one.
Well, you can use pitch_scale on your AudioStreamPlayer(2D/3D), but that also shortens the note. Instead…
Look at the bottom of the Godot editor, there is a panel called Audio. There you can configure audio buses. Add a new bus, add the PitchShift effect to it. If you select the effect, you can configure it on the Inspector panel. Now, in your AudioStreamPlayer(2D/3D), you can select the bus that has the effect, and there you go.
Except, you would have to setup a lot of these. So, let us do that from code instead.
First, adding an AudioStreamPlayer(2D/3D), is adding a node:
var player := AudioStreamPlayer.new()
add_child(player)
We want to set the sample, so we also need to load the sample:
var sample := preload("res://sample.ogg")
var player := AudioStreamPlayer.new()
player.stream = sample # <--
add_child(player)
By the way, double check in the import settings of your sample (With the file selected in the FileSystem panel, go to the Import panel) if it has loop enabled or not.
To set the audio bus, you can do this:
var sample := preload("res://sample.ogg")
var player := AudioStreamPlayer.new()
player.stream = sample
player.bus = "Bus Name" # <--
add_child(player)
And that brings me to adding an audio bus:
AudioServer.add_bus()
Wait, hmm… Ok, let us put the bus explicitly at the end, so we know the index:
var bus_index := AudioServer.get_bus_count()
AudioServer.add_bus(bus_index)
And give it a name:
var bus_index := AudioServer.get_bus_count()
AudioServer.add_bus(bus_index)
AudioServer.set_bus_name(bus_index, "Bus Name") # <--
And let us route it to Master:
var bus_index := AudioServer.get_bus_count()
AudioServer.add_bus(bus_index)
AudioServer.set_bus_name(bus_index, "Bus Name")
AudioServer.set_bus_send(bus_index, "Master") # <--
Yes, it is set to Master by default. But you might need to change that.
And now we can add the effect:
var pitch_shift_effect := AudioEffectPitchShift.new()
pitch_shift_effect.pitch_scale = 0.1
AudioServer.add_bus_effect(bus_index, pitch_shift_effect, 0)
That 0 at the end is the index of the effect. Since this is the only effect in a newly created audio bus, it goes in the index 0.
And, well, you can make a loop and add the players with their corresponding audio buses with their pitch shift effects.
Generating audio
Alright, perhaps you don't have a sample at all. Instead you want to generate waves. We can do that too.
This time we are going to have a AudioStreamPlayer(2D/3D), and give it an AudioStreamGenerator (you find it in the drop down menu from the stream property in the Inspecto panel). Edit the resource to set the mix rate you want to work with, by default it is 44100. But we are going to be generating this audio as close as real time as possible, so a lower rate might be necesary.
Now, in a script, we are going to get the playback object form the AudioStreamPlayer(2D/3D):
onready var _playback := $Player.get_stream_playback()
Or if you are placing the script in the player, because why not:
onready var _playback := get_stream_playback()
We can push audio frames to the playback object. With playback.push_frame, it takes a Vector2, where each component is one of the stereo channels (x = left, y = right).
We are going to call get_frames_available to figure out how many we need to push, and we are going to be pushing them every graphics frame (i.e. in _process).
The following script will generate an sine wave with frequency 440 (A):
extends AudioStreamPlayer
onready var _playback := get_stream_playback()
onready var _sample_hz:float = stream.mix_rate
var _pulse_hz := 440.0
var _phase := 0.0
func _ready():
_fill_buffer()
func _process(_delta):
_fill_buffer()
func _fill_buffer():
var increment := _pulse_hz / _sample_hz
for frame_index in int(_playback.get_frames_available()):
_playback.push_frame(Vector2.ONE * sin(_phase * TAU))
_phase = fmod(_phase + increment, 1.0)
You can set the AudioStreamPlayer to autoplay.
This code is adapted from the official Audio Generator demo.
We, of course, may want to play multiple of these notes at the same time.
So, I created a Note class that looks like this (just add a new script in the FileSystem panel):
class_name Note extends Object
var increment:float
var pulse_hz:float
var phase:float
func _init(hz:float, sample_hz):
pulse_hz = hz
phase = 0.0
increment = pulse_hz / sample_hz
func frame() -> float:
var result := sin(phase * TAU)
phase = fmod(phase + increment, 1.0)
return result
And now we can play them like this:
extends AudioStreamPlayer
onready var _playback := get_stream_playback()
onready var _sample_hz:float = stream.mix_rate
onready var notes := [
Note.new(440, _sample_hz),
Note.new(554.37, _sample_hz),
Note.new(622.25, _sample_hz)
]
func _ready():
_fill_buffer()
func _process(_delta):
_fill_buffer()
func _fill_buffer():
var note_count := notes.size()
for frame_index in int(_playback.get_frames_available()):
var frame := 0.0
for note in notes:
frame += note.frame()
_playback.push_frame(Vector2.ONE * frame / note_count)
Recording
To record we are going to add a "Record" (AudioEffectRecord) effect to an audio bus. Let us say you added it to Master (the first bus), and it is the first effect there, we can get if from code like this:
var record_bus_index := 0 # Master
var record_effect_index := 0 # First Effect
var record_effect = AudioServer.get_bus_effect(record_bus_index, record_effect_index) as AudioEffectRecord
Then we need to start recording, like this:
record_effect.set_recording_active(true)
And when we are done recording we can get what was recorded (an AudioStreamSample) and stop recording:
var recording := record_effect.get_recording()
record_effect.set_recording_active(false)
And finally we can save it to a WAV file:
recording.save_to_wav("user://recording.wav")
See also the official Audio Mic Record demo project.
No, there is no in engine solution to save an MP3.
Linky links
The official Audio Generator demo.
The official Audio Mic Record demo project.
The addon godot-simple-sampler.
The addon godot-midi-player.

How to create multiple jwplayer playing buttons

This is a jwplayer case. I have a website with music album pages. Right now I have a jwplayer playing a playlist and works fine, but I want to have a table listing all the songs by track number and a play icon that plays the song on the first of each line. So far I managed to create a play icon that plays the full playlist but no luck on how to create as many icons as the number of songs and that each plays a different song from the playlist.
This is a representation of what I want to do
play icon (song 1) | track number | title song 1 | duration
play icon (song 2) | track number | title song 2 | duration
The current code I have is this, which creates a single play icon that plays the playlist. This code, by the way is pretty awesome as it plays next song automatically and controls the pause/play of the main player. This website runs on joomla.
<script>
var playerInstance = jwplayer('container');
playerInstance.setup({
playlist: [{
//DYNAMICALLY GENERATED PLAYLIST
<?php
$album_id = $this->item->id;
// Get default database object
$db = JFactory::getDbo();
// Get a new JDatabaseQuery object
$query = $db->getQuery(true);
$query = 'SELECT position, name, length, filename FROM XXX WHERE `album_id` = ' . $db->quote( (int) $album_id ) . ' ORDER BY `num` ASC LIMIT 0 , 30';
$db->setQuery($query);
$results = $db -> loadAssocList();
foreach($results as $row){
echo "file: \"/". htmlentities($row['filename']). "\", ";
echo "title: \"". htmlentities($row['name']). "\"";
echo "},{";
}
?> }]
//END DYNAMICALLY GENERATED PLAYLIST
controls: false
});
playerInstance.on('play', function() {
document.getElementById("videoPlayPause").style.backgroundPosition = "-263px -70px";
});
playerInstance.on('pause', function() {
document.getElementById("videoPlayPause").style.backgroundPosition = "-287px -70px";
});
</script>
<br/>
<div class="videoPlayerControls playing" id="videoPlayerControls">
<button id="videoPlayPause" onclick="playerInstance.play();" onmouseout="if(playerInstance.getState() == "IDLE" || playerInstance.getState() == "PAUSED"){document.getElementById("videoPlayPause").style.backgroundPosition = "-62px 0";} if(playerInstance.getState() == "PLAYING"){document.getElementById("videoPlayPause").style.backgroundPosition = "-62px -50px";}" onmouseover="if(playerInstance.getState() == "PLAYING"){document.getElementById("videoPlayPause").style.backgroundPosition = "-263px -70px";}if(playerInstance.getState() == "IDLE" || playerInstance.getState() == "PAUSED"){document.getElementById("videoPlayPause").style.backgroundPosition = "-287px -70px";}" type="button">Play/Pause</button>
Anyone has done something like this?
In JavaScript, you just need to load the URL of the file you want to play into the player, like this.
<script>
jwplayer('yourPlayerDivId').setup({
file: 'track1.mp4'
});
</script>
Given you have a loaded playlist, you can access (play) any item in the playlist directly using the playerInstance.playlistItem(index) method.
This starts playback of the playlist item at the specified index - bearing in mind that the first item in the playlist would have an index of 0.
You should therefore be able to attach a click event to each corresponding 'Play Icon' which calls this method with an incremented index in order to access the associated playlist item.
BTW: Since JW7 the playerInstance.getState() reports the state as a lowercase string...

GroundOverlay And TimeSpan On Embedded Google Earth

Am attempting to add a ground overlay to a Google Earth embed. The ground overlay has a series of six transparent gif images -- the URLs of which are dynamically added to a KML file. Only question is -- now how do I add the ground overlay using ge.createGroundOverlay('') when I have no 'icon' -- it's a URL. Tried to add it using a network link, but all six images are thrown on there and there is no slider to animate them.
Take a look the tutorial and code examples:
https://developers.google.com/earth/documentation/geometries#groundoverlay
To ensure animation works you must set the time elements of the groundOverlay: timeSpan or timeStamp.
See https://developers.google.com/earth/documentation/time
Here's snippet of code to create a ground overlay in Google Earth API with a URL:
// Create the GroundOverlay
var groundOverlay = ge.createGroundOverlay('');
// Specify the image path and assign it to the GroundOverlay
var icon = ge.createIcon('');
icon.setHref("http://www.google.com/logos/earthday08.gif");
groundOverlay.setIcon(icon);
var timeSpan = ge.createTimeSpan('');
timeSpan.getBegin().set('2009-01-01T17:00:00Z');
timeSpan.getEnd().set('2009-01-01T18:00:00Z');
groundOverlay.setTimePrimitive(timeSpan)
// Specify the geographic location
var latLonBox = ge.createLatLonBox('');
latLonBox.setBox(48.80, 48.75, -121.77, -121.85, 0);
groundOverlay.setLatLonBox(latLonBox);
// Add the GroundOverlay to Earth
ge.getFeatures().appendChild(groundOverlay);
If you're adding the GroundOverlay via a NetworkLink then the URL of the NetworkLink must be to the KML which includes the GroundOverlay and the associated URL to overlay image.
See https://developers.google.com/earth/documentation/kml#kmlnetworklink
var link = ge.createLink('');
var href = 'http://code.google.com/'
+ 'apis/earth/documentation/samples/kml_example.kml'
link.setHref(href);
var networkLink = ge.createNetworkLink('');
networkLink.set(link, true, true); // Sets the link, refreshVisibility, and flyToView
ge.getFeatures().appendChild(networkLink);

Resources