Failamp is a simple audio & video mediaplayer implemented in Python, using the built-in Qt playlist and media handling features. Syncmate expert for mac. It is modelled, very loosely on the original Winamp, although nowhere near as complete (hence the fail).
This is a collection of cool things to do with dual monitors that will increase your efficiency and creativity. Here are a few tips that I’ve learned through the years while working with multiple monitor setups. Feel free to add additional recommendations in the comments below Use Secondary Monitor for Remote Desktop Session Enable the. Winamp was the go-to program back when it was first released and a lot of years thereafter. The music player had a lot to offer back then, thanks to its great list of features, plug-ins and skins support. AOL acquired the Winamp team and technology in 1999 and things started to go downhill from then ever since. Internet Archive - The Internet Archive lets you preview winamp skins and listen to audio tracks using Webamp; Winampify.io - An online Spotify client using Webamp; Webamp Desktop - An Electron app version of Webamp; 98.js.org - A Windows 98 clone in JavaScript; winxp.now.sh - A Windows XP clone in JavaScript with React.
The Main Window
Is there any program for linux that will do everything that winamp does? I want something that will play any music or video files i throw at it, assuming i install the proper codec. A winamp-like feel would be nice but i don't really care that much. Anybody know of anything?
The main window UI was built using Qt Designer. The screenshot below shows the constructed layout, with the default colour scheme as visible within Designer.
Mediaplayer Design in Qt Designer
The layout is constructed in a QVBoxLayout
which in turn contains the playlist view (QListView
) and two QHBoxLayout
horizontal layouts which contain the time slider and time indicators and the control buttons respectively.
Winamp Clone Windows
Player
First we need to setup the Qt media player controller QMediaPlayer
. This controller handles load and playback of media files automatically, we just need to provide it with the appropriate signals.
We create a persistent player which we'll use globally. We setup an error handler by connecting our custom erroralert
slot to the error signal.
The generic media player controls can all be connected to the player directly, using the appropriate slots on self.player
.
We also have two slots for volume control and time slider position. Updating either of these will alter the playback automatically, without any handling on by us.
Finally we connect up our timer display methods to the player position signals, allowing us to automatically update the display as the play position changes.
When you drag the slider, this sends a signal to update the play position, which in turn sends a signal to update the time display. Chaining operations off each other allows you to keep your app components independent, one of the great things about signals.
Winamp Clone Linux
Qt Multimedia also provides a simple playlist controller. This does not provide the widget itself, just a simple interface for queuing up tracks (we handle the display using our own QListView
).
Playlist
Helpfully, the playlist can be passed to the player, which wil then use it to automatically select the track to play once the current one is complete.
The previous and next control buttons are connected to the playlist and will perform skip/restart/back as expected (all handled by QMediaPlaylist
). Because the playlist is connected to the player, this will automatically trigger the player to play the appropriate track.
The display of the playlist is handled by a QListView
object. This is a view component from Qt's model/view architecture, which is used to efficiently display data held in data models. In our case, we are storing the data in a playlist object QMediaPlaylist
from the Qt Multimedia module.
The PlaylistModel
is our custom model for taking data from the QMediaPlaylist
and mappingit to the view. We instantiate the model and pass it into our view.
Opening and dropping
We have a single file operation — open a file — which adds the file to the playlist. We also accept drag and drop, which is covered later.
Video
Finally, we add the viewer for video playback. If we don't add this the player will still playvideos, but just play the audio component. Video playback is handled by a specific QVideoWidget
. To enable playback we just pass this widget to the players .setVideoOutput
method.
Finally we just enable the toggles for the viewer to show/hide on demand.
Playlist model
As mentioned we're using a QListView
object from Qt's model/view architecture for playlist display, with data held in the QMediaPlaylist
. Since the data store is already handled for us, all we need to handle is the mapping from the playlist to the view.
In this case the requirements are pretty basic — we need:
- a method
rowCount
to return the total number of rows in the playlist, via.mediaCount()
- a method
data
which returns data for a specific row, in this case we're only displaying the filename
You could extend this to access media file metadata and show the track name instead.
By storing a reference to the playlist in __init__
the can get the other data easily at any time. Changes to the playlist in the application will be automatically reflected in the view.
The playlist and the player can handle track changes automatically, and we have the controls for skipping. However, we also want users to be able to select a track to play in the playlist, and we want the selection in the playlist view to update automatically as the tracks progress.
For both of these we need to define our own custom handlers. The first is for updating the playlist position in response to playlist selection by the user —
The next is to update the selection in the playlist as the track progresses. We specifically check for -1
since this value is sent by the playlist when there are not more tracks to play — either we're at the end of the playlist, or the playlist is empty.
Drag, drop and file operations
We enabled drag and drop on the main window by setting self.setAcceptDrops(True)
. With this enabled, the main window will raise the dragEnterEvent
and dropEvent
events when we perform drag-drop operations.
This enter/drop duo is the standard approach to drag-drop in desktop UIs. The enter event recognises what is being dropped and either *accepts* or *rejects*. Only if accepted can a drop occur.
The dragEnterEvent
checks whether the dragged object is droppable on our application. In this implementation we're very lax — we only check that the drop is file (by path). By default QMimeData
has checks built in for html, image, text and path/URL types, but not audio or video. If we want these we would have to implement them ourselves.
We could add a check here for specific file extension based on what we support.
The dropEvent
iterates over the URLs in the provided data, and adds them to the playlist.If we're not playing, dropping the file triggers autoplay from the newly added file.
The single operation defined is to open a file, which adds it to the current playlist. We predefine a number of standard audio and video file types — you can easily add more, as long as they are supported by the QMediaPlayer
controller, they will work fine.
Position duration
The QMediaPlayer
controller emits signals when the current playback duration and position are updated. The former is changed when the current media being played changes, e.g. when we progress to the next track. The second is emitted repeatedly as the play position updates during playback.
Both receive an int64
(64 bit integer) which represents the time in milliseconds. This same scale is used by all signals so there is no conversion between them, and we can simply pass the value to our slider to update.
Winamp Clone
One slightly tricky thing occurs where we update the slider position. We want to update the slider as the track progresses, however updating the slider triggers the update of the position (so the user can drag to a position in the track). This can trigger weird behaviour and a possible endless loop.
Winamp Clone Linux
To work around it we just block the signals while we make the update, and re-enable the after.
Timer
Finally, we need a method to convert a time in milliseconds in to an h:m:s
or m:s
display. For this we can use a series of divmod
calls with the milliseconds for each time division. This returns the number of complete divisions (div
) and the remainder (mod
). The slight tweak is to only show the hour part when the time is longer than an hour.
If you try this on Windows you may notice that the duration reported is incorrect. This is because of an issue with the legacy DirectShow media driver on Windows, which is unfortunately enabled by default. If you switch to windowsmediafoundation
instead you get accurate duration reporting and better media file support. Usually an easy choice. To enable it, just add the following to your application, somewhere before you create the QApplication
instance. os.environ['QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation'
You'll need to import os
first. For more information, see the Qt documentation on Windows multimedia.
Video viewer
The video viewer is a simple QMainWindow
with the addition of a toggle handler to show/display the window. We also add a hook into the closeEvent
to update the toggle button, while overriding the default behaviour — closing the window will not actually close it, just hide it.
Styling the windows
To mimic the style of Winamp (badly) we're using the Fusion application style as a base, then applying a dark theme. The Fusion style is nice Qt cross-platform application style. Thedark theme has been borrowed from this Gist from user QuantumCD.
This covers all the elements used in this Failamp. If you want to use this is another app you may need to add additional CSS tweaks, like that added for QToolTip
.
This gives us the final result —
mediaplayer-demo.jpg
Suggestions for improvements
If you want to take the app further, here are some suggestions of things to do.
- Auto-displaying the video viewer when viewing video (and auto-hiding when not)
- Docking of windows so they can be snapped together — like the original Winamp.
- Graphic equalizer/display —
QMediaPlayer
does provide a stream of the audio data which is playing. Withnumpy
for FFT we should be able to create a nice nice visual.