Compare commits

...

258 Commits

Author SHA1 Message Date
Ed Rogalsky
46f72f66f3 minor post merge hacks 2014-01-10 17:45:06 +01:00
Ed Rogalsky
a2379633d9 Merge branch 'master' into feature/jack
Conflicts:
	src/abstractclipitem.cpp
	src/abstractclipitem.h
	src/abstractgroupitem.cpp
	src/abstractgroupitem.h
	src/abstractmonitor.h
	src/archivewidget.cpp
	src/clipitem.cpp
	src/clipmanager.cpp
	src/clipproperties.cpp
	src/clipproperties.h
	src/clipstabilize.cpp
	src/clipstabilize.h
	src/commands/razorclipcommand.cpp
	src/commands/razorclipcommand.h
	src/customruler.cpp
	src/customtrackview.cpp
	src/customtrackview.h
	src/docclipbase.cpp
	src/docclipbase.h
	src/doubleparameterwidget.cpp
	src/dvdwizard.cpp
	src/dvdwizard.h
	src/dvdwizardchapters.cpp
	src/dvdwizardmenu.cpp
	src/dvdwizardmenu.h
	src/dvdwizardvob.cpp
	src/effectstack/collapsibleeffect.cpp
	src/graphicsscenerectmove.cpp
	src/jogshuttle.cpp
	src/kdenlive.desktop
	src/kdenlive.notifyrc
	src/kdenlivedoc.cpp
	src/kdenlivedoc.h
	src/keyframehelper.cpp
	src/mainwindow.cpp
	src/mainwindow.h
	src/markerdialog.cpp
	src/monitor.cpp
	src/monitor.h
	src/monitormanager.cpp
	src/monitormanager.h
	src/onmonitoritems/onmonitorcornersitem.cpp
	src/onmonitoritems/onmonitorrectitem.cpp
	src/projectlist.cpp
	src/projecttree/meltjob.h
	src/projecttree/proxyclipjob.cpp
	src/renderer.cpp
	src/renderer.h
	src/renderwidget.cpp
	src/renderwidget.h
	src/scopes/audioscopes/audiospectrum.cpp
	src/scopes/audioscopes/spectrogram.cpp
	src/titlewidget.cpp
	src/transition.cpp
	src/transitionsettings.cpp
	src/videoglwidget.cpp
	src/videoglwidget.h
	thumbnailer/westleypreview.desktop
2014-01-10 17:16:05 +01:00
Ed Rogalsky
cb43038a7f Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-05-05 15:51:18 +02:00
Pino Toscano
c89f6b3879 Remove erroneous double-quotes around %c in Exec line 2013-05-05 15:46:28 +02:00
Ed Rogalsky
68e53bfef2 audio to video frame number conversion implemented like xjadeo
ala R. Gareus
2013-05-04 20:04:21 +02:00
Ed Rogalsky
e5c206765e fix jack seeking problems with new mlt purge implementation 2013-05-04 19:55:10 +02:00
Montel Laurent
5bb198126e Initialize variable 2013-05-03 22:52:03 +02:00
Jean-Baptiste Mardelle
38628dd8a1 Fix some problems with transitions keyframes 2013-04-29 18:33:31 +02:00
Ed Rogalsky
f4f42c4b21 fix jackless build 2013-04-23 18:28:01 +02:00
Ed Rogalsky
2ee712f9e2 disable forward/rewind button if slaved to jack
minor code cleanup
2013-04-23 17:54:30 +02:00
Script Kiddy
2747a209dc SVN_SILENT made messages (.desktop file) 2013-04-22 21:53:36 +02:00
Script Kiddy
519dce4464 SVN_SILENT made messages (.desktop file) 2013-04-22 21:47:36 +02:00
Ed Rogalsky
8ed5bce13f set next dev version 2013-04-22 21:42:13 +02:00
Ed Rogalsky
0d341548a5 disable fast reverse/forward playing if jack transport is enabled 2013-04-21 22:31:43 +02:00
Ed Rogalsky
beb0f220dd Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-04-14 11:36:47 +02:00
Ed Rogalsky
235dfe6bff make jack icons more attractive 2013-04-13 22:26:21 +02:00
Jean-Baptiste Mardelle
629b0cb6de Fix scopes: http://kdenlive.org/mantis/view.php?id=3052 2013-04-13 21:31:16 +02:00
Jean-Baptiste Mardelle
45b0b4dc6c update changelog for 0.9.6 2013-04-06 21:21:19 +02:00
Jean-Baptiste Mardelle
0478cf276a Finally get ready for 0.9.6 release 2013-04-06 21:16:20 +02:00
Ed Rogalsky
bd3fcb13bb minor name changes 2013-04-06 16:51:05 +02:00
Ed Rogalsky
b710e8548d minor logical name fixes 2013-04-04 18:39:38 +02:00
Ed Rogalsky
2682ac5f8c fix start/stop icon toggle when slaved to jack 2013-04-04 18:13:13 +02:00
Ed Rogalsky
80291b4246 minor icon update 2013-04-04 17:12:42 +02:00
Ed Rogalsky
d9fff06f74 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-04-04 16:10:34 +02:00
Ed Rogalsky
ca5587224b add m icon for jack monitoring action 2013-04-04 16:07:22 +02:00
Jean-Baptiste Mardelle
f3bca8009f Add reverse clip to clip actions: http://kdenlive.org/mantis/view.php?id=2933 2013-04-04 15:28:32 +02:00
Ed Rogalsky
1b5f18dfbc Merge remote-tracking branch 'origin/v0.9' into feature/jack
Conflicts:
	src/mainwindow.cpp
	src/mainwindow.h
2013-04-03 22:07:09 +02:00
Jean-Baptiste Mardelle
08614d7be6 Try to fix font GUI issue: http://www.kdenlive.org/mantis/view.php?id=3049 2013-04-03 00:03:54 +02:00
Jean-Baptiste Mardelle
74d4a56cea Show project duration in status bar 2013-04-02 17:52:55 +02:00
Ed Rogalsky
691dbadbe8 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-04-01 21:18:41 +02:00
Jean-Baptiste Mardelle
b4cd8e5882 Spacer tool should never allow to move clips before another clip, fixes timeline corruption 2013-04-01 14:56:10 +02:00
Jean-Baptiste Mardelle
96d873bb2b Correctly handle unsupported filters 2013-04-01 12:26:18 +02:00
Jean-Baptiste Mardelle
8ca44cc603 Remove space from filename start / end in render dialog: http://kdenlive.org/mantis/view.php?id=3018 2013-04-01 12:08:45 +02:00
Ed Rogalsky
de22d39e22 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-04-01 11:37:03 +02:00
Ed Rogalsky
c16e330840 show error message in explicit jack mode if jackd is not running
some code cleanup in init code
2013-04-01 11:20:41 +02:00
Jean-Baptiste Mardelle
4dd620b9c3 Fix possible crash when changing speed effect 2013-03-31 22:25:24 +02:00
Jean-Baptiste Mardelle
910e49c805 Remove duplicate colortap filter: http://kdenlive.org/mantis/view.php?id=3010 2013-03-31 22:08:20 +02:00
Jean-Baptiste Mardelle
0097caf273 Fix vstab angle parameter: http://kdenlive.org/mantis/view.php?id=2955 2013-03-31 21:11:11 +02:00
Jean-Baptiste Mardelle
f2e2aa0b76 Make audio / video bitrate easily configurable in custom render profiles: http://kdenlive.org/mantis/view.php?id=3012 2013-03-31 20:43:25 +02:00
Ed Rogalsky
f8cc04f775 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-03-31 17:28:28 +02:00
Ed Rogalsky
774302c6eb fix jackless build
rename option WITH_Jack. It is set by find_package -> condition
was always true.
2013-03-31 17:27:50 +02:00
Jean-Baptiste Mardelle
f663bdd328 Fix playlist corruption & crash when moving clip: http://kdenlive.org/mantis/view.php?id=3046 2013-03-31 11:48:01 +02:00
Ed Rogalsky
a5c32c8155 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-03-30 23:39:07 +01:00
Jean-Baptiste Mardelle
ab3b5e2ca7 Add more standard mpeg4/aac as rendering profile 2013-03-30 22:41:15 +01:00
Jean-Baptiste Mardelle
2af433083b Fix moving transition sometimes losing properties: http://kdenlive.org/mantis/view.php?id=3025 2013-03-30 22:06:25 +01:00
Jean-Baptiste Mardelle
bf992aef55 Fix crash in title widget: http://kdenlive.org/mantis/view.php?id=3032 2013-03-30 21:13:02 +01:00
Ed Rogalsky
7095920970 jack refactoring + cleanup - part3 2013-03-29 21:48:04 +01:00
Ed Rogalsky
39b7a78218 jack refactoring + cleanup - part2 2013-03-29 18:23:07 +01:00
Ed Rogalsky
d2cce9bf4b jack refactoring + cleanup - part1 2013-03-28 18:00:49 +01:00
Ed Rogalsky
2515ab2622 findjack cmake script added 2013-03-23 16:31:33 +01:00
Ed Rogalsky
5330aaa9f0 Merge remote-tracking branch 'origin/v0.9' into feature/jack
Conflicts:
	src/monitormanager.h
2013-03-23 14:34:45 +01:00
Ed Rogalsky
b378528894 synchronize v0.9 branch with master 2013-03-23 13:51:06 +01:00
Jean-Baptiste Mardelle
dca8b03ba3 Move mlt interlace and rescale into main menu 2013-03-23 13:42:19 +01:00
Jean-Baptiste Mardelle
142e3e41d6 Implement deinterlacer and rescale options for MLT consumer 2013-03-23 13:42:04 +01:00
Ed Rogalsky
b3391222fa update config hooks implemented for renderers 2013-03-23 12:56:27 +01:00
Ed Rogalsky
04b5d88d68 syncdiffmaxvalue settable in config
todo: update config hook
2013-03-21 21:16:38 +01:00
Ed Rogalsky
b381719994 syncaction enum added 2013-03-21 20:10:31 +01:00
Ed Rogalsky
532be6179d jack playback sync monitoring enable/disable logic + action implemented
todo: cleanup code + sync diff value in config
2013-03-17 11:45:29 +01:00
Ed Rogalsky
9e46e2872d some progress on jack transport monitoring
monitoring enable/disable button slots added
2013-03-11 18:53:01 +01:00
Jean-Baptiste Mardelle
a01e37d60c Fix crash when doing clip resize and clicking item quickly 2013-03-04 20:53:58 +01:00
Jean-Baptiste Mardelle
5eaf1c602a Fix wrong group moving when groups overlap 2013-03-04 19:59:55 +01:00
Ed Rogalsky
f9c8e5d62a Merge branch 'feature/jack' into feature/jack-mon 2013-03-02 17:36:04 +01:00
Ed Rogalsky
4b3cd3c847 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-03-02 17:35:21 +01:00
Jean-Baptiste Mardelle
f7573287d1 Disable monitor scene when transition is unselected 2013-03-01 21:23:25 +01:00
Jean-Baptiste Mardelle
5948ee0151 Remove useless include 2013-02-27 20:53:12 +01:00
Jean-Baptiste Mardelle
b4633f1d6b * Set document as modified when changing project metadata: http://kdenlive.org/mantis/view.php?id=2996
* Automatic recovery of corrupted files produced by Kdenlive 0.9.4
2013-02-27 20:53:02 +01:00
Jean-Baptiste Mardelle
fe5586ec6d Don't corrupt project when adding a title clip and a transition already is in place 2013-02-25 15:22:08 +01:00
Ed Rogalsky
9bcec2a7dd Merge branch 'feature/jack' into feature/jack-mon 2013-02-24 19:57:29 +01:00
Ed Rogalsky
d431251c58 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-02-24 19:55:25 +01:00
Jean-Baptiste Mardelle
31012828bb Fix monitor displaying corrupt image on startup: http://www.kdenlive.org/mantis/view.php?id=2992 2013-02-24 18:50:20 +01:00
Jean-Baptiste Mardelle
7c9855c7b5 Switch to rgb24 instead of rbg24a when requesting frames from MLT. Fixes: http://kdenlive.org/mantis/view.php?id=2990 2013-02-24 18:20:39 +01:00
Jean-Baptiste Mardelle
952681475b Fix clip monitor not activated on open: http://kdenlive.org/mantis/view.php?id=2992 2013-02-24 16:37:15 +01:00
Ed Rogalsky
28ea8dd68e Merge branch 'feature/jack' into feature/jack-mon 2013-02-23 18:26:29 +01:00
Ed Rogalsky
ca5c8bf210 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-02-23 18:05:44 +01:00
Jean-Baptiste Mardelle
10d1c827c1 Merge branch 'v0.9' of git://anongit.kde.org/kdenlive into v0.9 2013-02-23 17:51:50 +01:00
Jean-Baptiste Mardelle
066d37fc43 New Median filter from Marko Cebokli 2013-02-23 17:51:10 +01:00
Jean-Baptiste Mardelle
1efbcfc92a Fix possible crash in monitor scene 2013-02-23 17:50:23 +01:00
Ed Rogalsky
2e654bcec3 cleanup unused jogshuttle code 2013-02-23 17:32:29 +01:00
Jean-Baptiste Mardelle
06a8be51bc Merge branch 'v0.9' of git://anongit.kde.org/kdenlive into v0.9 2013-02-23 17:18:54 +01:00
Jean-Baptiste Mardelle
ce50b7deb5 Fix cutting of geometry keyframes (like pan & zoom): http://kdenlive.org/mantis/view.php?id=2991 2013-02-23 17:18:40 +01:00
Ed Rogalsky
ffd37b37a2 optimize jogshuttle code 2013-02-23 16:58:10 +01:00
Jean-Baptiste Mardelle
32813818d1 Fix metadata not properly set for project: http://kdenlive.org/mantis/view.php?id=2996 2013-02-23 15:41:58 +01:00
Jean-Baptiste Mardelle
81e7614799 Fix "Clip in project tree" in groups: http://kdenlive.org/mantis/view.php?id=2781 2013-02-23 09:04:10 +01:00
Jean-Baptiste Mardelle
256767b764 Fix keyframes when undoing a clip / group cut 2013-02-23 08:21:36 +01:00
Jean-Baptiste Mardelle
e467a6a777 Fix keyframes cutting (first part) 2013-02-23 08:21:36 +01:00
Jean-Baptiste Mardelle
b67fb9481a Fix double click in a timeline clip to add keyframe 2013-02-23 08:21:35 +01:00
Ed Rogalsky
f205a50f86 basic jack transport monitoring implemented 2013-02-17 20:54:37 +01:00
Ed Rogalsky
53fa655121 Merge branch 'feature/jack' into feature/jack-mon 2013-02-17 18:44:49 +01:00
Ed Rogalsky
40d9edcf5c Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-02-17 18:44:30 +01:00
Jean-Baptiste Mardelle
c6b1beff20 Fix transcoding (broken by last commit) 2013-02-17 18:18:34 +01:00
Ed Rogalsky
fa086ec448 Merge branch 'feature/jack' into feature/jack-mon 2013-02-17 16:47:03 +01:00
Ed Rogalsky
6129f0b16e Merge remote-tracking branch 'origin/v0.9' into feature/jack
Conflicts:
	src/monitormanager.cpp
	src/renderer.cpp
2013-02-17 16:33:35 +01:00
Ed Rogalsky
0436f22757 first ideas how to implement jack sync monitoring 2013-02-17 14:46:14 +01:00
Jean-Baptiste Mardelle
8c96562a49 Warn before overwriting stabilized clip 2013-02-17 14:33:24 +01:00
Jean-Baptiste Mardelle
c030d42f97 Fix monitor focus on ruler wheel event 2013-02-17 11:59:24 +01:00
Jean-Baptiste Mardelle
6e93ff5fe7 Try to fix monitor confusion: http://kdenlive.org/mantis/view.php?id=2986 2013-02-17 11:56:00 +01:00
Jean-Baptiste Mardelle
029d2db59a Fix unnecessary refresh of effect stack, set effect param description as tooltip 2013-02-16 23:46:37 +01:00
Jean-Baptiste Mardelle
95c1b91921 Fix some MLT effects (Mono to Stereo was showing twice the "To" param) 2013-02-16 21:04:02 +01:00
Jean-Baptiste Mardelle
ed31bc0d0d Try to avoid locale errors when converting double 2013-02-16 20:08:35 +01:00
Jean-Baptiste Mardelle
fc8ccb61a4 Fix proxy of playlist aspect ratio broken on some locales 2013-02-16 18:56:05 +01:00
Ed Rogalsky
c8a693b178 add jack sound in opengl mode
it is dramatic slow
2013-02-15 19:02:50 +01:00
Ed Rogalsky
b90c5ccfbf toggle jack icon added 2013-02-14 22:18:16 +01:00
Ed Rogalsky
e3bf2a0eda shortcut added for enable/disable jack transport button 2013-02-14 16:00:29 +01:00
Ed Rogalsky
958cb77341 fix regression in jack init code 2013-02-14 14:13:42 +01:00
Ed Rogalsky
f3efa339af fix concurrency crash in opengl mode 2013-02-13 19:39:32 +01:00
Ed Rogalsky
0496d7f664 fix crash if jack transport is enabled and monitor are switched to fast 2013-02-13 17:00:29 +01:00
Ed Rogalsky
6bccc67355 stop jack playback on reaching eof 2013-02-13 13:29:22 +01:00
Ed Rogalsky
70c198ad88 Merge remote-tracking branch 'origin/v0.9' into feature/jack 2013-02-13 12:36:38 +01:00
Jean-Baptiste Mardelle
a121e94dd9 Make monitor ruler slightly bigger so it's easier to click for seeking 2013-02-12 13:55:15 +01:00
Jean-Baptiste Mardelle
6c8b8a6e03 Fix Coverity #980671 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
f43ef86a0f Fix Coverity #980672 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
2abbfe2ef0 Fix Coverity #980673 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
0438a0682c Fix Coverity #980677 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
12cd43cfd4 Fix Coverity #980678 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
8afe094faa Fix Coverity #980679 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
c3cc3abc21 Fix Coverity #980680 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
e5752ab314 Fix Coverity #980681 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
a84ecc52ea Fix Coverity #980682 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
1ddbf38fad Fix Coverity #980683 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
88fab6e0fd Fix Coverity #980684 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
8c55aa37ab Fix Coverity #980686 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
2dd1db6676 Fix Coverity #980687 2013-02-12 01:44:25 +01:00
Jean-Baptiste Mardelle
bc55890a55 Fix Coverity #980688 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
ed37f7bad2 Fix Coverity #980690 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
39465e1126 Fix Coverity #980691 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
cabd83dcf4 Fix Coverity #980692 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
79634a597c Fix Coverity #980693 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
d06b38d7e6 Fix Coverity #980694 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
f50634a4de Fix Coverity #980695 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
a44e4ced83 Fix Coverity #980696 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
0088750869 Fix Coverity #980697 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
bc95cc02c1 Fix Coverity #980698 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
aa58692458 Fix Coverity #980699 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
77b5c4becd Fix Coverity #980700 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
bea3e057f8 Fix Coverity #980701 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
3701617d75 Fix Coverity #980702 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
b3ee29e687 Fix Coverity #980703 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
9256029a01 Fix Coverity #980704 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
cfedab39f0 Fix Coverity #980705 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
43dcc8bcec Show clip size & fps in project tree tooltip 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
2e19960808 Fix Coverity #980706 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
456efd6445 Fix Coverity #980712 2013-02-12 01:44:24 +01:00
Jean-Baptiste Mardelle
fe9248af58 Fix Coverity #980707 2013-02-12 01:44:23 +01:00
Jean-Baptiste Mardelle
28406cbc78 Fix crash when opening invalid file from command line: http://kdenlive.org/mantis/view.php?id=2984 2013-02-11 17:55:28 +01:00
Ed Rogalsky
d855ca0cca Merge remote-tracking branch 'origin/v0.9' into feature/jack
Conflicts:
	src/monitormanager.cpp
2013-02-11 14:35:05 +01:00
Jean-Baptiste Mardelle
fde4c3affb Correctly refresh transition widget when resizing a transition, move last keyframe when expanding the transition 2013-02-11 12:00:01 +01:00
Jean-Baptiste Mardelle
382b731ef8 Only use exiftool / ML on video clips 2013-02-11 10:01:10 +01:00
Jean-Baptiste Mardelle
bc24dd0547 Mark THM metadata as ExifTool, not ML 2013-02-11 09:12:45 +01:00
Jean-Baptiste Mardelle
3c9c2762bc Fix DVD chapters broken when using an intro movie, show chapters in monitor ruler 2013-02-10 01:52:17 +01:00
Jean-Baptiste Mardelle
798becb879 Some cleanup in DVD wizard on menu button move 2013-02-10 01:23:57 +01:00
Jean-Baptiste Mardelle
00118ecfed Fix small UI bugs in title widget: http://kdenlive.org/mantis/view.php?id=1257 2013-02-09 21:56:44 +01:00
Jean-Baptiste Mardelle
3e0341727e Fix timeline seek sometimes not refreshing on last frame of the seek, small update for monitor ruler colors 2013-02-09 19:49:48 +01:00
Jean-Baptiste Mardelle
195ea6b6ef Allow retrieval of metadata created by Magic Lantern for canon cams 2013-02-09 16:53:31 +01:00
Jean-Baptiste Mardelle
3ac7926509 Small cleanup in render widget, fix error message (no matching profile) sometimes appearing when it should not 2013-02-09 10:32:09 +01:00
Jean-Baptiste Mardelle
e687ac0352 Fix effect's keyframe line not appearing on project load 2013-02-08 18:59:02 +01:00
Jean-Baptiste Mardelle
a0d3941b85 Fix monitor timecode not visible with some window decorations:
http://kdenlive.org/mantis/view.php?id=2979
2013-02-08 18:07:25 +01:00
Jean-Baptiste Mardelle
0ec4289e12 Fix moving guide bug 2013-02-04 19:02:49 +01:00
Jean-Baptiste Mardelle
61c33cd043 Fix some clips metadata corrupting project file: http://kdenlive.org/mantis/view.php?id=2976 2013-02-04 16:15:18 +01:00
Jean-Baptiste Mardelle
62fc36de3a Fix possible crash on track deletion: http://kdenlive.org/mantis/view.php?id=2967 2013-02-04 13:07:07 +01:00
Jean-Baptiste Mardelle
599909d0e4 Don't convert number when not necessary 2013-02-02 22:25:31 +01:00
Jean-Baptiste Mardelle
1cb68ab635 Fix compilation on OSX (moc issue) 2013-02-01 15:36:05 +01:00
Jean-Baptiste Mardelle
5937575100 Fix keyframe line not appearing in timeline until we modify a keyframe 2013-02-01 13:38:29 +01:00
Jean-Baptiste Mardelle
e5e694dff0 Fix keyframe line not painted over clips in timeline 2013-02-01 13:06:49 +01:00
Jean-Baptiste Mardelle
d850307c9a Small fix for clipproperties dialog (improve column resizing in metadata and other properties) 2013-01-30 01:43:03 +01:00
Jean-Baptiste Mardelle
4f4107b7ed Merge branch 'master' into v0.9 2013-01-29 11:12:07 +01:00
Ed Rogalsky
7827dd337b Merge branch 'master' into feature/jack 2013-01-06 14:12:51 +01:00
Ed Rogalsky
c5bc2ae79a Merge remote-tracking branch 'origin/master' into feature/jack 2013-01-05 22:21:53 +01:00
Ed Rogalsky
9d1821169d Merge remote-tracking branch 'origin/master' into feature/jack 2013-01-05 22:17:59 +01:00
Ed Rogalsky
0e4afc2943 Merge branch 'master' into feature/jack
Conflicts:
	src/renderer.cpp
2013-01-05 14:19:14 +01:00
Ed Rogalsky
3e3ba91918 Merge remote-tracking branch 'origin/master' into feature/jack 2013-01-01 16:12:24 +01:00
Ed Rogalsky
6563c7d774 Merge remote-tracking branch 'origin/master' into feature/jack
Conflicts:
	src/monitor.cpp
	src/renderer.cpp
2012-12-31 13:44:48 +01:00
Ed Rogalsky
af159d08a5 Merge remote-tracking branch 'origin/master' into feature/jack 2012-12-29 12:29:35 +01:00
Ed Rogalsky
713ff1305f Merge remote-tracking branch 'origin/master' into feature/jack 2012-12-28 22:36:06 +01:00
Ed Rogalsky
c38e2a4b64 Merge remote-tracking branch 'origin/master' into feature/jack 2012-12-28 18:23:53 +01:00
Ed Rogalsky
bb1b54efbd Merge remote-tracking branch 'origin/master' into feature/jack
Conflicts:
	src/renderer.cpp
2012-12-28 16:07:35 +01:00
Ed Rogalsky
f5d066e640 Merge branch 'master' into feature/jack 2012-12-28 13:29:23 +01:00
Ed Rogalsky
7286e6bbfe jack seeking works again 2012-12-27 14:18:02 +01:00
Ed Rogalsky
f44e280f07 Merge remote-tracking branch 'origin/master' into feature/jack 2012-12-26 20:51:23 +01:00
Ed Rogalsky
4ec7e33d13 Merge remote-tracking branch 'origin/master' into feature/jack 2012-12-26 14:06:03 +01:00
Ed Rogalsky
d7b73a8940 Merge branch 'master' into feature/jack
Conflicts:
	src/renderer.cpp
2012-12-22 23:23:26 +01:00
Ed Rogalsky
ec3d586dd2 Merge branch 'master' into feature/jack 2012-12-11 19:48:03 +01:00
Ed Rogalsky
1fd99b2bea Merge branch 'master' into feature/jack 2012-12-08 14:06:14 +01:00
Ed Rogalsky
a5e26b7450 jackless build works again 2012-12-02 17:50:15 +01:00
Ed Rogalsky
eb31061223 Merge branch 'master' into feature/jack 2012-12-02 16:10:31 +01:00
Ed Rogalsky
1027d24a85 some crashes fixed
now the jack toggle button works properly depending on the active
monitor
2012-12-02 16:06:49 +01:00
Ed Rogalsky
d7a1012232 jackdevice shutdown event added
close jackdevice safe if jackd aborts unexpected
2012-12-01 18:42:14 +01:00
Ed Rogalsky
8da0f0e570 Merge branch 'feature/jack-mon-event' into feature/jack 2012-11-28 22:44:35 +01:00
Ed Rogalsky
bd2f5b7d94 Merge branch 'master' into feature/jack 2012-11-28 22:42:07 +01:00
Ed Rogalsky
b467a5bcf0 jack toggle button works again 2012-11-28 22:37:31 +01:00
Ed Rogalsky
208203d4ee stopped/started event for rec_monitor 2012-11-28 22:09:01 +01:00
Ed Rogalsky
84b8184f91 first impl of controlled jack toggle button 2012-11-27 21:24:40 +01:00
Ed Rogalsky
b614e0429e bugfix resetSlavePerm 2012-11-27 19:12:05 +01:00
Ed Rogalsky
ea66901d0c more generic slave perm interface 2012-11-27 19:07:45 +01:00
Ed Rogalsky
970988acb4 replace old school defines with namespaced enums 2012-11-25 21:45:06 +01:00
Ed Rogalsky
b3dc6db630 jack build enabled 2012-11-23 15:53:35 +01:00
Ed Rogalsky
fcbbb78fd1 jackless build works again 2012-11-23 15:33:29 +01:00
Ed Rogalsky
053a3b4aee most of jack refactoring completed 2012-11-23 15:06:13 +01:00
Ed Rogalsky
6ddd3c58f7 jack device implemented 2012-11-23 13:51:03 +01:00
Ed Rogalsky
295356483d Merge branch 'master' into feature/jack 2012-11-22 19:48:18 +01:00
Ed Rogalsky
9287b050c7 Merge branch 'master' into feature/jack 2012-11-22 13:34:08 +01:00
Ed Rogalsky
0aecfd55f1 jack less build fixed 2012-11-21 16:04:22 +01:00
Ed Rogalsky
1967f92980 unnecessary transport calls removed
minor code cleanup + workaround for moc preprocessor problem
2012-11-21 15:12:35 +01:00
Ed Rogalsky
e7a961b5ec no buffer update while syncing 2012-11-21 14:54:49 +01:00
Ed Rogalsky
99d8b834ac noise while syncing removed 2012-11-21 14:28:23 +01:00
Ed Rogalsky
094eb7d607 jack audio device implemented 2012-11-21 00:02:46 +01:00
Ed Rogalsky
4e52df362c ringbuffers added 2012-11-20 19:44:24 +01:00
Ed Rogalsky
138d8b03b3 jack build enabled 2012-11-20 18:21:58 +01:00
Ed Rogalsky
e5290c8a58 Merge branch 'master' into feature/jack 2012-11-20 17:19:02 +01:00
Ed Rogalsky
390c76e78d jack less build enabled 2012-11-20 17:01:11 +01:00
Ed Rogalsky
fc574c4476 Merge branch 'master' into feature/jack 2012-11-18 16:28:19 +01:00
Ed Rogalsky
d2097f7e93 Merge branch 'master' into feature/jack 2012-11-17 10:58:59 +01:00
Ed Rogalsky
a8e3e3808d kdenlive looping in jack mode works completely now
implemented looping in jackslave because the consumer-paused event does
not work properly if audio_off property is enabled and seeking is done
with zero speed (best seeking performance and smoothnest).
2012-11-16 16:34:15 +01:00
Ed Rogalsky
0f0174667a basic jack enabled looping implemented
kdenlive: play zone or loop zone feature
2012-11-15 18:35:50 +01:00
Ed Rogalsky
c4b42d2f39 Merge branch 'master' into feature/jack 2012-11-15 13:47:45 +01:00
Ed Rogalsky
a250c9e3e4 Merge branch 'master' into feature/jack 2012-11-13 07:01:45 +01:00
Ed Rogalsky
e5cd254489 make jack seeking just awesome 2012-11-13 06:52:29 +01:00
Ed Rogalsky
388f59a181 Merge branch 'master' into feature/jack 2012-11-10 18:56:12 +01:00
Ed Rogalsky
c24494ec5e don't round up in toVideoPosition function
do it like in ardour - truncate the rest. This improves the timecode
sync
2012-11-10 18:34:53 +01:00
Ed Rogalsky
9cb70f8336 seeking while playing implemented
major jack enabled playback features implemented
2012-11-10 15:18:10 +01:00
Ed Rogalsky
6566ed80d2 jack shutdown callback implemented
make kdenlive robust (no crash) against jackd shutdown
position conversion function added
2012-11-10 10:59:55 +01:00
Ed Rogalsky
454e2fc50a jack synced seeking while stopped
crash fixed
2012-11-09 07:41:14 +01:00
Ed Rogalsky
4121442268 basic jack transport sync implemented
todo fix crash
2012-11-08 08:10:23 +01:00
Ed Rogalsky
c08f3ceeba jack probe feature added
if jackd is running this is auto detected and the jack audio device is
set on starting in audio automatic mode
2012-11-07 21:39:48 +01:00
Ed Rogalsky
c76747d282 jack client name as parameter 2012-11-07 20:46:16 +01:00
Ed Rogalsky
04ec462b4f Merge branch 'master' into feature/jack 2012-11-07 19:40:40 +01:00
Ed Rogalsky
15afb87437 basic direct jack transport integration without mlt jack filter
after consulting Dan I decided to implement jack directly in kdenlive
because doing it in mlt caused to much trouble
2012-11-06 21:41:32 +01:00
Ed Rogalsky
f6bf704d93 Merge branch 'master' into feature/jack 2012-11-06 17:21:20 +01:00
Ed Rogalsky
0f78a3d97a code cleanup 2012-11-03 17:45:45 +01:00
Ed Rogalsky
e1f2a9fd5e initial jack implementation 2012-11-03 16:57:01 +01:00
Jean-Baptiste Mardelle
50451496ba Fix color selection widget when getting average color for a region 2012-06-20 11:01:31 +02:00
Jean-Baptiste Mardelle
9b72f1df9f Fix keyframes not correctly updated when resizing clip 2012-06-20 09:25:29 +02:00
Jean-Baptiste Mardelle
10246b5d17 Fix script rendering not working in some cases (resizing) 2012-06-20 00:01:27 +02:00
Jean-Baptiste Mardelle
b3ef3d6bba Fix pasting fade effect in a group 2012-06-19 22:21:15 +02:00
Jean-Baptiste Mardelle
20dce6e949 Fix effect group collapse state not saved 2012-06-19 11:03:45 +02:00
Jean-Baptiste Mardelle
ffaffc8d31 Fix fade effects 2012-06-19 01:25:54 +02:00
Jean-Baptiste Mardelle
10ad1edcda Fix crash when dragging some track effect 2012-06-14 09:14:08 +02:00
Jean-Baptiste Mardelle
77d8cca359 Fix pan & zoom effect (paste, edit after reloading project) 2012-06-13 00:08:28 +02:00
Jean-Baptiste Mardelle
4db534e109 update changelog for 0.9.x branch 2012-06-12 17:31:23 +02:00
Jean-Baptiste Mardelle
5257097d15 Color values in MLT should always contain alpha (0xRRGGBBAA):
http://kdenlive.org/mantis/view.php?id=2644
2012-06-12 17:24:38 +02:00
Jean-Baptiste Mardelle
eb19dab9a3 Fix broken keyframes when dropping an effect on another clip 2012-06-08 20:39:57 +02:00
Jean-Baptiste Mardelle
81ffc86247 Disable blackmagic support if no card found 2012-06-05 19:00:22 +02:00
Jean-Baptiste Mardelle
0021e7d518 * Get rid of custom video4linux header, use system header
* get rid of GPL2 files / rewrite v4l queries
2012-06-05 11:58:23 +02:00
Jean-Baptiste Mardelle
6b24f25d50 Set version to 0.9.2 2012-05-29 23:38:12 +02:00
Vincent PINON
6b9c3cb660 Titler: apply background color to the whole scene (scrolling titles more readable) 2012-05-29 08:08:47 +02:00
Vincent PINON
09efe0bca0 Allow deleting & moving multiple selected items 2012-05-29 08:08:17 +02:00
Jean-Baptiste Mardelle
fc88c34243 Getting ready for Kdenlive 0.9.1 2012-05-28 23:43:34 +02:00
Jean-Baptiste Mardelle
37b8773983 Fix firewire capture 2012-05-28 23:27:56 +02:00
Jean-Baptiste Mardelle
4fa2235ac5 Update FSF address 2012-05-28 09:47:15 +02:00
Jean-Baptiste Mardelle
a010eb0e39 Fix wrong locale when rendering:
http://kdenlive.org/mantis/view.php?id=2623
2012-05-28 09:00:36 +02:00
Jean-Baptiste Mardelle
c5b60ba999 Fix archive job never finishing when no external clips to archive 2012-05-27 18:52:20 +02:00
Jean-Baptiste Mardelle
cde2d7e3db Fix freeze on reloading a missing clip, don't reload twice missing clips that were found 2012-05-27 18:13:13 +02:00
Jean-Baptiste Mardelle
65d0c1f96a Fix editing clip crop start and fade effects lost when resizing clip:
http://kdenlive.org/mantis/view.php?id=2570
2012-05-27 12:18:00 +02:00
Jean-Baptiste Mardelle
6fbcf1b7dd Fix error in last commit 2012-05-26 18:16:33 +02:00
Jean-Baptiste Mardelle
4c60e68058 Fix i18n calls 2012-05-24 23:02:21 +02:00
Jean-Baptiste Mardelle
b1f3c36559 Fix track effect checkbox always disabled 2012-05-22 20:28:32 +02:00
Jean-Baptiste Mardelle
97571645de Fix broken slideshow:
http://kdenlive.org/mantis/view.php?id=2616
2012-05-20 20:08:44 +02:00
Jean-Baptiste Mardelle
051ddbf0d5 Fix crash on audio analysis (temporary fix):
http://kdenlive.org/mantis/view.php?id=2613
2012-05-19 12:53:27 +02:00
Jean-Baptiste Mardelle
419d8e22c7 Fix crash when opening stop motion widget:
http://kdenlive.org/mantis/view.php?id=2607
2012-05-17 11:09:41 +02:00
26 changed files with 1854 additions and 36 deletions

View File

@@ -0,0 +1,82 @@
# - Try to find jack-2.6
# Once done this will define
#
# JACK_FOUND - system has jack
# JACK_INCLUDE_DIRS - the jack include directory
# JACK_LIBRARIES - Link these to use jack
# JACK_DEFINITIONS - Compiler switches required for using jack
#
# Copyright (c) 2008 Andreas Schneider <mail@cynapses.org>
# Modified for other libraries by Lasse Kärkkäinen <tronic>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)
# in cache already
set(JACK_FOUND TRUE)
else (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
include(UsePkgConfig)
pkgconfig(jack _JACK_INCLUDEDIR _JACK_LIBDIR _JACK_LDFLAGS _JACK_CFLAGS)
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_JACK jack)
endif (PKG_CONFIG_FOUND)
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_path(JACK_INCLUDE_DIR
NAMES
jack/jack.h
PATHS
${_JACK_INCLUDEDIR}
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(JACK_LIBRARY
NAMES
jack
PATHS
${_JACK_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
if (JACK_LIBRARY AND JACK_INCLUDE_DIR)
set(JACK_FOUND TRUE)
set(JACK_INCLUDE_DIRS
${JACK_INCLUDE_DIR}
)
set(JACK_LIBRARIES
${JACK_LIBRARIES}
${JACK_LIBRARY}
)
endif (JACK_LIBRARY AND JACK_INCLUDE_DIR)
if (JACK_FOUND)
if (NOT JACK_FIND_QUIETLY)
message(STATUS "Found jack: ${JACK_LIBRARY}")
endif (NOT JACK_FIND_QUIETLY)
else (JACK_FOUND)
if (JACK_FIND_REQUIRED)
message(FATAL_ERROR "Could not find JACK")
endif (JACK_FIND_REQUIRED)
endif (JACK_FOUND)
# show the JACK_INCLUDE_DIRS and JACK_LIBRARIES variables only in the advanced view
mark_as_advanced(JACK_INCLUDE_DIRS JACK_LIBRARIES)
endif (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

View File

@@ -10,9 +10,11 @@ if(APPLE)
endif(APPLE)
macro_optional_find_package(Nepomuk)
macro_optional_find_package(QJSON)
macro_optional_find_package(Jack)
option(WITH_V4L "Build capture support with Video4Linux" ON)
option(WITH_JogShuttle "Build Jog/Shuttle support" ON)
option(WITH_JACK "Build Jack support" ON)
@@ -33,6 +35,12 @@ if(WITH_JogShuttle)
endif(HAVE_LINUX_INPUT_H)
endif(WITH_JogShuttle)
if(WITH_JACK)
if(JACK_FOUND)
set(BUILD_Jack TRUE)
endif(JACK_FOUND)
endif(WITH_JACK)
macro_log_feature(QT_QTOPENGL_FOUND
"QtOpenGL"
"Qt bindings for the OpenGL library"
@@ -282,6 +290,10 @@ if(BUILD_JogShuttle)
)
endif(BUILD_JogShuttle)
if(BUILD_Jack)
list(APPEND kdenlive_SRCS jackdevice.cpp)
endif(BUILD_Jack)
kde4_add_kcfg_files(kdenlive_SRCS kdenlivesettings.kcfgc)
qt4_add_dbus_adaptor(kdenlive_SRCS
org.kdenlive.MainWindow.xml
@@ -376,6 +388,12 @@ if(BUILD_JogShuttle)
add_definitions(-DUSE_JOGSHUTTLE)
endif(BUILD_JogShuttle)
if(BUILD_Jack)
add_definitions(-DUSE_JACK)
include_directories(${JACK_INCLUDE_DIRS})
target_link_libraries(kdenlive ${JACK_LIBRARIES})
endif(BUILD_Jack)
install(TARGETS kdenlive DESTINATION ${BIN_INSTALL_DIR})
install(FILES
kdenliveui.rc

View File

@@ -29,6 +29,25 @@
#include <QVBoxLayout>
bool AbstractRender::isAudioEngineActive(AudioEngine::Type engine)
{
#ifdef USE_JACK
if (engine == AudioEngine::Jack)
if (&JACKDEV && JACKDEV.isValid())
return true;
if (engine == AudioEngine::Mlt)
if (!&JACKDEV || (&JACKDEV && !JACKDEV.isValid()))
return true;
#else
if (engine == AudioEngine::Mlt)
return true;
#endif
return false;
}
AbstractMonitor::AbstractMonitor(Kdenlive::MONITORID id, MonitorManager *manager, QWidget *parent):
QWidget(parent),
videoSurface(NULL),

View File

@@ -30,9 +30,49 @@
#include <stdint.h>
#ifdef USE_JACK
#include "jackdevice.h"
#endif
class MonitorManager;
class VideoContainer;
/* transport slave namespace */
namespace Slave
{
enum Type
{
Internal = 0,
Jack
};
};
/* audio engine namespace */
namespace AudioEngine
{
enum Type
{
Mlt = 0,
Jack
};
};
/* render role namespace */
namespace Rndr
{
enum Role
{
NoRole = (1<<0),
OpenCloseJackEngineRole = (1<<1),
OpenCloseSlaveRole = (1<<2)
};
};
Q_DECLARE_FLAGS(RndrRole, Rndr::Role);
Q_DECLARE_OPERATORS_FOR_FLAGS(RndrRole);
class AbstractRender: public QObject
{
Q_OBJECT public:
@@ -41,11 +81,12 @@ Q_OBJECT public:
* @param name A unique identifier for this renderer
* @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering
* @param profile The MLT profile used for the renderer (default one will be used if empty). */
explicit AbstractRender(Kdenlive::MONITORID name, QWidget *parent = 0)
explicit AbstractRender(Kdenlive::MONITORID name, RndrRole role, QWidget *parent = 0)
: QObject(parent),
sendFrameForAnalysis(false),
analyseAudio(false),
m_name(name)
m_name(name),
m_role(role)
{
}
@@ -63,9 +104,31 @@ Q_OBJECT public:
/** @brief Someone needs us to send again a frame. */
virtual void sendFrameUpdate() = 0;
/** @brief Checks if appropriate role is set. */
virtual bool hasRole(Rndr::Role role) {return m_role.testFlag(role);}
/** @brief Checks if appropriate slave is active.*/
virtual bool isSlaveActive(Slave::Type slave) {return (m_activeSlave == slave);}
/** @brief Enable appropriate slave.*/
virtual void enableSlave(Slave::Type slave) {slave = slave;}
/** @brief Checks if appropriate audio engine is active.*/
virtual bool isAudioEngineActive(AudioEngine::Type engine);
/** @brief Set playback sync monitoring state */
virtual void setPlaybackSyncMonEnabled(bool state) {state = state;}
/** @brief Update configuration */
virtual void updateConfiguration() {}
private:
QString m_name;
protected:
RndrRole m_role;
Slave::Type m_activeSlave;
signals:
/** @brief The renderer refreshed the current frame. */
void frameUpdated(const QImage &);

View File

@@ -154,7 +154,7 @@ void DvdWizardChapters::createMonitor(DVDFORMAT format)
{
QString profile = DvdWizardVob::getDvdProfile(format);
if (m_monitor == NULL) {
m_monitor = new Monitor(Kdenlive::dvdMonitor, m_manager, profile, this);
m_monitor = new Monitor(Kdenlive::dvdMonitor, m_manager, Rndr::NoRole, profile, this);
//m_monitor->start();
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(m_monitor);

562
src/jackdevice.cpp Normal file
View File

@@ -0,0 +1,562 @@
/***************************************************************************
* Copyright (C) 2012 by Ed Rogalsky (ed.rogalsky@gmail.com) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "jackdevice.h"
#include "qmath.h"
JackDevice::JackDevice(Mlt::Profile * profile) :
m_valid(false),
m_shutdown(false),
m_transportEnabled(false),
m_loopState(0),
m_playbackSyncDiff(0),
m_playbackSyncDiffMaxValue(1),
m_playbackSyncMonEnabled(true),
m_playbackSyncMonAction(None)
{
m_mltProfile = profile;
}
JackDevice& JackDevice::singleton(Mlt::Profile * profile)
{
static JackDevice* instance = 0;
if (!instance && profile != 0) {
instance = new JackDevice(profile);
}
return *instance;
}
JackDevice::~JackDevice()
{
// TODO Auto-generated destructor stub
}
void* JackDevice::runTransportThread(void* device)
{
((JackDevice*)device)->updateTransportState();
return NULL;
}
void JackDevice::updateTransportState()
{
pthread_mutex_lock(&m_transportLock);
while (m_valid && !m_shutdown) {
jack_position_t jackpos;
jack_transport_state_t state = JackTransportStopped;
int position = 0;
/* don't call client if already invalidated */
if (!m_shutdown) {
state = jack_transport_query(m_client, &jackpos);
/* convert jack (audio) to kdenlive video position */
position = toVideoPosition(jackpos);
}
if(state != m_state) {
m_nextState = m_state = state;
switch (state) {
case JackTransportRolling:
/* fire playback started event */
emit playbackStarted(position);
break;
case JackTransportStopped:
/* fire playback stopped event */
emit playbackStopped(position);
break;
default:
break;
}
}
pthread_cond_wait(&m_transportCondition, &m_transportLock);
}
pthread_mutex_unlock(&m_transportLock);
}
int JackDevice::toVideoPosition(const jack_position_t &position)
{
double jacktime = 0;
int frame = 0;
double framerate = m_mltProfile->fps();
jacktime = (double) position.frame / (double) position.frame_rate;
frame = qFloor(framerate * jacktime);
/* return video frame number */
return frame;
}
jack_nframes_t JackDevice::toAudioPosition(const int &position, const jack_nframes_t &framerate)
{
return (jack_nframes_t)(((double) framerate * (double) position) / (double) m_mltProfile->fps());
}
bool JackDevice::isValid()
{
return m_valid;
}
void JackDevice::open(const QString &name, int channels, int buffersize)
{
kDebug() << "open client";
if (m_valid == true)
return;
jack_options_t options = JackNullOption;
jack_status_t status;
// open client
m_client = jack_client_open(name.toUtf8().constData(), options, &status);
if(m_client == NULL)
// AUD_THROW(AUD_ERROR_JACK, clientopen_error);
return;
// set callbacks
jack_set_process_callback(m_client, JackDevice::jack_process, this);
jack_on_shutdown(m_client, JackDevice::jack_shutdown, this);
jack_set_sync_callback(m_client, JackDevice::jack_sync, this);
/* store the number of channels */
m_channels = channels;
/* register our output channels which are called ports in jack */
m_ports = new jack_port_t*[m_channels];
// try
{
char portname[64];
for(int i = 0; i < m_channels; i++)
{
sprintf(portname, "out_%d", i+1);
m_ports[i] = jack_port_register(m_client, portname,
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if(m_ports[i] == NULL) {
// AUD_THROW(AUD_ERROR_JACK, port_error);
jack_client_close(m_client);
delete[] m_ports;
return;
}
}
}
// catch(AUD_Exception&)
// {
// jack_client_close(m_client);
// delete[] m_ports;
// throw;
// }
m_ringbuffers = new jack_ringbuffer_t*[m_channels];
for(int i = 0; i < m_channels; i++)
m_ringbuffers[i] = jack_ringbuffer_create(buffersize * sizeof(float));
resetLooping();
/* connect signals */
connect(this, SIGNAL(currentPositionChanged(int)),
this, SLOT(processLooping()));
connect(this, SIGNAL(currentPositionChanged(int)),
this, SLOT(monitorPlaybackSync(int)));
m_valid = true;
m_sync = 0;
/* store current transport state */
m_nextState = m_state = jack_transport_query(m_client, NULL);
/* store jacks audio sample rate */
m_frameRate = jack_get_sample_rate(m_client);
pthread_mutex_init(&m_transportLock, NULL);
pthread_cond_init(&m_transportCondition, NULL);
// activate the client
if(jack_activate(m_client))
{
jack_client_close(m_client);
delete[] m_ports;
for(int i = 0; i < m_channels; i++)
jack_ringbuffer_free(m_ringbuffers[i]);
delete[] m_ringbuffers;
pthread_mutex_destroy(&m_transportLock);
pthread_cond_destroy(&m_transportCondition);
// AUD_THROW(AUD_ERROR_JACK, activate_error);
m_valid = false;
return;
}
const char** ports = jack_get_ports(m_client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
if(ports != NULL)
{
for(int i = 0; i < m_channels && ports[i]; i++)
jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]);
free(ports);
}
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&m_transportThread, &attr, runTransportThread, this);
pthread_attr_destroy(&attr);
/* debug */
kDebug()<< "// jack device open ..." << endl;
}
void JackDevice::close()
{
if(m_valid) {
m_valid = false;
pthread_mutex_lock(&m_transportLock);
pthread_cond_signal(&m_transportCondition);
pthread_mutex_unlock(&m_transportLock);
pthread_join(m_transportThread, NULL);
pthread_cond_destroy(&m_transportCondition);
pthread_mutex_destroy(&m_transportLock);
/* close the client */
jack_client_close(m_client);
delete[] m_ports;
/* free and delete ringbuffers */
for(int i = 0; i < m_channels; i++)
jack_ringbuffer_free(m_ringbuffers[i]);
delete[] m_ringbuffers;
/* disconnect signals */
disconnect(this, SIGNAL(currentPositionChanged(int)),
this, SLOT(processLooping()));
disconnect(this, SIGNAL(currentPositionChanged(int)),
this, SLOT(monitorPlaybackSync(int)));
/* debug */
kDebug()<< "// jack device closed ..." << endl;
}
}
bool JackDevice::probe()
{
jack_client_t *client;
jack_status_t status;
jack_options_t options = JackNoStartServer;
/* try to connect to jackd */
client = jack_client_open("kdenliveprobe", options, &status, NULL );
/* close client if connection successful */
if (status == 0) {
jack_client_close(client);
}
/* return status */
return (status == 0);
}
void JackDevice::jack_shutdown(void *data)
{
JackDevice* device = (JackDevice*)data;
device->m_shutdown = true;
emit device->shutdown();
}
int JackDevice::jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data)
{
JackDevice* device = (JackDevice*)data;
int result = 0;
/* no job if transport is disabled */
if (!device->m_transportEnabled)
return 1;
if(state == JackTransportStopped) {
if (!device->m_sync) {
/*start seeking */
device->m_sync = 1;
emit device->playbackSync(device->toVideoPosition(*pos));
} else if (device->m_sync == 1) {
/* sync position */
if (device->m_currentPosition == device->toVideoPosition(*pos)) {
device->m_sync = 2;
} else {
device->m_sync = 0;
}
}
} else if (state == JackTransportStarting) {
if (!device->m_sync) {
/*start seeking */
device->m_sync = 1;
emit device->playbackSync(device->toVideoPosition(*pos));
} else if (device->m_sync == 1) {
/* sync position */
if (device->m_currentPosition == device->toVideoPosition(*pos)) {
device->m_sync = 2;
} else {
device->m_sync = 0;
}
}
} else if (state == JackTransportRolling) {
/* give up sync and just start playing */
device->m_sync = 0;
result = 1;
}
if (device->m_sync > 1) {
/* FIXME: optimize sync */
#if 0
for(int i = 0; i < device->m_channels; i++)
jack_ringbuffer_reset(device->m_ringbuffers[i]);
#endif
device->m_sync = 0;
result = 1;
}
return result;
}
int JackDevice::jack_process(jack_nframes_t frames, void *data)
{
JackDevice* device = (JackDevice*)data;
int channels = device->m_channels;
/* TODO: review later */
#if 0
if (device->m_sync) {
size_t bufsize = (frames * sizeof(float));
/* play silence while syncing */
for(int i = 0; i < channels; i++)
memset(jack_port_get_buffer(device->m_ports[i], frames), 0, bufsize);
/* FIXME: optimize sync */
// if (device->m_sync > 1) {
// for(int i = 0; i < device->m_channels; i++)
// jack_ringbuffer_reset(device->m_ringbuffers[i]);
// device->m_sync = 3;
// }
} else
#endif
{
/* convert nr of frames to nr of bytes */
size_t jacksize = (frames * sizeof(float));
/* copy audio data into jack buffers */
for (int i = 0; i < channels; i++) {
size_t ringsize;
char * buffer;
ringsize = jack_ringbuffer_read_space(device->m_ringbuffers[i]);
buffer = (char*)jack_port_get_buffer(device->m_ports[i], frames);
jack_ringbuffer_read(device->m_ringbuffers[i], buffer,
ringsize < jacksize ? ringsize : jacksize );
/* fill the rest with zeros to prevent noise */
if(ringsize < jacksize)
memset(buffer + ringsize, 0, jacksize - ringsize);
}
}
if(device->m_transportEnabled) {
if(pthread_mutex_trylock(&(device->m_transportLock)) == 0) {
if (device->m_state != jack_transport_query(device->m_client, NULL))
pthread_cond_signal(&(device->m_transportCondition));
pthread_mutex_unlock(&(device->m_transportLock));
}
}
return 0;
}
void JackDevice::updateBuffers(Mlt::Frame& frame)
{
/* no job while syncing */
if (m_sync) {
return;
}
if (!frame.is_valid() || frame.get_int("test_audio") != 0) {
return;
}
mlt_audio_format format = mlt_audio_float;
int freq = (int)m_frameRate;
int samples = 0;
/* get the audio buffers */
float *buffer = (float*)frame.get_audio(format, freq, m_channels, samples);
if (!buffer) {
return;
}
/* process audio */
size_t size = samples * sizeof(float);
/* write into output ringbuffer */
for (int i = 0; i < m_channels; i++)
{
if (jack_ringbuffer_write_space(m_ringbuffers[i]) >= size)
jack_ringbuffer_write(m_ringbuffers[i], (char*)(buffer + i * samples), size);
}
}
void JackDevice::processLooping()
{
if (m_loopState == 1) {
m_loopState = 2;
} else if (m_loopState == 2) {
if (m_currentPosition == m_loopOut ) {
if (m_loopInfinite) {
seekPlayback(m_loopIn, false);
} else {
stopPlayback();
}
}
} else {
m_loopState = 0;
return;
}
}
void JackDevice::startPlayback(bool resetLoop)
{
if (m_valid) {
/* reset looping state */
if (resetLoop)
resetLooping();
/* start jack transport */
jack_transport_start(m_client);
m_nextState = JackTransportRolling;
}
}
void JackDevice::stopPlayback(bool resetLoop)
{
if (m_valid) {
/* reset looping state */
if (resetLoop)
resetLooping();
/* stop jack transport */
jack_transport_stop(m_client);
m_nextState = JackTransportStopped;
}
}
void JackDevice::seekPlayback(int time, bool resetLoop)
{
if (m_valid) {
if(time >= 0) {
/* reset looping state */
if (resetLoop)
resetLooping();
/* locate jack transport */
jack_transport_locate(m_client, toAudioPosition(time, m_frameRate));
}
}
}
void JackDevice::loopPlayback(int in, int out, bool infinite)
{
m_loopIn = in;
m_loopOut = out;
m_loopInfinite = infinite;
if (!doesPlayback())
startPlayback(false);
seekPlayback(m_loopIn, false);
m_loopState = 1;
}
void JackDevice::resetLooping()
{
m_loopIn = 0;
m_loopOut = 0;
m_loopInfinite = false;
m_loopState = 0;
}
int JackDevice::getPlaybackPosition()
{
jack_position_t position;
jack_transport_query(m_client, &position);
return toVideoPosition(position);
}
void JackDevice::setCurrentPosition(int position)
{
m_currentPosition = position;
emit currentPositionChanged(position);
}
void JackDevice::monitorPlaybackSync(int position)
{
if (!m_playbackSyncMonEnabled)
return;
/* get playback sync difference */
int diff = position - getPlaybackPosition();
if (m_playbackSyncDiff != diff) {
/* save diff */
m_playbackSyncDiff = diff;
/* fire diff event */
emit playbackSyncDiffChanged(diff);
}
/* if action defined */
if (m_playbackSyncMonAction != None) {
bool flag = qAbs(diff) > m_playbackSyncDiffMaxValue;
if (flag && m_nextState == JackTransportRolling) {
if (m_playbackSyncMonAction == Stop) {
stopPlayback();
} else if (m_playbackSyncMonAction == Resync) {
seekPlayback(getPlaybackPosition());
}
}
}
}
void JackDevice::setTransportEnabled(bool state)
{
m_transportEnabled = state;
}
bool JackDevice::doesPlayback()
{
return (m_nextState != JackTransportStopped);
}
void JackDevice::setPlaybackSyncMonEnabled(bool state)
{
m_playbackSyncMonEnabled = state;
}
void JackDevice::setPlaybackSyncMonAction(SyncAction action)
{
m_playbackSyncMonAction = action;
}
void JackDevice::setPlaybackSyncDiffMaxValue(int value)
{
m_playbackSyncDiffMaxValue = value;
}
#include "jackdevice.moc"

329
src/jackdevice.h Normal file
View File

@@ -0,0 +1,329 @@
/***************************************************************************
* Copyright (C) 2012 by Ed Rogalsky (ed.rogalsky@gmail.com) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#ifndef JACKDEVICE_H_
#define JACKDEVICE_H_
#include <jack/jack.h>
#include <jack/ringbuffer.h>
#include <mlt++/Mlt.h>
#include <QObject>
#include <qstring.h>
#include <KDebug>
class JackDevice : public QObject
{
Q_OBJECT
public:
/**
* Singleton constructor.
*/
static JackDevice& singleton(Mlt::Profile * profile = 0);
/**
* Destructor.
*/
virtual ~JackDevice();
/**
* Sync action enum.
*/
enum SyncAction {
None = 0,
Stop,
Resync
};
/**
* Checks if the slave is still valid for processing.
*/
bool isValid();
/**
* Open and init slave.
*/
void open(const QString &name, int channels, int buffersize);
/**
* Close slave.
*/
void close();
/**
* Set transport state.
*/
void setTransportEnabled(bool state);
/**
* Return transport state.
*/
inline bool isTransportEnabled() {return m_transportEnabled;}
/**
* Convert jack audio frame position to kdenlive video position.
*/
int toVideoPosition(const jack_position_t &position);
/**
* Convert kdenlive video to jack audio frame position.
*/
jack_nframes_t toAudioPosition(const int &position, const jack_nframes_t &framerate);
/**
* Checks if jackd is started.
*/
bool probe();
/**
* Starts jack transport playback.
*/
void startPlayback(bool resetLoop = true);
/**
* Stops jack transport playback.
*/
void stopPlayback(bool resetLoop = true);
/**
* Seeks jack transport playback.
* \param time The time to seek to.
*/
void seekPlayback(int time, bool resetLoop = true);
/**
* Loop playback.
* \param in The loop start time.
* \param out The loop stop time.
* \param infinite If true loop forever.
*/
void loopPlayback(int in, int out, bool infinite = true);
/**
* Retrieves the jack transport playback time.
* \return The current time position.
*/
int getPlaybackPosition();
/**
* Returns whether jack transport plays back.
* \return Whether jack transport plays back.
*/
bool doesPlayback();
/**
* Set playback sync monitoring state.
*/
void setPlaybackSyncMonEnabled(bool state);
/**
* Set playback sync monitoring action.
*/
void setPlaybackSyncMonAction(SyncAction action);
/**
* Set playback sync diff max value.
*/
void setPlaybackSyncDiffMaxValue(int value);
/**
* Updates the buffers.
*/
void updateBuffers(Mlt::Frame& frame);
protected:
/**
* Standard constructor.
*/
JackDevice(Mlt::Profile * profile);
private:
/**
* The output ports of jack.
*/
jack_port_t** m_ports;
/**
* The jack client.
*/
jack_client_t* m_client;
/**
* The jack ring buffer.
*/
jack_ringbuffer_t** m_ringbuffers;
/**
* Number of audio channels.
*/
int m_channels;
/**
* Whether the device is valid.
*/
volatile bool m_valid;
/**
* Whether the device is shutdown by jack.
*/
volatile bool m_shutdown;
/**
* The transport synchronization thread.
*/
pthread_t m_transportThread;
/**
* Mutex for transport.
*/
pthread_mutex_t m_transportLock;
/**
* Condition for transport.
*/
pthread_cond_t m_transportCondition;
/**
* Kdenlives current position.
*/
int m_currentPosition;
/**
* Set transport status.
*/
volatile bool m_transportEnabled;
/**
* Loop start position.
*/
int m_loopIn;
/**
* Loop stop position.
*/
int m_loopOut;
/**
* Flag infinite loop [true = infinite|false = single].
*/
bool m_loopInfinite;
/**
* Loop state.
*/
int m_loopState;
/**
* Next Jack Transport state (-1 if not expected to change).
*/
jack_transport_state_t m_nextState;
/**
* Current jack transport status.
*/
jack_transport_state_t m_state;
/**
* Jacks audio frame rate.
*/
jack_nframes_t m_frameRate;
/**
* Syncronisation state.
*/
int m_sync;
/**
* Playback sync difference.
*/
int m_playbackSyncDiff;
/**
* Playback sync difference max value.
*/
int m_playbackSyncDiffMaxValue;
/**
* Playback sync monitoring status.
*/
bool m_playbackSyncMonEnabled;
/**
* Playback sync monitoring Action.
*/
SyncAction m_playbackSyncMonAction;
/**
* Reset looping.
*/
void resetLooping();
/**
* Transport thread function.
* \param device The this pointer.
* \return NULL.
*/
static void* runTransportThread(void* device);
/**
* Updates the transport state.
*/
void updateTransportState();
/**
* Invalidates the jack device.
* \param data The jack device that gets invalidet by jack.
*/
static void jack_shutdown(void *data);
/**
* Mixes the next bytes into the buffer.
* \param length The length in samples to be filled.
* \param data A pointer to the jack device.
* \return 0 what shows success.
*/
static int jack_process(jack_nframes_t length, void *data);
static int jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data);
/** ----------------------------- **/
Mlt::Profile *m_mltProfile;
public slots:
void setCurrentPosition(int position);
private slots:
void processLooping();
void monitorPlaybackSync(int position);
signals:
void playbackStarted(int position);
void playbackSync(int position);
void playbackStopped(int position);
void playbackSyncDiffChanged(int diff);
void currentPositionChanged(int postition);
void shutdown();
};
#define JACKDEV JackDevice::singleton()
#endif /* JACKDEVICE_H */

View File

@@ -194,6 +194,16 @@
<label>Automatically split audio and video.</label>
<default>false</default>
</entry>
<entry name="syncdiffmonaction" type="Int">
<label>Playback sync diff monitor action.</label>
<default>2</default>
</entry>
<entry name="syncdiffmaxvalue" type="Int">
<label>Playback sync diff max value.</label>
<default>1</default>
</entry>
</group>
<group name="sdl">
@@ -601,6 +611,16 @@
<label>Snap movements to clips, guides and markers.</label>
<default>true</default>
</entry>
<entry name="jacktransport" type="Bool">
<label>Enable jack transport in timeline.</label>
<default>true</default>
</entry>
<entry name="jacktransportmon" type="Bool">
<label>Enable jack transport monitoring.</label>
<default>true</default>
</entry>
<entry name="transitionfollowcursor" type="Bool">
<label>When editing a composite transition, move timeline cursor for better preview.</label>

View File

@@ -361,6 +361,7 @@ void KdenliveSettingsDialog::initDevices()
m_configSdl.kcfg_audio_driver->addItem(i18n("OSS with DMA access"), "dma");
m_configSdl.kcfg_audio_driver->addItem(i18n("Esound daemon"), "esd");
m_configSdl.kcfg_audio_driver->addItem(i18n("ARTS daemon"), "artsc");
m_configSdl.kcfg_audio_driver->addItem(i18n("JACK"), "jack");
#endif
if (!KdenliveSettings::audiodrivername().isEmpty())

View File

@@ -53,6 +53,9 @@
<Action name="edit_clip" />
<Action name="delete_clip" />
<Separator />
<Action name="connect_jack" />
<Action name="disconnect_jack" />
<Separator />
<Action name="project_clean" />
<Action name="project_render" />
<Action name="project_adjust_profile" />
@@ -126,6 +129,7 @@
<Action name="show_audio_thumbs" />
<Action name="show_markers" />
<Action name="snap" />
<Action name="jack_transport" />
<Separator />
<Action name="zoom_in" />
<Action name="zoom_out" />

View File

@@ -66,6 +66,9 @@
#include "databackup/backupwidget.h"
#include "utils/resourcewidget.h"
#ifdef USE_JACK
#include "jackdevice.h"
#endif
#include <KApplication>
#include <KAction>
@@ -127,6 +130,10 @@
static const char version[] = VERSION;
#ifdef USE_JACK
static const int STS_BAR_JACK_MON_ID = 0;
#endif
namespace Mlt
{
class Producer;
@@ -234,7 +241,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
m_clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this);
m_clipMonitorDock->setObjectName("clip_monitor");
m_clipMonitor = new Monitor(Kdenlive::clipMonitor, m_monitorManager, QString(), m_timelineArea);
m_clipMonitor = new Monitor(Kdenlive::clipMonitor, m_monitorManager, Rndr::NoRole, QString(), m_timelineArea);
m_clipMonitorDock->setWidget(m_clipMonitor);
// Connect the project list
@@ -252,7 +259,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
m_projectMonitorDock->setObjectName("project_monitor");
m_projectMonitor = new Monitor(Kdenlive::projectMonitor, m_monitorManager, QString());
m_projectMonitor = new Monitor(Kdenlive::projectMonitor, m_monitorManager, Rndr::OpenCloseJackEngineRole | Rndr::OpenCloseSlaveRole, QString());
m_projectMonitorDock->setWidget(m_projectMonitor);
#ifndef Q_WS_MAC
@@ -267,6 +274,23 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
#endif /* ! Q_WS_MAC */
m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
#ifdef USE_JACK
connect(m_monitorManager, SIGNAL(monitorStarted(AbstractMonitor&)),
this, SLOT(slotEnableJackTransportButton(AbstractMonitor&)));
connect(m_monitorManager, SIGNAL(monitorStopped(AbstractMonitor&)),
this, SLOT(slotDisableJackTransportButton(AbstractMonitor&)));
connect(m_monitorManager, SIGNAL(monitorStarted(AbstractMonitor&)),
this, SLOT(slotEnableJackTransportMonButton(AbstractMonitor&)));
connect(m_monitorManager, SIGNAL(monitorStopped(AbstractMonitor&)),
this, SLOT(slotDisableJackTransportMonButton(AbstractMonitor&)));
connect(&JACKDEV, SIGNAL(playbackSyncDiffChanged(int)),
this, SLOT(slotUpdateJackSyncDiff(int)));
connect(this, SIGNAL(jackTransportStateChanged(bool)),
m_monitorManager, SLOT(slotOnJackTransportStateChanged(bool)));
/* fire startup event for proper init */
jackTransportStateChanged(KdenliveSettings::jacktransport());
#endif
m_notesDock = new QDockWidget(i18n("Project Notes"), this);
m_notesDock->setObjectName("notes_widget");
m_notesWidget = new NotesWidget();
@@ -574,6 +598,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
connect(m_recMonitorDock, SIGNAL(visibilityChanged(bool)), m_recMonitor, SLOT(refreshRecMonitor(bool)));
connect(m_effectList, SIGNAL(addEffect(QDomElement)), this, SLOT(slotAddEffect(QDomElement)));
connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
@@ -1175,6 +1200,24 @@ void MainWindow::setupActions()
m_buttonSnap->setChecked(KdenliveSettings::snaptopoints());
connect(m_buttonSnap, SIGNAL(triggered()), this, SLOT(slotSwitchSnap()));
#ifdef USE_JACK
m_buttonJackTransport = new KAction(KIcon("kdenlive-toggle-jack"), i18n("Enable jack transport"), this);
toolbar->addAction(m_buttonJackTransport);
m_buttonJackTransport->setShortcut(Qt::SHIFT + Qt::Key_T);
m_buttonJackTransport->setCheckable(true);
m_buttonJackTransport->setChecked(KdenliveSettings::jacktransport());
m_buttonJackTransport->setDisabled(true);
connect(m_buttonJackTransport, SIGNAL(triggered()), this, SLOT(slotSwitchJackTransport()));
m_buttonJackTransportMon = new KAction(KIcon("kdenlive-toggle-jack-mon"), i18n("Enable jack transport monitoring"), this);
toolbar->addAction(m_buttonJackTransportMon);
m_buttonJackTransportMon->setShortcut(Qt::SHIFT + Qt::Key_E);
m_buttonJackTransportMon->setCheckable(true);
m_buttonJackTransportMon->setChecked(KdenliveSettings::jacktransportmon());
m_buttonJackTransportMon->setDisabled(true);
connect(m_buttonJackTransportMon, SIGNAL(triggered()), this, SLOT(slotSwitchJackTransportMon()));
#endif
actionWidget = toolbar->widgetForAction(m_buttonAutomaticSplitAudio);
actionWidget->setMaximumWidth(max);
actionWidget->setMaximumHeight(max - 4);
@@ -1195,6 +1238,16 @@ void MainWindow::setupActions()
actionWidget->setMaximumWidth(max);
actionWidget->setMaximumHeight(max - 4);
#ifdef USE_JACK
actionWidget = toolbar->widgetForAction(m_buttonJackTransport);
actionWidget->setMaximumWidth(max);
actionWidget->setMaximumHeight(max - 4);
actionWidget = toolbar->widgetForAction(m_buttonJackTransportMon);
actionWidget->setMaximumWidth(max);
actionWidget->setMaximumHeight(max - 4);
#endif
m_messageLabel = new StatusBarMessageLabel(this);
m_messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
@@ -1202,6 +1255,10 @@ void MainWindow::setupActions()
statusBar()->addWidget(m_statusProgressBar, 0);
statusBar()->addPermanentWidget(toolbar);
#ifdef USE_JACK
statusBar()->insertPermanentFixedItem(" 0", STS_BAR_JACK_MON_ID);
#endif
m_timeFormatButton = new KSelectAction("00:00:00:00 / 00:00:00:00", this);
m_timeFormatButton->addAction(i18n("hh:mm:ss:ff"));
m_timeFormatButton->addAction(i18n("Frames"));
@@ -1229,6 +1286,9 @@ void MainWindow::setupActions()
collection.addAction("show_audio_thumbs", m_buttonAudioThumbs);
collection.addAction("show_markers", m_buttonShowMarkers);
collection.addAction("snap", m_buttonSnap);
#ifdef USE_JACK
collection.addAction("jack_transport", m_buttonJackTransport);
#endif
collection.addAction("zoom_fit", m_buttonFitZoom);
collection.addAction("zoom_in", m_zoomIn);
collection.addAction("zoom_out", m_zoomOut);
@@ -1370,6 +1430,18 @@ void MainWindow::setupActions()
insertTimeline->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_I);
connect(insertTimeline, SIGNAL(triggered(bool)), this, SLOT(slotInsertZoneToTimeline()));
#ifdef USE_JACK
KAction *connectJack = collection.addAction("connect_jack");
connectJack->setText(i18n("Jack connect"));
connectJack->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_A);
connect(connectJack, SIGNAL(triggered(bool)), this, SLOT(slotConnectJack()));
KAction *disconnectJack = collection.addAction("disconnect_jack");
disconnectJack->setText(i18n("Jack disconnect"));
disconnectJack->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_D);
connect(disconnectJack, SIGNAL(triggered(bool)), this, SLOT(slotDisconnectJack()));
#endif
KAction *resizeStart = new KAction(KIcon(), i18n("Resize Item Start"), this);
collection.addAction("resize_timeline_clip_start", resizeStart);
resizeStart->setShortcut(Qt::Key_1);
@@ -2554,6 +2626,16 @@ void MainWindow::slotUpdateProjectDuration(int pos)
}
}
void MainWindow::slotUpdateJackSyncDiff(int diff)
{
#ifdef USE_JACK
statusBar()->changeItem(QString::number(diff), STS_BAR_JACK_MON_ID);
#else
/* prevent warning */
Q_UNUSED(diff)
#endif
}
void MainWindow::slotUpdateDocumentState(bool modified)
{
if (!m_activeDocument) return;
@@ -2827,6 +2909,11 @@ void MainWindow::updateConfiguration()
if (m_activeDocument)
m_activeDocument->clipManager()->checkAudioThumbs();
}
if (m_monitorManager) {
m_monitorManager->updateConfiguration();
}
m_buttonAudioThumbs->setChecked(KdenliveSettings::audiothumbnails());
m_buttonVideoThumbs->setChecked(KdenliveSettings::videothumbnails());
m_buttonShowMarkers->setChecked(KdenliveSettings::showmarkers());
@@ -2882,6 +2969,110 @@ void MainWindow::slotSwitchSnap()
}
void MainWindow::slotSwitchJackTransport()
{
#ifdef USE_JACK
AbstractRender* abstrRender = m_monitorManager->activeRenderer();
bool jacktransport = KdenliveSettings::jacktransport();
if (abstrRender) {
if(abstrRender->hasRole(Rndr::OpenCloseSlaveRole) &&
abstrRender->isAudioEngineActive(AudioEngine::Jack) && !jacktransport) {
KdenliveSettings::setJacktransport(true);
abstrRender->enableSlave(Slave::Jack);
} else {
KdenliveSettings::setJacktransport(false);
abstrRender->enableSlave(Slave::Internal);
}
}
m_buttonJackTransport->setChecked(KdenliveSettings::jacktransport());
/* fire event on state change */
jackTransportStateChanged(KdenliveSettings::jacktransport());
#endif
}
void MainWindow::slotSwitchJackTransportMon()
{
#ifdef USE_JACK
AbstractRender* abstrRender = m_monitorManager->activeRenderer();
bool monEnabled = KdenliveSettings::jacktransportmon();
if (abstrRender) {
if(abstrRender->hasRole(Rndr::OpenCloseSlaveRole) && !monEnabled) {
KdenliveSettings::setJacktransportmon(true);
abstrRender->setPlaybackSyncMonEnabled(true);
} else {
KdenliveSettings::setJacktransportmon(false);
abstrRender->setPlaybackSyncMonEnabled(false);
}
}
m_buttonJackTransportMon->setChecked(KdenliveSettings::jacktransportmon());
#endif
}
void MainWindow::slotEnableJackTransportButton(AbstractMonitor& monitor)
{
#ifdef USE_JACK
AbstractRender* abstrRender = monitor.abstractRender();
if (abstrRender) {
if(abstrRender->hasRole(Rndr::OpenCloseSlaveRole) &&
abstrRender->isAudioEngineActive(AudioEngine::Jack)) {
/* if jack transport enabled slave to jack */
if (KdenliveSettings::jacktransport()) {
abstrRender->enableSlave(Slave::Jack);
}
/* enable toggle button */
m_buttonJackTransport->setDisabled(false);
}
}
#endif
}
void MainWindow::slotDisableJackTransportButton(AbstractMonitor& monitor)
{
#ifdef USE_JACK
AbstractRender* abstrRender = monitor.abstractRender();
if (abstrRender) {
if (abstrRender->isSlaveActive(Slave::Jack)) {
/* disable jack slave */
abstrRender->enableSlave(Slave::Internal);
}
/* disable toggle button */
m_buttonJackTransport->setDisabled(true);
}
#endif
}
void MainWindow::slotEnableJackTransportMonButton(AbstractMonitor& monitor)
{
#ifdef USE_JACK
AbstractRender* abstrRender = monitor.abstractRender();
if (abstrRender) {
if(abstrRender->hasRole(Rndr::OpenCloseSlaveRole) &&
abstrRender->isAudioEngineActive(AudioEngine::Jack)) {
/* enable toggle button */
m_buttonJackTransportMon->setDisabled(false);
}
}
#endif
}
void MainWindow::slotDisableJackTransportMonButton(AbstractMonitor& monitor)
{
#ifdef USE_JACK
AbstractRender* abstrRender = monitor.abstractRender();
if (abstrRender) {
/* disable toggle button */
m_buttonJackTransportMon->setDisabled(true);
}
#endif
}
void MainWindow::slotDeleteItem()
{
if (QApplication::focusWidget() &&
@@ -4690,6 +4881,23 @@ void MainWindow::slotSaveTimelineClip()
}
}
void MainWindow::slotConnectJack()
{
m_monitorManager->slotOpenAudioEngine(AudioEngine::Jack);
AbstractRender* abstrRender = m_monitorManager->activeRenderer();
if (abstrRender && abstrRender->hasRole(Rndr::OpenCloseSlaveRole)) {
if(abstrRender->isAudioEngineActive(AudioEngine::Jack)) {
abstrRender->enableSlave(Slave::Jack);
}
}
}
void MainWindow::slotDisconnectJack()
{
m_monitorManager->slotCloseAudioEngine(AudioEngine::Jack);
}
void MainWindow::slotProcessImportKeyframes(GRAPHICSRECTITEM type, const QString& data, int maximum)
{
if (type == AVWIDGET) {

View File

@@ -253,6 +253,10 @@ private:
KAction *m_buttonRazorTool;
KAction *m_buttonSpacerTool;
KAction *m_buttonSnap;
#ifdef USE_JACK
KAction *m_buttonJackTransport;
KAction *m_buttonJackTransportMon;
#endif
KAction *m_saveAction;
KAction *m_closeAction;
QSlider *m_zoomSlider;
@@ -360,6 +364,7 @@ private slots:
void slotConnectMonitors();
void slotUpdateClip(const QString &id);
void slotUpdateMousePosition(int pos);
void slotUpdateJackSyncDiff(int diff);
void slotUpdateProjectDuration(int pos);
void slotAddEffect(const QDomElement &effect);
void slotEditProfiles();
@@ -571,8 +576,27 @@ private slots:
/** @brief Set MLT's consumer interpolation method */
void slotSetInterpolation(int ix);
/* TODO: @eddrog find solution - moc has a problem with #ifdef in slots */
/** @brief Connect slave to jackd */
void slotConnectJack();
/** @brief Disconnect slave from jackd */
void slotDisconnectJack();
/** @brief Switch jack transport enabled state */
void slotSwitchJackTransport();
/** @brief Switch jack transport monitoring enabled state */
void slotSwitchJackTransportMon();
/** @brief Enable jack transport button */
void slotEnableJackTransportButton(AbstractMonitor& monitor);
/** @brief Disable jack transport button */
void slotDisableJackTransportButton(AbstractMonitor& monitor);
/** @brief Enable jack transport monitoring button */
void slotEnableJackTransportMonButton(AbstractMonitor& monitor);
/** @brief Disable jack transport monitoring button */
void slotDisableJackTransportMonButton(AbstractMonitor& monitor);
signals:
Q_SCRIPTABLE void abortRenderJob(const QString &url);
void jackTransportStateChanged(bool enabled);
};

View File

@@ -78,7 +78,7 @@ static void rec_consumer_frame_preview(mlt_consumer, MltDeviceCapture * self, ml
MltDeviceCapture::MltDeviceCapture(QString profile, VideoSurface *surface, QWidget *parent) :
AbstractRender(Kdenlive::recordMonitor, parent),
AbstractRender(Kdenlive::recordMonitor, Rndr::NoRole, parent),
doCapture(0),
sendFrameForAnalysis(false),
processingImage(false),

View File

@@ -48,7 +48,7 @@
#define SEEK_INACTIVE (-1)
Monitor::Monitor(Kdenlive::MONITORID id, MonitorManager *manager, QString profile, QWidget *parent) :
Monitor::Monitor(Kdenlive::MONITORID id, MonitorManager *manager, RndrRole role, QString profile, QWidget *parent) :
AbstractMonitor(id, manager, parent)
, render(NULL)
, m_currentClip(NULL)
@@ -91,7 +91,7 @@ Monitor::Monitor(Kdenlive::MONITORID id, MonitorManager *manager, QString profil
m_toolbar->addAction(KIcon("kdenlive-zone-end"), i18n("Set zone end"), this, SLOT(slotSetZoneEnd()));
}
m_toolbar->addAction(KIcon("media-seek-backward"), i18n("Rewind"), this, SLOT(slotRewind()));
m_rewindAction = m_toolbar->addAction(KIcon("media-seek-backward"), i18n("Rewind"), this, SLOT(slotRewind()));
//m_toolbar->addAction(KIcon("media-skip-backward"), i18n("Rewind 1 frame"), this, SLOT(slotRewindOneFrame()));
QToolButton *playButton = new QToolButton(m_toolbar);
@@ -105,7 +105,7 @@ Monitor::Monitor(Kdenlive::MONITORID id, MonitorManager *manager, QString profil
m_toolbar->addWidget(playButton);
//m_toolbar->addAction(KIcon("media-skip-forward"), i18n("Forward 1 frame"), this, SLOT(slotForwardOneFrame()));
m_toolbar->addAction(KIcon("media-seek-forward"), i18n("Forward"), this, SLOT(slotForward()));
m_forwardAction = m_toolbar->addAction(KIcon("media-seek-forward"), i18n("Forward"), this, SLOT(slotForward()));
playButton->setDefaultAction(m_playAction);
@@ -154,17 +154,17 @@ Monitor::Monitor(Kdenlive::MONITORID id, MonitorManager *manager, QString profil
bool monitorCreated = false;
#ifdef Q_WS_MAC
createOpenGlWidget(videoBox, profile);
createOpenGlWidget(videoBox, profile, role);
monitorCreated = true;
//m_glWidget->setFixedSize(width, height);
#elif defined(USE_OPENGL)
if (KdenliveSettings::openglmonitors()) {
monitorCreated = createOpenGlWidget(videoBox, profile);
monitorCreated = createOpenGlWidget(videoBox, profile, role);
}
#endif
if (!monitorCreated) {
createVideoSurface();
render = new Render(m_id, (int) videoSurface->winId(), profile, this);
render = new Render(m_id, (int) videoSurface->winId(), role, profile, this);
connect(videoSurface, SIGNAL(refreshMonitor()), render, SLOT(doRefresh()));
}
#ifdef USE_OPENGL
@@ -184,6 +184,7 @@ Monitor::Monitor(Kdenlive::MONITORID id, MonitorManager *manager, QString profil
connect(m_audioSlider, SIGNAL(valueChanged(int)), this, SLOT(slotSetVolume(int)));
connect(render, SIGNAL(durationChanged(int)), this, SLOT(adjustRulerSize(int)));
connect(render, SIGNAL(rendererStopped(int)), this, SLOT(rendererStopped(int)));
connect(render, SIGNAL(rendererStarted()), this, SLOT(rendererStarted()));
connect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
if (id != Kdenlive::clipMonitor) {
@@ -230,9 +231,9 @@ QWidget *Monitor::container()
}
#ifdef USE_OPENGL
bool Monitor::createOpenGlWidget(QWidget *parent, const QString &profile)
bool Monitor::createOpenGlWidget(QWidget *parent, const QString &profile, RndrRole role)
{
render = new Render(id(), 0, profile, this);
render = new Render(id(), 0, role, profile, this);
m_glWidget = new VideoGLWidget(parent);
if (m_glWidget == NULL) {
// Creation failed, we are in trouble...
@@ -483,6 +484,22 @@ void Monitor::slotSwitchFullScreen()
videoBox->switchFullScreen();
}
void Monitor::slotOnJackTransportStateChanged(bool enabled)
{
/* no action if not connected to jack */
if (!render->isAudioEngineActive(AudioEngine::Jack)) {
return;
}
if (enabled) {
m_forwardAction->setDisabled(true);
m_rewindAction->setDisabled(true);
} else {
m_forwardAction->setDisabled(false);
m_rewindAction->setDisabled(false);
}
}
// virtual
void Monitor::mouseReleaseEvent(QMouseEvent * event)
{
@@ -693,6 +710,12 @@ void Monitor::slotZoneEnd()
void Monitor::slotRewind(double speed)
{
#ifdef USE_JACK
/* in jack mode only speed 1 and forward direction is possible */
if (render->isSlaveActive(Slave::Jack)) {
return;
}
#endif
slotActivateMonitor();
if (speed == 0) {
double currentspeed = render->playSpeed();
@@ -717,7 +740,14 @@ void Monitor::slotRewind(double speed)
void Monitor::slotForward(double speed)
{
slotActivateMonitor();
#ifdef USE_JACK
/* in jack mode only speed 1 and forward direction is possible */
if (render->isSlaveActive(Slave::Jack)) {
return;
}
#endif
slotActivateMonitor();
if (speed == 0) {
double currentspeed = render->playSpeed();
if (currentspeed <= 0) render->play(1);
@@ -772,6 +802,12 @@ void Monitor::rendererStopped(int pos)
m_playAction->setIcon(m_playIcon);
}
void Monitor::rendererStarted()
{
m_playAction->setIcon(m_pauseIcon);
}
void Monitor::adjustRulerSize(int length)
{
if (length > 0) m_length = length;
@@ -784,7 +820,11 @@ void Monitor::adjustRulerSize(int length)
void Monitor::stop()
{
if (render) render->stop();
if (render) {
render->stop();
}
/* on stopping monitor reset icon */
m_playAction->setIcon(m_playIcon);
}
void Monitor::start()

View File

@@ -68,7 +68,7 @@ class Monitor : public AbstractMonitor
Q_OBJECT
public:
Monitor(Kdenlive::MONITORID id, MonitorManager *manager, QString profile = QString(), QWidget *parent = 0);
Monitor(Kdenlive::MONITORID id, MonitorManager *manager, RndrRole role, QString profile = QString(), QWidget *parent = 0);
~Monitor();
Render *render;
AbstractRender *abstractRender();
@@ -130,6 +130,8 @@ private:
KIcon m_pauseIcon;
TimecodeDisplay *m_timePos;
QAction *m_playAction;
QAction *m_rewindAction;
QAction *m_forwardAction;
/** Has to be available so we can enable and disable it. */
QAction *m_loopClipAction;
QMenu *m_contextMenu;
@@ -146,7 +148,7 @@ private:
#ifdef USE_OPENGL
VideoGLWidget *m_glWidget;
bool createOpenGlWidget(QWidget *parent, const QString &profile);
bool createOpenGlWidget(QWidget *parent, const QString &profile, RndrRole role);
#endif
GenTime getSnapForPos(bool previous);
@@ -159,6 +161,7 @@ private:
private slots:
void seekCursor(int pos);
void rendererStopped(int pos);
void rendererStarted();
void slotExtractCurrentFrame();
void slotSetThumbFrame();
void slotSetSizeOneToOne();
@@ -215,6 +218,7 @@ public slots:
void slotSetSelectedClip(Transition *item);
void slotMouseSeek(int eventDelta, bool fast);
void slotSwitchFullScreen();
void slotOnJackTransportStateChanged(bool enabled);
signals:
void renderPosition(int);

View File

@@ -102,15 +102,19 @@ bool MonitorManager::activateMonitor(Kdenlive::MONITORID name, bool forceRefresh
for (int i = 0; i < m_monitorsList.count(); ++i) {
if (m_monitorsList.at(i)->id() == name) {
m_activeMonitor = m_monitorsList.at(i);
} else {
m_monitorsList.at(i)->stop();
/* fire monitor stopped event */
emit monitorStopped(*m_monitorsList.at(i));
}
else m_monitorsList.at(i)->stop();
}
if (m_activeMonitor) {
m_activeMonitor->blockSignals(true);
m_activeMonitor->parentWidget()->raise();
m_activeMonitor->blockSignals(false);
m_activeMonitor->blockSignals(false);
m_activeMonitor->start();
/* fire monitor started event */
emit monitorStarted(*m_activeMonitor);
}
emit checkColorScopes();
return (m_activeMonitor != NULL);
@@ -281,5 +285,30 @@ QString MonitorManager::getProjectFolder() const
return m_document->projectFolder().path(KUrl::AddTrailingSlash);
}
void MonitorManager::slotOpenAudioEngine(AudioEngine::Type engine)
{
m_projectMonitor->render->openAudioEngine(engine);
}
void MonitorManager::slotCloseAudioEngine(AudioEngine::Type engine)
{
m_projectMonitor->render->closeAudioEngine(engine);
}
void MonitorManager::slotOnJackTransportStateChanged(bool enabled)
{
m_projectMonitor->slotOnJackTransportStateChanged(enabled);
}
void MonitorManager::updateConfiguration()
{
AbstractRender *abstrRender = NULL;
for (int i = 0; i < m_monitorsList.size(); i++) {
abstrRender = m_monitorsList[i]->abstractRender();
if (abstrRender)
abstrRender->updateConfiguration();
}
}
#include "monitormanager.moc"

View File

@@ -52,6 +52,8 @@ public:
void setDocument(KdenliveDoc *doc);
/** @brief Change an MLT consumer property for both monitors. */
void setConsumerProperty(const QString &name, const QString &value);
/** @brief Update configuration for available monitors. */
void updateConfiguration();
public slots:
@@ -82,6 +84,13 @@ public slots:
void slotSwitchMonitors(bool activateClip);
void slotUpdateAudioMonitoring();
/** @brief Open defined audio engine */
void slotOpenAudioEngine(AudioEngine::Type engine);
/** @brief Close defined audio engine */
void slotCloseAudioEngine(AudioEngine::Type engine);
/** @brief Action handler for JackTransportStateChanged event */
void slotOnJackTransportStateChanged(bool enabled);
private slots:
void slotRefreshCurrentMonitor(const QString &id);
@@ -99,6 +108,11 @@ signals:
/** @brief When the active monitor renderer was deleted, reset color scopes */
void clearScopes();
/** @brief Inform if monitor is started */
void monitorStarted(AbstractMonitor & mon);
/** @brief Inform if monitor is stopped */
void monitorStopped(AbstractMonitor & mon);
};
#endif

View File

@@ -1000,7 +1000,7 @@ void RecMonitor::refreshRecMonitor(bool visible)
{
if (visible) {
//if (!m_isActive) activateMonitor();
slotActivateMonitor();
}
}

View File

@@ -31,7 +31,7 @@ class QPaintEvent;
class QResizeEvent;
class QMouseEvent;
class RegionGrabber : public QWidget
class RegionGrabber : public QObject, public QWidget
{
Q_OBJECT
public:

View File

@@ -26,10 +26,15 @@
#include "renderer.h"
#include "kdenlivesettings.h"
#include "kthumb.h"
#include "kapplication.h"
#include "definitions.h"
#include "slideshowclip.h"
#include "profilesdialog.h"
#ifdef USE_JACK
#include "jackdevice.h"
#endif
#include <mlt++/Mlt.h>
#include <KDebug>
@@ -51,6 +56,17 @@
#define SEEK_INACTIVE (-1)
#include <QThread>
// Can't believe I need to do this to sleep.
class SleepThread : QThread
{
public:
virtual void run() {};
static void msleep(unsigned long msecs) {
QThread::msleep(msecs);
}
};
static void kdenlive_callback(void* /*ptr*/, int level, const char* fmt, va_list vl)
{
if (level > MLT_LOG_ERROR) return;
@@ -71,6 +87,13 @@ void Render::consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_pt
if (self->sendFrameForAnalysis && frame_ptr->convert_image) {
self->emitFrameUpdated(frame);
}
#ifdef USE_JACK
if (self->isAudioEngineActive(AudioEngine::Jack)) {
JACKDEV.updateBuffers(frame);
}
#endif
if (self->analyseAudio) {
self->showAudio(frame);
}
@@ -102,17 +125,25 @@ void Render::consumer_gl_frame_show(mlt_consumer consumer, Render * self, mlt_fr
emit self->rendererPosition((int) mlt_consumer_position(consumer));
return;
}
Mlt::Frame frame(frame_ptr);
if (frame.get_double("_speed") == 0) self->emitConsumerStopped();
else if (frame.get_double("_speed") < 0.0 && mlt_frame_get_position(frame_ptr) <= 0) {
self->pause();
self->emitConsumerStopped(true);
}
#ifdef USE_JACK
if (self->isAudioEngineActive(AudioEngine::Jack)) {
JACKDEV.updateBuffers(frame);
}
#endif
emit self->mltFrameReceived(new Mlt::Frame(frame_ptr));
}
Render::Render(Kdenlive::MONITORID rendererName, int winid, QString profile, QWidget *parent) :
AbstractRender(rendererName, parent),
Render::Render(Kdenlive::MONITORID rendererName, int winid, RndrRole role, QString profile, QWidget *parent) :
AbstractRender(rendererName, role, parent),
requestedSeekPosition(SEEK_INACTIVE),
showFrameSemaphore(1),
externalConsumer(false),
@@ -135,9 +166,11 @@ Render::Render(Kdenlive::MONITORID rendererName, int winid, QString profile, QWi
if (profile.isEmpty())
profile = KdenliveSettings::current_profile();
buildConsumer(profile);
m_mltProducer = m_blackClip->cut(0, 1);
m_mltConsumer->connect(*m_mltProducer);
m_mltProducer->set_speed(0.0);
m_refreshTimer.setSingleShot(true);
m_refreshTimer.setInterval(100);
connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
@@ -148,7 +181,13 @@ Render::Render(Kdenlive::MONITORID rendererName, int winid, QString profile, QWi
Render::~Render()
{
closeMlt();
#ifdef USE_JACK
/* isDeviceActive ()*/
if (hasRole(Rndr::OpenCloseJackEngineRole)) {
closeAudioEngine(AudioEngine::Jack);
}
#endif
closeMlt();
delete m_mltProfile;
}
@@ -324,6 +363,30 @@ void Render::buildConsumer(const QString &profileName)
m_mltConsumer->set("frequency", 48000);
m_mltConsumer->set("real_time", KdenliveSettings::mltthreads());
#ifdef USE_JACK
/* create the jack device singleton instance */
JackDevice::singleton(m_mltProfile);
bool jackdStarted = &JACKDEV && JACKDEV.probe();
bool rolesValid = hasRole(Rndr::OpenCloseJackEngineRole);
if (jackdStarted && rolesValid) {
/* open jack audio engine */
openAudioEngine(AudioEngine::Jack);
} else if (!jackdStarted && rolesValid) {
/* show error message in explicite jack mode */
if (!audioDriver.isEmpty() && audioDriver == "jack") {
KMessageBox::error(qApp->activeWindow(),
i18n("Can't connect to jackd. Please start jackd and restart kdenlive!"));
}
} else if (jackdStarted && !rolesValid) {
/* stop consumer */
if (!m_mltConsumer->is_stopped())
m_mltConsumer->stop();
/* disable audio */
m_mltConsumer->set("audio_off", 1);
}
#endif
}
Mlt::Producer *Render::invalidProducer(const QString &id)
@@ -424,11 +487,25 @@ void Render::seek(const GenTime &time)
seek(pos);
}
void Render::seek(int time)
void Render::seek(int time, bool fromMaster)
{
/* limit time */
time = qMax(0, time);
time = qMin(m_mltProducer->get_playtime(), time);
#ifdef USE_JACK
if (!fromMaster && isSlaveActive(Slave::Jack)) {
if (isAudioEngineActive(AudioEngine::Jack)) {
JACKDEV.seekPlayback(time < 0 ? 0 : time);
}
/* return */
return;
} else if (fromMaster && isSlaveActive(Slave::Jack)) {
// m_mltProducer->set_speed(0);
}
#endif
resetZoneMode();
time = qMax(0, time);
time = qMin(m_mltProducer->get_playtime(), time);
if (requestedSeekPosition == SEEK_INACTIVE) {
requestedSeekPosition = time;
m_mltConsumer->purge();
@@ -1624,12 +1701,31 @@ void Render::setActiveMonitor()
if (!m_isActive) emit activateMonitor(m_name);
}
void Render::switchPlay(bool play)
void Render::switchPlay(bool play, bool fromMaster)
{
QMutexLocker locker(&m_mutex);
requestedSeekPosition = SEEK_INACTIVE;
if (!m_mltProducer || !m_mltConsumer || !m_isActive)
return;
#ifdef USE_JACK
if (!fromMaster && isSlaveActive(Slave::Jack)) {
if (isAudioEngineActive(AudioEngine::Jack)) {
if (play) {
JACKDEV.startPlayback();
} else {
JACKDEV.stopPlayback();
}
}
/* return */
return;
} else if (fromMaster && isSlaveActive(Slave::Jack)) {
// position = JACKDEV.getPlaybackPosition();
}
#else
Q_UNUSED(fromMaster)
#endif
if (m_isZoneMode) resetZoneMode();
if (play && m_paused) {
if (m_name == Kdenlive::clipMonitor && m_mltConsumer->position() == m_mltProducer->get_out()) m_mltProducer->seek(0);
@@ -1699,6 +1795,21 @@ void Render::playZone(const GenTime & startTime, const GenTime & stopTime)
requestedSeekPosition = SEEK_INACTIVE;
if (!m_mltProducer || !m_mltConsumer || !m_isActive)
return;
#ifdef USE_JACK
if (isSlaveActive(Slave::Jack) && isAudioEngineActive(AudioEngine::Jack)) {
/* calc loop in/out */
int loopIn = (int)(startTime.frames(m_fps));
int loopOut = (int)(stopTime.frames(m_fps));
/* internal processing compat */
m_isZoneMode = true;
/* start looping */
JACKDEV.loopPlayback(loopIn, loopOut, m_isLoopMode);
/* return */
return;
}
#endif
m_mltProducer->set("out", (int)(stopTime.frames(m_fps)));
m_mltProducer->seek((int)(startTime.frames(m_fps)));
m_paused = false;
@@ -1850,6 +1961,15 @@ void Render::emitConsumerStopped(bool forcePause)
{
// This is used to know when the playing stopped
if (m_mltProducer && (forcePause || (!m_paused && m_mltProducer->get_speed() == 0))) {
#ifdef USE_JACK
if (isSlaveActive(Slave::Jack) && isAudioEngineActive(AudioEngine::Jack)) {
if (m_mltConsumer->position() == m_mltProducer->get_out()) {
JACKDEV.stopPlayback();
}
return;
}
#endif
double pos = m_mltProducer->position();
m_paused = true;
if (m_isLoopMode) play(m_loopStart);
@@ -4819,5 +4939,181 @@ bool Render::checkX11Grab()
return result.contains("x11grab");
}
void Render::openAudioEngine(AudioEngine::Type engine)
{
#ifdef USE_JACK
if (engine == AudioEngine::Jack) {
/* stop consumer */
if (!m_mltConsumer->is_stopped())
m_mltConsumer->stop();
/* disable audio */
m_mltConsumer->set("audio_off", 1);
/* connect to jackd and open device */
if (&JACKDEV && !JACKDEV.isValid()) {
JACKDEV.open("kdenlive", 2, 204800 * 6);
/* connect shutdown event handler */
connect(&JACKDEV, SIGNAL(shutdown()),
this, SLOT(slotOnDeviceShutdown()));
/* set sync diff monitoring action */
JackDevice::SyncAction syncAction =
(JackDevice::SyncAction)KdenliveSettings::syncdiffmonaction();
JACKDEV.setPlaybackSyncMonAction(syncAction);
/* set sync diff max value */
int syncDiffMax = KdenliveSettings::syncdiffmaxvalue();
JACKDEV.setPlaybackSyncDiffMaxValue(syncDiffMax);
}
} else
#endif
{
/* prevent warnings */
engine = engine;
}
}
void Render::closeAudioEngine(AudioEngine::Type engine)
{
#ifdef USE_JACK
if (engine == AudioEngine::Jack) {
if (isAudioEngineActive(AudioEngine::Jack)) {
/* close jack slave */
enableSlave(Slave::Internal);
/* disconnect shutdown event handler */
disconnect(&JACKDEV, SIGNAL(shutdown()),
this, SLOT(slotOnDeviceShutdown()));
/* disconnect from jackd and close device */
JACKDEV.close();
/* TODO: on jack client shutdown event => close dev */
}
} else
#endif
{
/* prevent warning */
engine = engine;
}
}
void Render::enableSlave(Slave::Type slave)
{
/* if slave is equal return */
if (isSlaveActive(slave))
return;
#ifdef USE_JACK
/* close current slave */
if (isSlaveActive(Slave::Jack)) {
if (&JACKDEV && JACKDEV.isTransportEnabled()) {
/* disable transport */
JACKDEV.setTransportEnabled(false);
/* disconnect transport callbacks */
disconnect(&JACKDEV, SIGNAL(playbackStarted(int)),
this, SLOT(slotOnSlavePlaybackStarted(int)));
disconnect(&JACKDEV, SIGNAL(playbackSync(int)),
this, SLOT(slotOnSlavePlaybackSync(int)));
disconnect(&JACKDEV, SIGNAL(playbackStopped(int)),
this, SLOT(slotOnSlavePlaybackStopped(int)));
disconnect(this, SIGNAL(rendererPosition(int)),
&JACKDEV, SLOT(setCurrentPosition(int)));
/* stop jack playback */
JACKDEV.stopPlayback();
/* stop mlt playback and relocate to stopped jack pos */
if (m_mltProducer->get_speed() != 0)
slotOnSlavePlaybackStopped(JACKDEV.getPlaybackPosition());
/* DEBUG */
kDebug() << "// JACK Slave disabled";
}
} else
#endif
{
/* DEBUG */
kDebug() << "// INTERNAL Slave disabled";
}
#ifdef USE_JACK
if ((slave == Slave::Jack) && hasRole(Rndr::OpenCloseSlaveRole)
&& isAudioEngineActive(AudioEngine::Jack)) {
/* connect transport callbacks */
connect(&JACKDEV, SIGNAL(playbackStarted(int)),
this, SLOT(slotOnSlavePlaybackStarted(int)));
connect(&JACKDEV, SIGNAL(playbackSync(int)),
this, SLOT(slotOnSlavePlaybackSync(int)));
connect(&JACKDEV, SIGNAL(playbackStopped(int)),
this, SLOT(slotOnSlavePlaybackStopped(int)));
connect(this, SIGNAL(rendererPosition(int)),
&JACKDEV, SLOT(setCurrentPosition(int)));
/* enable transport */
JACKDEV.setTransportEnabled(true);
/* stop playback and relocate */
JACKDEV.stopPlayback();
JACKDEV.seekPlayback(seekFramePosition());
/* change slave */
m_activeSlave = slave;
/* DEBUG */
kDebug() << "// JACK Slave enabled";
} else
#endif
{
/* default to INTERNAL */
m_activeSlave = Slave::Internal;
/* DEBUG */
kDebug() << "// INTERNAL Slave enabled";
}
}
void Render::setPlaybackSyncMonEnabled(bool state)
{
#ifdef USE_JACK
if (isAudioEngineActive(AudioEngine::Jack)) {
JACKDEV.setPlaybackSyncMonEnabled(state);
}
#endif
}
void Render::updateConfiguration()
{
#ifdef USE_JACK
if (isAudioEngineActive(AudioEngine::Jack)) {
/* set sync diff monitoring action */
JackDevice::SyncAction syncAction =
(JackDevice::SyncAction)KdenliveSettings::syncdiffmonaction();
JACKDEV.setPlaybackSyncMonAction(syncAction);
/* set sync diff max value */
int syncDiffMax = KdenliveSettings::syncdiffmaxvalue();
JACKDEV.setPlaybackSyncDiffMaxValue(syncDiffMax);
}
#endif
}
void Render::slotOnSlavePlaybackStarted(int position)
{
position = position;
switchPlay(true, true);
rendererStarted();
}
void Render::slotOnSlavePlaybackSync(int position)
{
if (m_mltProducer->get_speed() != 0)
switchPlay(false, true);
seek(position, true);
m_paused = true;
}
void Render::slotOnSlavePlaybackStopped(int position)
{
switchPlay(false, true);
seek(position, true);
m_paused = true;
emit rendererStopped(position);
}
void Render::slotOnDeviceShutdown()
{
closeAudioEngine(AudioEngine::Jack);
}
#include "renderer.moc"

View File

@@ -47,6 +47,8 @@
#include <QSemaphore>
#include <QTimer>
class QTimer;
class QPixmap;
class KComboBox;
@@ -105,20 +107,36 @@ class Render: public AbstractRender
enum FailStates { OK = 0,
APP_NOEXIST
};
/** @brief Build a MLT Renderer
/** @brief Build a MLT Renderer
* @param rendererName A unique identifier for this renderer
* @param winid The parent widget identifier (required for SDL display). Set to 0 for OpenGL rendering
* @param profile The MLT profile used for the renderer (default one will be used if empty). */
Render(Kdenlive::MONITORID rendererName, int winid, QString profile = QString(), QWidget *parent = 0);
Render(Kdenlive::MONITORID rendererName, int winid, RndrRole role, QString profile = QString(), QWidget *parent = 0);
/** @brief Destroy the MLT Renderer. */
virtual ~Render();
/** @brief Seeks the renderer clip to the given time. */
void seek(const GenTime &time);
void seek(int time);
void seek(int time, bool fromMaster = false);
void seekToFrameDiff(int diff);
/** @brief Open appropriate audio engine */
void openAudioEngine(AudioEngine::Type engine);
/** @brief Close appropriate audio engine */
void closeAudioEngine(AudioEngine::Type engine);
/** @brief Enable appropriate transport slave */
void enableSlave(Slave::Type slave);
/** @brief Set playback sync monitoring state */
void setPlaybackSyncMonEnabled(bool state);
/** @brief Update configuration */
void updateConfiguration();
QPixmap getImageThumbnail(const KUrl &url, int width, int height);
/** @brief Sets the current MLT producer playlist.
@@ -146,7 +164,7 @@ class Render: public AbstractRender
* The speed is relative to normal playback, e.g. 1.0 is normal speed, 0.0
* is paused, -1.0 means play backwards. It does not specify start/stop */
void play(double speed);
void switchPlay(bool play);
void switchPlay(bool play, bool fromMaster = false);
void pause();
/** @brief Stops playing.
@@ -459,6 +477,7 @@ signals:
void durationChanged(int);
void rendererPosition(int);
void rendererStopped(int);
void rendererStarted();
/** @brief The clip is not valid, should be removed from project. */
void removeInvalidClip(const QString &, bool replaceProducer);
/** @brief The proxy is not valid, should be deleted.
@@ -504,6 +523,15 @@ public slots:
void seekToFrame(int pos);
/** @brief Starts a timer to query for a refresh. */
void doRefresh();
/** @brief Slave playback started event handler */
void slotOnSlavePlaybackStarted(int position);
/** @brief Slave playback sync event handler */
void slotOnSlavePlaybackSync(int position);
/** @brief Slave playback stopped event handler */
void slotOnSlavePlaybackStopped(int position);
/** @brief Audio device shutdown event handler */
void slotOnDeviceShutdown();
};
#endif

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>361</width>
<height>222</height>
<width>386</width>
<height>252</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -92,6 +92,83 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Playback sync diff max. value</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="kcfg_syncdiffmaxvalue">
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Playback sync diff monitoring action</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="kcfg_syncdiffmonaction">
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>none</string>
</property>
</item>
<item>
<property name="text">
<string>stop</string>
</property>
</item>
<item>
<property name="text">
<string>resync</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>