'From etoys3.0 of 7 March 2008 [latest update: #2059] on 26 July 2008 at 9:03:19 pm'! "Change Set: GStreamer-Base Date: 26 July 2008 Author: John McIntosh, Joshua Gargus Initial import of GStreamer code base from squeaksource.com/GStreamer Name: GStreamer-Base-jcg.38 Author: jcg Time: 4 May 2008, 11:59:55 am UUID: c833d859-91e5-4ff9-9e90-4cc979bfc2f2 Ancestors: GStreamer-Base-jcg.37 "! Object subclass: #GStreamer instanceVariableNames: 'initializedOk version' classVariableNames: 'Default DiagnosticMsgToTranscript' poolDictionaries: '' category: 'GStreamer-Base'! !GStreamer commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ! Object subclass: #GStreamerMetadata instanceVariableNames: 'handle' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base'! Object subclass: #GStreamerObject instanceVariableNames: 'handle' classVariableNames: 'Registry' poolDictionaries: '' category: 'GStreamer-Base'! !GStreamerObject commentStamp: '' prior: 0! handle is a memory address for a GStreamer Object Register is the Weak Registery to enable our ability to deal with GCed Objects * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerObject subclass: #GStreamerBus instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base'! !GStreamerBus commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerObject subclass: #GStreamerCaps instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base'! !GStreamerCaps commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerObject subclass: #GStreamerClock instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base'! !GStreamerClock commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerObject subclass: #GStreamerElement instanceVariableNames: 'metadata requestPads' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! !GStreamerElement commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerElement subclass: #GStreamerBin instanceVariableNames: 'elementsInPipe' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! !GStreamerBin commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerObject subclass: #GStreamerElementFactory instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! !GStreamerElementFactory commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerElement subclass: #GStreamerElementForSqueakSinkAudio instanceVariableNames: 'audioSink' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! !GStreamerElementForSqueakSinkAudio commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerElement subclass: #GStreamerElementForSqueakSinkVideo instanceVariableNames: 'videoSink' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! GStreamerElement subclass: #GStreamerElementForSqueakSrcAudio instanceVariableNames: 'audioSrc' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! GStreamerElement subclass: #GStreamerElementForSqueakSrcVideo instanceVariableNames: 'videoSrc' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! GStreamerObject subclass: #GStreamerMessage instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base'! !GStreamerMessage commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerObject subclass: #GStreamerPad instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pads'! !GStreamerPad commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerBin subclass: #GStreamerPipeline instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! !GStreamerPipeline commentStamp: '' prior: 0! elementsInPipe elements in the pipe * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerPipeline subclass: #GStreamerPipelineSqueakSink instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! !GStreamerPipelineSqueakSink commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerPipelineSqueakSink subclass: #GStreamerPipelineSqueakAudioSink instanceVariableNames: 'squeakerAudio' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! !GStreamerPipelineSqueakAudioSink commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerPipelineSqueakSink subclass: #GStreamerPipelineSqueakSrc instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! GStreamerPipelineSqueakSrc subclass: #GStreamerPipelineSqueakAudioSrc instanceVariableNames: 'semaphoreAudio semaIndexAudio squeakerAudio frequency' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! GStreamerPipelineSqueakAudioSink subclass: #GStreamerPipelineSqueakVideoSink instanceVariableNames: 'squeakerVideo' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! !GStreamerPipelineSqueakVideoSink commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerPipelineSqueakSrc subclass: #GStreamerPipelineSqueakVideoSrc instanceVariableNames: 'semaphoreVideo semaIndexVideo squeakerVideo width height depth fps' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pipelines'! GStreamerPad subclass: #GStreamerRequestPad instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pads'! !GStreamerRequestPad commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerPad subclass: #GStreamerStaticPad instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Pads'! !GStreamerStaticPad commentStamp: '' prior: 0! * Created by John M McIntosh on 3/10/08. * Copyright 2008 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com All rights reserved. * Written for Viewpoints Research Institute http://www.vpri.org/ * http://www.opensource.org/licenses/mit-license.php! GStreamerElement subclass: #GstElemFakeSink instanceVariableNames: 'sem semInd squeakSink' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! !GstElemFakeSink commentStamp: '' prior: 0! Has subclasses for audio/video. Has basically the same role as GStreamerElementForSqueakSinkAudio/Video, except: - puts semaphore management in the element instead of the pipeline - shorter name... easier to type when manually composing pipelines! GstElemFakeSink subclass: #GstElemSqueakAudioSink instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! GstElemFakeSink subclass: #GstElemSqueakVideoSink instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GStreamer-Base-Elements'! !GStreamer methodsFor: 'signals' stamp: 'JMM 3/29/2008 17:28'! allocateSqueakSinkAudioForElement: gstElement useSemaphoreIndex: semaphoreIndex ^self primSqueakSinkAllocate: 0 semaIndex: semaphoreIndex for: gstElement handle ! ! !GStreamer methodsFor: 'signals' stamp: 'JMM 3/30/2008 15:01'! allocateSqueakSinkVideoForElement: gstElement useSemaphoreIndex: semaphoreIndex ^self primSqueakSinkAllocate: 1 semaIndex: semaphoreIndex for: gstElement handle ! ! !GStreamer methodsFor: 'signals' stamp: 'JMM 4/2/2008 02:04'! allocateSqueakSrc: numberOfBytes forElement: gstElement useSemaphoreIndex: semaphoreIndex ^self primSqueakSrcAllocate: numberOfBytes semaIndex: semaphoreIndex for: gstElement handle ! ! !GStreamer methodsFor: 'signals' stamp: 'JMM 3/30/2008 20:43'! freeSqueakSink: sink sink ifNil: [^self]. self primSqueakSinkFreeFor: sink! ! !GStreamer methodsFor: 'pads' stamp: 'JMM 3/24/2008 11:14'! getOopFrom: anAddress ^self primgetoop: anAddress ! ! !GStreamer methodsFor: 'pads' stamp: 'JMM 3/24/2008 09:24'! interpreterProxy ^self primgetinterpreterproxy ! ! !GStreamer methodsFor: 'pads' stamp: 'JMM 3/19/2008 20:26'! linkElementSrc: srcElement toDest: destElement filtered: caps "Links src to dest using the given caps as filtercaps. The link must be from source to destination; the other direction will not be tried. The function looks for existing pads that aren't linked yet. It will request new pads if necessary. If multiple links are possible, only one is established. Make sure you have added your elements to a bin or pipeline with gst_bin_add() before trying to link them." ^self primgstelementlinkfiltered: srcElement handle dest: destElement handle filtered: caps handle "Returns : TRUE if the pads could be linked, FALSE otherwise. "! ! !GStreamer methodsFor: 'pads' stamp: 'JMM 3/18/2008 21:59'! linkPadSrc: srcElement toDest: destElement "Links the source pad and the sink pad." ^self primgstpadlink: srcElement handle dest: destElement handle "typedef enum { GST_PAD_LINK_OK = 0, GST_PAD_LINK_WRONG_HIERARCHY = -1, GST_PAD_LINK_WAS_LINKED = -2, GST_PAD_LINK_WRONG_DIRECTION = -3, GST_PAD_LINK_NOFORMAT = -4, GST_PAD_LINK_NOSCHED = -5, GST_PAD_LINK_REFUSED = -6 } GstPadLinkReturn; Result values from gst_pad_link and friends. GST_PAD_LINK_OK link succeeded GST_PAD_LINK_WRONG_HIERARCHY pads have no common grandparent GST_PAD_LINK_WAS_LINKED pad was already linked GST_PAD_LINK_WRONG_DIRECTION pads have wrong direction GST_PAD_LINK_NOFORMAT pads do not have common format GST_PAD_LINK_NOSCHED pads cannot cooperate in scheduling GST_PAD_LINK_REFUSED refused for some reason "! ! !GStreamer methodsFor: 'initialize-release' stamp: 'JMM 3/31/2008 14:55'! initialize initializedOk := self primgstinitcheck. initializedOk ifFalse: [self registryforksetenabled: false. "Possible OLPC issue" initializedOk := self primgstinitcheck]. "initializedOk is true if GStreamer was ok". initializedOk ifTrue: [version := self primgstversionstring].! ! !GStreamer methodsFor: 'initialize-release' stamp: 'JMM 3/31/2008 14:01'! registryforksetenabled: aBoolean self primgstregistryforksetenabled: aBoolean! ! !GStreamer methodsFor: 'accessing' stamp: 'JMM 3/10/2008 18:20'! initializedOk "initializedOk is true if GStreamer was ok". ^initializedOk! ! !GStreamer methodsFor: 'accessing' stamp: 'JMM 3/10/2008 20:29'! version ^version! ! !GStreamer methodsFor: 'elements' stamp: 'JMM 3/18/2008 21:53'! linkElementSrc: srcElement toDest: destElement "Links src to dest. The link must be from source to destination; the other direction will not be tried. The function looks for existing pads that aren't linked yet. It will request new pads if necessary. Such pads need to be released manualy when unlinking. If multiple links are possible, only one is established. Make sure you have added your elements to a bin or pipeline with gst_bin_add() before trying to link them." ^self primgstelementlink: srcElement handle dest: destElement handle! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgetinterpreterproxy self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgetoop: anAddress self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstbinnew: name self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstelementfactoryfind: name self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstelementfactorymake: factoryName name: name self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstelementlinkfiltered: srcOop dest: destOop filtered: capsOops self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstelementlink: srcOop dest: destOop self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstinitcheck self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpadlink: srcOop dest: destOop self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpipelinenew: name self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/31/2008 14:01'! primgstregistryforksetenabled: boolean self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstversionstring self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/29/2008 16:00'! primSqueakSinkAllocate: type semaIndex: semaphoreIndex for: gstElementOoop self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 3/29/2008 16:02'! primSqueakSinkFreeFor: oops self primitiveFailed ! ! !GStreamer methodsFor: 'system primitives' stamp: 'JMM 4/1/2008 17:34'! primSqueakSrcAllocate: numberOfBytes semaIndex: semaphoreIndex for: gstElementOoop self primitiveFailed ! ! !GStreamer class methodsFor: 'debugging' stamp: 'JMM 3/24/2008 17:26'! convertToMixedSound: aByteArray sampleRate: aRate | data leftAndRight ms | data := SampledSound convertBytesTo16BitSamples: aByteArray mostSignificantByteFirst: false. leftAndRight := data splitStereo. ms := MixedSound new add: (SampledSound samples: leftAndRight first samplingRate: aRate) pan: 0.0; add: (SampledSound samples: leftAndRight last samplingRate: aRate) pan: 1.0; yourself. ^ms ! ! !GStreamer class methodsFor: 'debugging' stamp: 'JMM 3/21/2008 13:27'! possiblePrintOfMessage: messageData | msgType | DiagnosticMsgToTranscript == true ifTrue: [Transcript show: (messageData at: 1);space. msgType := messageData at: 1. msgType = 'state-changed' ifTrue: [Transcript show: (messageData at: 2) getStateChanged]. msgType = 'error' ifTrue: [Transcript show: (messageData at: 2) getErrorAndDebugStrings]. Transcript cr.]! ! !GStreamer class methodsFor: 'singleton' stamp: 'JMM 3/10/2008 18:44'! default "self default" ^Default ifNil: [Default := self new].! ! !GStreamer class methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:26'! diagnosticMessagesToTranscript: aBoolean DiagnosticMsgToTranscript := aBoolean! ! !GStreamer class methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:00'! stateCodeToSymbol: state state = 0 ifTrue: [^#pending]. state = 1 ifTrue: [^#null]. state = 2 ifTrue: [^#ready]. state = 3 ifTrue: [^#paused]. state = 4 ifTrue: [^#playing]. ^#unknown ! ! !GStreamer class methodsFor: 'system primitives' stamp: 'JMM 3/18/2008 21:24'! gobjectFree: pointer "g_object free it, can pass ZERO passing bogus data, or double free, etc may crash the VM" self primobjectfree: pointer! ! !GStreamer class methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:08'! primobjectfree: pointer self primitiveFailed ! ! !GStreamer class methodsFor: 'class initialization' stamp: 'JMM 3/14/2008 14:31'! initialize "self initialize" Smalltalk addToStartUpList: self. Smalltalk addToShutDownList: self. ! ! !GStreamer class methodsFor: 'class initialization' stamp: 'JMM 3/14/2008 14:28'! shutDown: aboutToQuit aboutToQuit ifTrue: [GStreamerObject allSubInstances do: [:e | e handle: 0]].! ! !GStreamer class methodsFor: 'class initialization' stamp: 'JMM 3/10/2008 20:23'! startUp: resuming | | resuming ifFalse: [^ self]. Default := nil.! ! !GStreamerObject methodsFor: 'finalize' stamp: 'JMM 3/12/2008 11:44'! actAsExecutor super actAsExecutor. ! ! !GStreamerObject methodsFor: 'finalize' stamp: 'JMM 3/12/2008 12:40'! finalize "Ok on finalization we want to dispose of the object, but this can be overridden by subclasses, for example GStreamerElement objects defer to their pipeline to dispose of their elements" self objectUnref! ! !GStreamerObject methodsFor: 'finalize' stamp: 'JMM 3/12/2008 11:42'! register ^self class register: self! ! !GStreamerObject methodsFor: 'finalize' stamp: 'JMM 3/12/2008 11:42'! unregister ^self class unregister: self! ! !GStreamerObject methodsFor: 'error handling' stamp: 'jcg 4/24/2008 09:22'! error "#error is sent in quite a few places, but Object>>error wasn't implemented in Croquet (maybe it is in the OLPC images). For cross-image compatibility, I implemented it here." self error: 'unspecified error'.! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:26'! getKeyValueBoolean: aName "get Boolean value of Name" ^self primgobjectgetboolfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:26'! getKeyValueDouble: aName "get double float value of Name" ^self primgobjectgetdoublefrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:26'! getKeyValueFloat: aName "get float value of Name, noting that squeak handles everything in double precision anyway" ^self primgobjectgetfloatfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:26'! getKeyValueLongLong: aName "get long long value of Name" ^self primgobjectgetlonglongfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:26'! getKeyValueLong: aName "get long value of Name" ^self primgobjectgetlongfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:27'! getKeyValuePointer: aName "get pointer value of Name" ^self primgobjectgetpointerfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:27'! getKeyValueString: aName "get string value of Name" ^self primgobjectgetstringfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:27'! getKeyValueULongLong: aName "get long long value of Name" ^self primgobjectgetulonglongfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:27'! getKeyValueULong: aName "get unsigned long value of Name" ^self primgobjectgetulongfrom: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'get value' stamp: 'jcg 4/21/2008 15:27'! getSmalltalkObject: aName "get smalltalk object" ^self primgobjectgetsmalltalkobject: self handle name: aName nullTerminated ! ! !GStreamerObject methodsFor: 'state' stamp: 'jcg 4/22/2008 10:51'! getSimplifiedState "wait 500 milliseconds for state, that is expressed in nanoseconds" | results returnCode | results := self getState: (0.5*1000000000) asInteger. returnCode := results at: 1. returnCode = 0 ifTrue: [^#failure]. returnCode = 2 ifTrue: [^#pending]. returnCode = 3 ifTrue: [^#pending]. ^GStreamer stateCodeToSymbol: (results at: 2). ! ! !GStreamerObject methodsFor: 'state' stamp: 'JMM 3/13/2008 01:03'! getState: aTimeOutValue "Gets the state of the element" "Returns an array which is the GstStateChangeReturn value, the state, the pending state" | results | results := self primstelementgetstate: self handle timeOut: aTimeOutValue. ^results "Gets the state of the element. For elements that performed an ASYNC state change, as reported by gst_element_set_state(), this function will block up to the specified timeout value for the state change to complete. If the element completes the state change or goes into an error, this function returns immediately with a return value of GST_STATE_CHANGE_SUCCESS or GST_STATE_CHANGE_FAILURE respectively. For elements that did not return GST_STATE_CHANGE_ASYNC, this function returns the current and pending state immediately. This function returns GST_STATE_CHANGE_NO_PREROLL if the element successfully changed its state but is not able to provide data yet. This mostly happens for live sources that only produce data in the PLAYING state. While the state change return is equivalent to GST_STATE_CHANGE_SUCCESS, it is returned to the application to signal that some sink elements might not be able to complete their state change because an element is not producing data to complete the preroll. When setting the element to playing, the preroll will complete and playback will start. element : a GstElement to get the state of. state : a pointer to GstState to hold the state. Can be NULL. pending : a pointer to GstState to hold the pending state. Can be NULL. timeout : a GstClockTime to specify the timeout for an async state change or GST_CLOCK_TIME_NONE for infinite timeout. Returns : GST_STATE_CHANGE_SUCCESS if the element has no more pending state and the last state change succeeded, GST_STATE_CHANGE_ASYNC if the element is still performing a state change or GST_STATE_CHANGE_FAILURE if the last state change failed. MT safe. The possible return values from a state change function. Only GST_STATE_CHANGE_FAILURE is a real failure. GST_STATE_CHANGE_FAILURE the state change failed GST_STATE_CHANGE_SUCCESS the state change succeeded GST_STATE_CHANGE_ASYNC the state change will happen asynchronously GST_STATE_CHANGE_NO_PREROLL the state change succeeded but the element cannot produce data in PAUSED. This typically happens with live sources. typedef enum { GST_STATE_CHANGE_FAILURE = 0, GST_STATE_CHANGE_SUCCESS = 1, GST_STATE_CHANGE_ASYNC = 2, GST_STATE_CHANGE_NO_PREROLL = 3 } GstStateChangeReturn;" ! ! !GStreamerObject methodsFor: 'state' stamp: 'JMM 3/12/2008 11:12'! setStateTo: symbol "Sets the state of the element. This function will try to set the requested state by going through all the intermediary states and calling the class's state change function for each. This function can return GST_STATE_CHANGE_ASYNC, in which case the element will perform the remainder of the state change asynchronously in another thread. An application can use gst_element_get_state() to wait for the completion of the state change or it can wait for a state change message on the bus." | anInteger | anInteger := 1. symbol = #pending ifTrue: [anInteger := 0]. symbol = #null ifTrue: [anInteger := 1]. symbol = #ready ifTrue: [anInteger := 2]. symbol = #paused ifTrue: [anInteger := 3]. symbol = #playing ifTrue: [anInteger := 4]. ^self primgstelementsetstate: self handle to: anInteger "typedef enum { GST_STATE_VOID_PENDING = 0, GST_STATE_NULL = 1, GST_STATE_READY = 2, GST_STATE_PAUSED = 3, GST_STATE_PLAYING = 4 } GstState; GST_STATE_VOID_PENDING no pending state. GST_STATE_NULL the NULL state or initial state of an element GST_STATE_READY the element is ready to go to PAUSED GST_STATE_PAUSED the element is PAUSED GST_STATE_PLAYING the element is PLAYING • GST_STATE_NULL: this is the default state. This state will deallocate all resources held by the element. • GST_STATE_READY: in the ready state, an element has allocated all of its global resources, that is, resources that can be kept within streams. You can think about opening devices, allocating buffers and so on. However, the stream is not opened in this state, so the stream positions is automatically zero. If a stream was previously opened, it should be closed in this state, and position, properties and such should be reset. • GST_STATE_PAUSED: in this state, an element has opened the stream, but is not actively processing it. An element is allowed to modify a stream's position, read and process data and such to prepare for playback as soon as state is changed to PLAYING, but it is not allowed to play the data which would make the clock run. In summary, PAUSED is the same as PLAYING but without a running clock. Elements going into the PAUSED state should prepare themselves for moving over to the PLAYING state as soon as possible. Video or audio outputs would, for example, wait for data to arrive and queue it so they can play it right after the state change. Also, video sinks can already play the first frame (since this does not affect the clock yet). Autopluggers could use this same state transition to already plug together a pipeline. Most other elements, such as codecs or filters, do not need to explicitely do anything in this state, however. • GST_STATE_PLAYING: in the PLAYING state, an element does exactly the same as in the PAUSED state, except that the clock now runs." ! ! !GStreamerObject methodsFor: 'accessing' stamp: 'JMM 3/10/2008 22:28'! handle "Answer the value of handle" handle = 0 ifTrue: [self error]. ^ handle! ! !GStreamerObject methodsFor: 'accessing' stamp: 'JMM 3/12/2008 11:29'! handle: anObject "Set the value of handle" handle := anObject. handle = 0 ifFalse: [self register]! ! !GStreamerObject methodsFor: 'accessing' stamp: 'JMM 3/12/2008 12:41'! noCheckHandle "special use only, do not use" ^ handle! ! !GStreamerObject methodsFor: 'accessing' stamp: 'JMM 3/12/2008 12:41'! noCheckHandle: anObject "special use only do not use" handle := anObject. ! ! !GStreamerObject methodsFor: 'testing' stamp: 'JMM 3/13/2008 12:25'! isHandleSane ^self noCheckHandle notNil and: [self noCheckHandle > 0] ! ! !GStreamerObject methodsFor: 'initialize-release' stamp: 'JMM 3/17/2008 01:42'! objectUnref "Use release instead. Decrements the reference count on object. If reference count hits zero, destroy object. This function does not take the lock on object as it relies on atomic refcounting. The unref method should never be called with the LOCK held since this might deadlock the dispose function." handle = 0 ifTrue: [^self]. self primgstobjectunref: self handle. handle := 0.! ! !GStreamerObject methodsFor: 'initialize-release' stamp: 'JMM 3/12/2008 11:45'! release self unregister. self objectUnref! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetboolfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetdoublefrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetfloatfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetlongfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetlonglongfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetpointerfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetsmalltalkobject: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetstringfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetulongfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectgetulonglongfrom: obj name: aName self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectsetboolon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectsetdoubleon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectsetfloaton: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectsetlonglongon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgobjectsetlongon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgobjectsetpointeron: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgobjectsetstringon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgobjectsetulonglongon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgobjectsetulongon: obj name: aName value: aValue self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstelementsetstate: aHandle to: anInteger self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstmessageunref: obj self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstobjectunref: obj self primitiveFailed ! ! !GStreamerObject methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primstelementgetstate: aHandle timeOut: gstClockTime self primitiveFailed ! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:27'! setKey: aName toBooleanValue: aValue "set value of Name to Boolean" self primgobjectsetboolon: self handle name: aName nullTerminated value: aValue ! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:27'! setKey: aName toDoubleValue: aValue "set value of Name to double" self primgobjectsetdoubleon: self handle name: aName nullTerminated value: aValue! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:27'! setKey: aName toFloatValue: aValue "set value of Name to float" self primgobjectsetfloaton: self handle name: aName nullTerminated value: aValue! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:27'! setKey: aName toLongLongValue: aValue "set value of Name to longlong" self primgobjectsetlonglongon: self handle name: aName nullTerminated value: aValue! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:27'! setKey: aName toLongValue: aValue "set value of Name to long" self primgobjectsetlongon: self handle name: aName nullTerminated value: aValue! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:28'! setKey: aName toPointerValue: aValue "set value of Name to pointer" self primgobjectsetpointeron: self handle name: aName nullTerminated value: aValue! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:28'! setKey: aName toStringValue: aValue "set value of Name to string" self primgobjectsetstringon: self handle name: aName nullTerminated value: (aValue copyWith: (Character value: 0)) ! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:28'! setKey: aName toUnsignedLongLongValue: aValue "set value of Name to unsigned long long" self primgobjectsetulonglongon: self handle name: aName nullTerminated value: aValue! ! !GStreamerObject methodsFor: 'set value' stamp: 'jcg 4/21/2008 15:28'! setKey: aName toUnsignedLongValue: aValue "set value of Name to unsigned long" self primgobjectsetulongon: self handle name: aName nullTerminated value: aValue! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/18/2008 21:42'! havePending "Check if there are pending messages on the bus that should be handled. bus : a GstBus to check Returns : TRUE if there are messages on the bus to be handled, FALSE otherwise. MT safe. " ^self primgstbushavepending: self handle.! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/18/2008 21:42'! peek "Peek the message on the top of the bus' queue. The message will remain on the bus' message queue. A reference is returned, and needs to be unreffed by the caller. bus : a GstBus Returns : The GstMessage that is on the bus, or NULL if the bus is empty. MT safe. " | data | data := self primgstbuspeek: self handle. data = 0 ifTrue: [^nil]. ^GStreamerMessage handle: data! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/18/2008 21:43'! pop "Get a message from the bus. bus : a GstBus to pop Returns : The GstMessage that is on the bus, or NULL if the bus is empty. The message is taken from the bus and needs to be unreffed with gst_message_unref() after usage. MT safe. " | data | data := self primgstbuspop: self handle. data = 0 ifTrue: [^nil]. ^GStreamerMessage handle: data! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/18/2008 21:44'! popFilter: aMessageType | data | data := self primgstbuspop: self handle filter: aMessageType. data = 0 ifTrue: [^nil]. ^GStreamerMessage handle: data "typedef enum { GST_MESSAGE_UNKNOWN = 0, GST_MESSAGE_EOS = (1 << 0), GST_MESSAGE_ERROR = (1 << 1), GST_MESSAGE_WARNING = (1 << 2), GST_MESSAGE_INFO = (1 << 3), GST_MESSAGE_TAG = (1 << 4), GST_MESSAGE_BUFFERING = (1 << 5), GST_MESSAGE_STATE_CHANGED = (1 << 6), GST_MESSAGE_STATE_DIRTY = (1 << 7), GST_MESSAGE_STEP_DONE = (1 << 8), GST_MESSAGE_CLOCK_PROVIDE = (1 << 9), GST_MESSAGE_CLOCK_LOST = (1 << 10), GST_MESSAGE_NEW_CLOCK = (1 << 11), GST_MESSAGE_STRUCTURE_CHANGE = (1 << 12), GST_MESSAGE_STREAM_STATUS = (1 << 13), GST_MESSAGE_APPLICATION = (1 << 14), GST_MESSAGE_ELEMENT = (1 << 15), GST_MESSAGE_SEGMENT_START = (1 << 16), GST_MESSAGE_SEGMENT_DONE = (1 << 17), GST_MESSAGE_DURATION = (1 << 18), GST_MESSAGE_LATENCY = (1 << 19), GST_MESSAGE_ASYNC_START = (1 << 20), GST_MESSAGE_ASYNC_DONE = (1 << 21), GST_MESSAGE_ANY = ~0 } GstMessageType; The different message types that are available. GST_MESSAGE_UNKNOWN an undefined message GST_MESSAGE_EOS end-of-stream reached in a pipeline. The application will only receive this message in the PLAYING state and every time it sets a pipeline to PLAYING that is in the EOS state. The application can perform a flushing seek in the pipeline, which will undo the EOS state again. GST_MESSAGE_ERROR an error occured. Whe the application receives an error message it should stop playback of the pipeline and not assume that more data will be played. GST_MESSAGE_WARNING a warning occured. GST_MESSAGE_INFO an info message occured GST_MESSAGE_TAG a tag was found. GST_MESSAGE_BUFFERING the pipeline is buffering. When the application receives a buffering message in the PLAYING state for a non-live pipeline it must PAUSE the pipeline until the buffering completes, when the percentage field in the message is 100%. For live pipelines, no action must be performed and the buffering percentage can be used to inform the user about the progress. GST_MESSAGE_STATE_CHANGED a state change happened GST_MESSAGE_STATE_DIRTY an element changed state in a streaming thread. This message is deprecated. GST_MESSAGE_STEP_DONE a framestep finished. This message is not yet implemented. GST_MESSAGE_CLOCK_PROVIDE an element notifies its capability of providing a clock. This message is used internally and never forwarded to the application. GST_MESSAGE_CLOCK_LOST The current clock as selected by the pipeline became unusable. The pipeline will select a new clock on the next PLAYING state change. GST_MESSAGE_NEW_CLOCK a new clock was selected in the pipeline. GST_MESSAGE_STRUCTURE_CHANGE the structure of the pipeline changed. Not implemented yet. GST_MESSAGE_STREAM_STATUS status about a stream, emitted when it starts, stops, errors, etc.. Not implemented yet. GST_MESSAGE_APPLICATION message posted by the application, possibly via an application-specific element. GST_MESSAGE_ELEMENT element-specific message, see the specific element's documentation GST_MESSAGE_SEGMENT_START pipeline started playback of a segment. This message is used internally and never forwarded to the application. GST_MESSAGE_SEGMENT_DONE pipeline completed playback of a segment. This message is forwarded to the application after all elements that posted GST_MESSAGE_SEGMENT_START posted a GST_MESSAGE_SEGMENT_DONE message. GST_MESSAGE_DURATION The duration of a pipeline changed. The application can get the new duration with a duration query. GST_MESSAGE_LATENCY Posted by elements when their latency changes. The pipeline will calculate and distribute a new latency. Since: 0.10.12 GST_MESSAGE_ASYNC_START Posted by elements when they start an ASYNC state change. This message is not forwarded to the application but is used internally. Since: 0.10.13. GST_MESSAGE_ASYNC_DONE Posted by elements when they complete an ASYNC state change. The application will only receive this message from the toplevel pipeline. Since: 0.10.13 GST_MESSAGE_ANY mask for all of the above messages. Get a message matching type from the bus. Will discard all messages on the bus that do not match type and that have been posted before the first message that does match type. If there is no message matching type on the bus, all messages will be discarded. bus : a GstBus to pop types : message types to take into account Returns : The next GstMessage matching type that is on the bus, or NULL if the bus is empty or there is no message matching type. The message is taken from the bus and needs to be unreffed with gst_message_unref() after usage. MT safe. "! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/25/2008 19:22'! popNextBusMessage | message | message := self pop. message ifNotNil: [^Array with: message typeString with: message]. ^nil. ! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 4/2/2008 19:00'! processStateChangeMessage: messageData against: aMessage | stateData checkmessage whoPostedMessage messageWas | checkmessage := messageData at: 1. checkmessage = aMessage ifTrue: [^true]. messageWas := messageData at: 2. whoPostedMessage := messageWas getMessagePostingSrcElement. (aMessage isCollection and: [(aMessage at: 1) = checkmessage]) ifTrue: [stateData := messageWas getStateChanged. ((aMessage at: 3) = (stateData at: (aMessage at: 2)) and: [((aMessage at: 4) handle) = whoPostedMessage]) ifTrue: [^true]]. ^false ! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/25/2008 19:26'! waitUntilErrorOrMessage: aMessage uptoMilliseconds: aNumberOfMilliSeconds ^self waitUntilErrorOrMessage: aMessage uptoMilliseconds: aNumberOfMilliSeconds do: [] waitBlock: [(Delay forMilliseconds: 10) wait]! ! !GStreamerBus methodsFor: 'accessing' stamp: 'jcg 4/22/2008 10:51'! waitUntilErrorOrMessage: aMessage uptoMilliseconds: aNumberOfMilliSeconds do: aBlock waitBlock: aWaitBlock | messageData was now checkmessage | was := Time millisecondClockValue. [messageData := self popNextBusMessage. messageData ifNotNil: [GStreamer possiblePrintOfMessage: messageData. checkmessage := messageData at: 1. (checkmessage = 'state-changed' and: [self processStateChangeMessage: messageData against: aMessage]) ifTrue: [^messageData]. checkmessage = aMessage ifTrue: [^messageData]. checkmessage = 'error' ifTrue: [^messageData]]. messageData release. aBlock value. aWaitBlock value. now := Time millisecondsSince: was. now > aNumberOfMilliSeconds ifTrue: [^nil]] repeat.! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/25/2008 17:35'! waitUntilErrorOrMessage: aMessage uptoSeconds: aNumberOfSeconds ^self waitUntilErrorOrMessage: aMessage uptoMilliseconds: aNumberOfSeconds*1000! ! !GStreamerBus methodsFor: 'accessing' stamp: 'JMM 3/25/2008 19:26'! waitUntilErrorOrMessage: aMessage uptoSeconds: aNumberOfSeconds do: aBlock ^self waitUntilErrorOrMessage: aMessage uptoMilliseconds: aNumberOfSeconds*1000 do: aBlock waitBlock: [(Delay forMilliseconds: 10) wait]! ! !GStreamerBus methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgstbushavepending: obj self primitiveFailed ! ! !GStreamerBus methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgstbuspeek: obj self primitiveFailed ! ! !GStreamerBus methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgstbuspop: obj self primitiveFailed ! ! !GStreamerBus methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgstbuspop: obj filter: filter self primitiveFailed ! ! !GStreamerCaps methodsFor: 'finalize' stamp: 'JMM 3/17/2008 11:32'! finalize "Do nothing, we want the pipeline or the bin to do the finalization" self noCheckHandle: 0! ! !GStreamerCaps methodsFor: 'accessing' stamp: 'JMM 3/18/2008 21:44'! getString "Converts caps to a string representation." ^self primgstcapstostring: self handle.! ! !GStreamerCaps methodsFor: 'system primitives' stamp: 'JMM 3/29/2008 16:46'! primgstcapsfromstring: gstCapsOop self primitiveFailed ! ! !GStreamerCaps methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgstcapstostring: gstCapsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/27/2008 12:19'! baseSeekToTime: aTimeValueInNanoSeconds ^self seekComplexRate: 1.0 format: 3 flags: (1 << 0) curType: 2 cur: aTimeValueInNanoSeconds asInteger stopType: 0 stop: -1! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/28/2008 20:01'! baseSimpleSeekToTime: aTimeValueInNanoSeconds ^self seekSimpleFormat: 3 flags: (1 << 0) cur: aTimeValueInNanoSeconds ! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 10:00'! convertFromPercentToTime: aValue | convertedValue | convertedValue := (aValue * 10000.0) asInteger. ^self convert: convertedValue fromFormat: 5 toFormat: 3! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 10:02'! convertFromTimeToPercent: aValue | data | data := self convert: aValue fromFormat: 3 toFormat: 5. data ifNil: [^nil]. ^data / 10000.0 ! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:45'! convert: aValue fromFormat: fromFormat toFormat: toFormat | data | data := self primgstelementqueryconvert: self handle sourceformat: fromFormat value: aValue destformat: toFormat. (data at: 1) ifFalse: [^nil]. ^data at: 2 "typedef enum { GST_FORMAT_UNDEFINED = 0, /* must be first in list */ GST_FORMAT_DEFAULT = 1, GST_FORMAT_BYTES = 2, GST_FORMAT_TIME = 3, GST_FORMAT_BUFFERS = 4, GST_FORMAT_PERCENT = 5 } GstFormat; Standard predefined formats GST_FORMAT_UNDEFINED undefined format GST_FORMAT_DEFAULT the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video. GST_FORMAT_BYTES bytes GST_FORMAT_TIME time in nanoseconds GST_FORMAT_BUFFERS buffers GST_FORMAT_PERCENT percentage of stream "! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:32'! queryDurationBuffers ^self queryDuration: 4! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:32'! queryDurationBytes ^self queryDuration: 2! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:32'! queryDurationDefault ^self queryDuration: 1! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/27/2008 12:29'! queryDurationInSecondsOrNilAsFloat "Note the tone pipeline would return -1 as the duration because it plays forever" | time | time := self queryDuration: 3. time ifNil: [^nil]. time = -1 ifTrue: [^nil]. ^time/1000000000.0! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 10:56'! queryDurationPercent | data | data := self queryDuration: 5. data ifNil: [^nil]. ^(self queryDuration: 5) / 10000.0 "GST_FORMAT_PERCENT_SCALE G_GINT64_CONSTANT (10000)"! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 10:43'! queryDurationTime "Note the tone pipeline would return -1 as the duration because it plays forever" ^self queryDuration: 3! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:32'! queryDurationUndefined ^self queryDuration: 0! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:38'! queryDuration: aFormat | data | data := self primgstelementqueryduration: self handle format: aFormat. (data at: 1) ifFalse: [^nil]. (data at: 2) = aFormat ifFalse: [^nil]. ^data at: 3 "typedef enum { GST_FORMAT_UNDEFINED = 0, /* must be first in list */ GST_FORMAT_DEFAULT = 1, GST_FORMAT_BYTES = 2, GST_FORMAT_TIME = 3, GST_FORMAT_BUFFERS = 4, GST_FORMAT_PERCENT = 5 } GstFormat; Standard predefined formats GST_FORMAT_UNDEFINED undefined format GST_FORMAT_DEFAULT the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video. GST_FORMAT_BYTES bytes GST_FORMAT_TIME time in nanoseconds GST_FORMAT_BUFFERS buffers GST_FORMAT_PERCENT percentage of stream "! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:39'! queryPositionBuffers ^self queryPosition: 4! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:39'! queryPositionBytes ^self queryPosition: 2! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:39'! queryPositionDefault ^self queryPosition: 1! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 10:58'! queryPositionPercent | data | data := self queryPosition: 5. data ifNil:[^nil]. ^(self queryPosition: 5) / 10000.0 "GST_FORMAT_PERCENT_SCALE G_GINT64_CONSTANT (10000)"! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:40'! queryPositionTime ^self queryPosition: 3! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:40'! queryPositionUndefined ^self queryPosition: 0! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 09:39'! queryPosition: aFormat | data | data := self primgstelementqueryposition: self handle format: aFormat. (data at: 1) ifFalse: [^nil]. (data at: 2) = aFormat ifFalse: [^nil]. ^data at: 3 "typedef enum { GST_FORMAT_UNDEFINED = 0, /* must be first in list */ GST_FORMAT_DEFAULT = 1, GST_FORMAT_BYTES = 2, GST_FORMAT_TIME = 3, GST_FORMAT_BUFFERS = 4, GST_FORMAT_PERCENT = 5 } GstFormat; Standard predefined formats GST_FORMAT_UNDEFINED undefined format GST_FORMAT_DEFAULT the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video. GST_FORMAT_BYTES bytes GST_FORMAT_TIME time in nanoseconds GST_FORMAT_BUFFERS buffers GST_FORMAT_PERCENT percentage of stream "! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 10:08'! seekComplexRate: aRate format: aFormat flags: aFlags curType: aCurrentType cur: currentPosition stopType: aStopType stop: stopPosition ^self primitivegstelementseek: self handle rate: aRate format: aFormat flags: aFlags curType: aCurrentType cur: currentPosition stopType: aStopType stop: stopPosition "typedef enum { GST_FORMAT_UNDEFINED = 0, /* must be first in list */ GST_FORMAT_DEFAULT = 1, GST_FORMAT_BYTES = 2, GST_FORMAT_TIME = 3, GST_FORMAT_BUFFERS = 4, GST_FORMAT_PERCENT = 5 } GstFormat; Standard predefined formats GST_FORMAT_UNDEFINED undefined format GST_FORMAT_DEFAULT the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video. GST_FORMAT_BYTES bytes GST_FORMAT_TIME time in nanoseconds GST_FORMAT_BUFFERS buffers GST_FORMAT_PERCENT percentage of stream typedef enum { GST_SEEK_FLAG_NONE = 0, GST_SEEK_FLAG_FLUSH = (1 << 0), GST_SEEK_FLAG_ACCURATE = (1 << 1), GST_SEEK_FLAG_KEY_UNIT = (1 << 2), GST_SEEK_FLAG_SEGMENT = (1 << 3) } GstSeekFlags; Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags can be used together. A non flushing seek might take some time to perform as the currently playing data in the pipeline will not be cleared. An accurate seek might be slower for formats that don't have any indexes or timestamp markers in the stream. Specifying this flag might require a complete scan of the file in those cases. When performing a segment seek: after the playback of the segment completes, no EOS will be emmited by the element that performed the seek, but a GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element. When this message is posted, it is possible to send a new seek event to continue playback. With this seek method it is possible to perform seemless looping or simple linear editing. GST_SEEK_FLAG_NONE no flag GST_SEEK_FLAG_FLUSH flush pipeline GST_SEEK_FLAG_ACCURATE accurate position is requested, this might be considerably slower for some formats. GST_SEEK_FLAG_KEY_UNIT seek to the nearest keyframe. This might be faster but less accurate. GST_SEEK_FLAG_SEGMENT perform a segment seek. typedef enum { /* one of these */ GST_SEEK_TYPE_NONE = 0, GST_SEEK_TYPE_CUR = 1, GST_SEEK_TYPE_SET = 2, GST_SEEK_TYPE_END = 3 } GstSeekType; The different types of seek events. When constructing a seek event with gst_event_new_seek(), a format, a seek method and optional flags are to be provided. The seek event is then inserted into the graph with gst_pad_send_event() or gst_element_send_event(). GST_SEEK_TYPE_NONE no change in position is required GST_SEEK_TYPE_CUR change relative to current position GST_SEEK_TYPE_SET absolute position is requested GST_SEEK_TYPE_END relative position to duration is requested "! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 22:45'! seekPlusMinusFrames: aFrameCount "Ok try to seek by frame, this might not work" ^self seekComplexRate: 1.0 format: 1 flags: (0 << 1) curType: 1 cur: aFrameCount stopType: 0 stop: -1! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 22:58'! seekSetRate: aRateFloatNumber self error. ^self seekComplexRate: aRateFloatNumber format: 0 flags: (0 << 1 ) curType: 0 cur: 0 stopType: 0 stop: -1! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/28/2008 20:00'! seekSimpleFormat: aFormat flags: aFlags cur: currentPosition ^self primitivegstelementseek: self handle format: aFormat flags: aFlags cur: currentPosition "typedef enum { GST_FORMAT_UNDEFINED = 0, /* must be first in list */ GST_FORMAT_DEFAULT = 1, GST_FORMAT_BYTES = 2, GST_FORMAT_TIME = 3, GST_FORMAT_BUFFERS = 4, GST_FORMAT_PERCENT = 5 } GstFormat; Standard predefined formats GST_FORMAT_UNDEFINED undefined format GST_FORMAT_DEFAULT the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video. GST_FORMAT_BYTES bytes GST_FORMAT_TIME time in nanoseconds GST_FORMAT_BUFFERS buffers GST_FORMAT_PERCENT percentage of stream typedef enum { GST_SEEK_FLAG_NONE = 0, GST_SEEK_FLAG_FLUSH = (1 << 0), GST_SEEK_FLAG_ACCURATE = (1 << 1), GST_SEEK_FLAG_KEY_UNIT = (1 << 2), GST_SEEK_FLAG_SEGMENT = (1 << 3) } GstSeekFlags; Flags to be used with gst_element_seek() or gst_event_new_seek(). All flags can be used together. A non flushing seek might take some time to perform as the currently playing data in the pipeline will not be cleared. An accurate seek might be slower for formats that don't have any indexes or timestamp markers in the stream. Specifying this flag might require a complete scan of the file in those cases. When performing a segment seek: after the playback of the segment completes, no EOS will be emmited by the element that performed the seek, but a GST_MESSAGE_SEGMENT_DONE message will be posted on the bus by the element. When this message is posted, it is possible to send a new seek event to continue playback. With this seek method it is possible to perform seemless looping or simple linear editing. GST_SEEK_FLAG_NONE no flag GST_SEEK_FLAG_FLUSH flush pipeline GST_SEEK_FLAG_ACCURATE accurate position is requested, this might be considerably slower for some formats. GST_SEEK_FLAG_KEY_UNIT seek to the nearest keyframe. This might be faster but less accurate. GST_SEEK_FLAG_SEGMENT perform a segment seek. "! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/20/2008 22:57'! seekToPercent: aPercent | value | self error. value := (aPercent * 10000.0) asInteger. ^self seekComplexRate: 1.0 format: 5 flags: (0 << 1) curType: 2 cur: value stopType: 0 stop: -1! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/27/2008 13:28'! seekToTimeInSecondsEnsurePlaying: seconds | flag state | flag := self seekToTimeInSeconds: seconds. state := self getSimplifiedState. ((state = #paused or: [state = #null]) and: [flag]) ifTrue: [self setStateTo: #playing]. ^flag ! ! !GStreamerElement methodsFor: 'position duration' stamp: 'JMM 3/27/2008 13:24'! seekToTimeInSeconds: seconds | state totalTime | seconds < 0 ifTrue: [self error]. state := self getSimplifiedState. state = #null ifTrue: [self setStateTo: #paused]. totalTime := self queryDurationInSecondsOrNilAsFloat. (totalTime notNil and: [seconds asFloat > totalTime]) ifTrue: [self setStateTo: #null]. ^self baseSeekToTime: seconds*1000000000.! ! !GStreamerElement methodsFor: 'finalize' stamp: 'JMM 3/17/2008 10:25'! finalize "Do nothing, we want the pipeline or the bin to do the finalization" ! ! !GStreamerElement methodsFor: 'finalize' stamp: 'jcg 4/22/2008 10:51'! finalizeViaPipeLine self requestPads do: [:p | self releasePad: p]. self noCheckHandle: 0. "metadata element 2 is via g_object_class_list_properties which must be freed when done" metadata ifNotNil: [GStreamer default gobjectFree: (metadata at: 2). metadata at: 2 put: 0].! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:29'! getPropertyBool: propertyName "Returns an array element 1 is default value, number 2 is the boolean value" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyboolatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:30'! getPropertyDouble: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertydoubleatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:30'! getPropertyEnum: propertyName "Returns an array element 1 is default value, number 2 is the value" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyenumatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:31'! getPropertyFloat: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyfloatatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:31'! getPropertyInt: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyintatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:43'! getPropertyLongLong: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertylonglongatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:31'! getPropertyLong: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertylongatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:37'! getPropertyMetaData: propertyName | data flag characters | data := self metaData at: propertyName. flag := data at: 3. characters := #none. characters := flag = 1 ifTrue: [#readonly] ifFalse: [characters]. characters := flag = 2 ifTrue: [#writeonly] ifFalse: [characters]. characters := flag = 3 ifTrue: [#readwrite] ifFalse: [characters]. characters := flag = 4 ifTrue: [#control] ifFalse: [characters]. characters := flag = 5 ifTrue: [#controlread] ifFalse: [characters]. characters := flag = 6 ifTrue: [#controlwrite] ifFalse: [characters]. characters := flag = 7 ifTrue: [#controlreadwrite] ifFalse: [characters]. data at: 3 put: characters. ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:33'! getPropertyPointer: propertyName "Returns an array element 1 is default value, number 2 is the value" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertypointeratIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:33'! getPropertyString: propertyName | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertystringatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:33'! getPropertyUInt: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyuintatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:34'! getPropertyULongLong: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyulonglongatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:34'! getPropertyULong: propertyName "Returns an array element 1 is default value, number 2 is the value number 3 is the min, number 4 is the max" | theIndex data | theIndex := self metaDataIndexOf: propertyName. data := self primgobjectclasslistpropertyulongatIndex: theIndex for: (metadata at: 2). ^data! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 15:10'! metaData "Dictionary(propertyName->#('name' 'description' flags type index)) flags: read (bit 1), write (bit 2), controllable (bit 3) type: INVALID(0) NONE(1) INTERFACE(2) CHAR(3) UCHAR(4) BOOLEAN(5) INT(6) UINT(7) LONG(8) ULONG(9) INT64(10) UINT64(11) ENUM(12) FLAGS(13) FLOAT(14) DOUBLE(15) STRING(16) POINTER(17) BOXED(18) PARAM(19) OBJECT(20)" | properties size | metadata ifNil: [ metadata := self primgobjectclasslistproperties: self handle. size := metadata at: 1. metadata at: 1 put: ( ((0 to: size-1) collect: [:i | properties := self primgobjectclasslistpropertymetaDataatIndex: i for: (metadata at: 2). (properties at: 1) -> (properties copyWith: i)]) as: Dictionary)]. ^metadata at: 1 ! ! !GStreamerElement methodsFor: 'meta data' stamp: 'bf 3/31/2008 14:12'! metaDataIndexOf: propertyName ^(self metaData at: propertyName) at: 5 ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'bf 3/31/2008 12:58'! primgobjectclasslistproperties: element "Returns an array element 1 is nubmer of properties, number 2 is array of GParamSpec* for all properties of a class." self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgobjectclasslistpropertyboolatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgobjectclasslistpropertydoubleatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertyenumatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertyfloatatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertyintatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertylongatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertylonglongatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertymetaDataatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertypointeratIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertystringatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertyuintatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertyulongatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgobjectclasslistpropertyulonglongatIndex: index for: propertyspecsOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/29/2008 15:50'! primgsignalconnect: element signal: aString data: dataOops self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgstelementadd: elementOop pad: aPadOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgstelementgetcompatiblepad: element pad: aPad capsFilter: caps self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgstelementgetrequestpad: element name: name self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgstelementgetstaticpad: element name: name self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:03'! primgstelementgsignalconnect: element for: name to: anArray self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementqueryconvert: aHandle sourceformat: srcformat value: valOop destformat: destformat self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementqueryduration: aHandle format: aFormat self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementqueryposition: aHandle format: aFormat self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primigstelementreleaserequestpad: element pad: pad self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/28/2008 19:58'! primitivegstelementseek: elementOop format: aFormat flags: aFlags cur: curOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primitivegstelementseek: elementOop rate: aRate format: aFormat flags: aFlags curType: aCurrentType cur: curOop stopType: aStopType stop: stopOop self primitiveFailed ! ! !GStreamerElement methodsFor: 'pads' stamp: 'JMM 3/17/2008 12:38'! releasePad: aPad aPad releasePadForElement: self "Makes the element free the previously requested pad as obtained with gst_element_get_request_pad()."! ! !GStreamerElement methodsFor: 'pads' stamp: 'jcg 4/21/2008 15:23'! requestPadByName: aName | pad padHandle | padHandle := self primgstelementgetrequestpad: self handle name: aName nullTerminated. padHandle = 0 ifTrue: [^nil]. pad := GStreamerRequestPad handle: padHandle. self requestPads add: pad. ^pad "Retrieves a pad from the element by name. This version only retrieves request pads. The pad should be released with gst_element_release_request_pad(). element : a GstElement to find a request pad of. name : the name of the request GstPad to retrieve. Returns : requested GstPad if found, otherwise NULL. Release after usage. "! ! !GStreamerElement methodsFor: 'pads' stamp: 'JMM 3/17/2008 10:21'! requestPads ^requestPads ifNil: [requestPads := Set new].! ! !GStreamerElement methodsFor: 'pads' stamp: 'JMM 3/17/2008 12:59'! requestPadThatIsCompatibleTo: aPad capsFilter: caps | pad padhandle | caps ifNil: [padhandle := self primgstelementgetcompatiblepad: self handle pad: aPad handle capsFilter: 0.] ifNotNil: [padhandle := self primgstelementgetcompatiblepad: self handle pad: aPad handle capsFilter: caps handle.]. padhandle = 0 ifTrue: [^nil]. pad := GStreamerPad handle: padhandle. self requestPads add: pad. ^pad "GstPad* gst_element_get_compatible_pad (GstElement *element, GstPad *pad, const GstCaps *caps); Looks for an unlinked pad to which the given pad can link. It is not guaranteed that linking the pads will work, though it should work in most cases. element : a GstElement in which the pad should be found. pad : the GstPad to find a compatible one for. caps : the GstCaps to use as a filter. Returns : the GstPad to which a link can be made, or NULL if one cannot be found. gst_object_unref() after usage. "! ! !GStreamerElement methodsFor: 'pads' stamp: 'jcg 4/21/2008 15:23'! requestStaticPadByName: aName | pad padHandle | padHandle := self primgstelementgetstaticpad: self handle name: aName nullTerminated. padHandle ifNil: [^nil]. pad := GStreamerStaticPad handle: padHandle. self requestPads add: pad. ^pad "Retrieves a pad from element by name. This version only retrieves already-existing (i.e. 'static') pads. element : a GstElement to find a static pad of. name : the name of the static GstPad to retrieve. Returns : the requested GstPad if found, otherwise NULL. unref after usage. MT safe. "! ! !GStreamerElement methodsFor: 'utility' stamp: 'jcg 4/21/2008 15:23'! requestCallBackForSignal: aName useArray: anArray "Ok for this callback signal (perhaps only pad add) we need to invoke the link to a target pad based on the newly created pad's caps data" self primgstelementgsignalconnect: self handle for: aName nullTerminated to: (anArray collect: [:e | e handle]) asWordArray! ! !GStreamerElement methodsFor: 'signal' stamp: 'jcg 4/21/2008 15:24'! signal: aString data: dataOops self primgsignalconnect: self handle signal: aString nullTerminated data: dataOops! ! !GStreamerBin methodsFor: 'adding' stamp: 'JMM 3/18/2008 21:35'! addElement: aElement "Adds the given element to the bin. Sets the element's parent, and thus takes ownership of the element. An element can only be added to one bin. If the element's pads are linked to other pads, the pads will be unlinked before the element is added to the bin." self elementsInPipe add: aElement. ^self primgstbinadd: self handle element: aElement handle! ! !GStreamerBin methodsFor: 'adding' stamp: 'JMM 3/18/2008 00:33'! addPad: aPad | pad padHandle | padHandle := self primgstelementadd: self handle pad: aPad handle. padHandle = 0 ifTrue: [^nil]. pad := GStreamerPad handle: padHandle. ^pad "Adds a pad (link point) to element. pad's parent will be set to element; see gst_object_set_parent() for refcounting information. Pads are not automatically activated so elements should perform the needed steps to activate the pad in case this pad is added in the PAUSED or PLAYING state. See gst_pad_set_active() for more information about activating pads. The pad and the element should be unlocked when calling this function. This function will emit the GstElement::pad-added signal on the element."! ! !GStreamerBin methodsFor: 'accessing' stamp: 'JMM 3/18/2008 22:13'! elementsInPipe ^elementsInPipe ifNil: [elementsInPipe := OrderedCollection new].! ! !GStreamerBin methodsFor: 'accessing' stamp: 'JMM 3/20/2008 11:53'! findElementCalled: aName ^self elementsInPipe detect: [:e | (e getKeyValueString: 'name') = aName] ifNone: [nil]! ! !GStreamerBin methodsFor: 'finalize' stamp: 'JMM 4/3/2008 19:34'! finalize "On a pipeline finalize we need to check to see if any elements exist, if so set their handles to 0" handle = 0 ifFalse: [self setStateTo: #null. self elementsInPipe do: [:e | e finalizeViaPipeLine]]. super finalize.! ! !GStreamerBin methodsFor: 'finalize' stamp: 'JMM 3/27/2008 11:11'! finalizeViaPipeLine self finalize. self noCheckHandle: 0. ! ! !GStreamerBin methodsFor: 'finalize' stamp: 'JMM 3/26/2008 23:34'! release self finalize. super release.! ! !GStreamerBin methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:02'! primgstbinadd: binOOp element: elementOop self primitiveFailed ! ! !GStreamerElementFactory methodsFor: 'creation' stamp: 'jcg 4/21/2008 15:24'! elementFactoryCreate: name "Create a new element of the type defined by the given elementfactory. It will be given the name supplied, since all elements require a name as their first argument." ^GStreamerElementFactory handle: (self primgstelementfactorycreate: self handle name: name nullTerminated)! ! !GStreamerElementFactory methodsFor: 'accessing' stamp: 'JMM 3/10/2008 22:06'! getAuthorName ^self primgstelementfactorygetauthor: self handle! ! !GStreamerElementFactory methodsFor: 'accessing' stamp: 'JMM 3/10/2008 22:00'! getDescription ^self primgstelementfactorygetdescription: self handle! ! !GStreamerElementFactory methodsFor: 'accessing' stamp: 'JMM 3/10/2008 22:27'! getKlass ^self primgstelementfactorygetklass: self handle! ! !GStreamerElementFactory methodsFor: 'accessing' stamp: 'JMM 3/10/2008 22:01'! getLongName ^self primgstelementfactorygetlongname: self handle! ! !GStreamerElementFactory methodsFor: 'accessing' stamp: 'JMM 3/10/2008 22:23'! getURIType ^self primgstelementfactorygeturitype: self handle! ! !GStreamerElementFactory methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementfactorycreate: factory name: name self primitiveFailed ! ! !GStreamerElementFactory methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementfactorygetauthor: factory self primitiveFailed ! ! !GStreamerElementFactory methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementfactorygetdescription: factory self primitiveFailed ! ! !GStreamerElementFactory methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementfactorygetklass: factory self primitiveFailed ! ! !GStreamerElementFactory methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementfactorygetlongname: factory self primitiveFailed ! ! !GStreamerElementFactory methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstelementfactorygeturitype: factory self primitiveFailed ! ! !GStreamerElementForSqueakSinkAudio methodsFor: 'accessing' stamp: 'JMM 3/29/2008 16:26'! audioSink "Answer the value of audioSink" ^ audioSink! ! !GStreamerElementForSqueakSinkAudio methodsFor: 'accessing' stamp: 'JMM 3/29/2008 16:26'! audioSink: anObject "Set the value of audioSink" audioSink := anObject! ! !GStreamerElementForSqueakSinkAudio methodsFor: 'accessing' stamp: 'JMM 3/29/2008 16:26'! getAudioData ^self primSqueakSinkAudioGetData: self audioSink! ! !GStreamerElementForSqueakSinkAudio methodsFor: 'finalize' stamp: 'jcg 4/22/2008 10:52'! freeSqueakSink GStreamer default freeSqueakSink: self audioSink.! ! !GStreamerElementForSqueakSinkAudio methodsFor: 'system primitives' stamp: 'JMM 3/29/2008 16:24'! primSqueakSinkAudioGetData: sinkOop self primitiveFailed ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'finalize' stamp: 'jcg 4/22/2008 10:52'! freeSqueakSink GStreamer default freeSqueakSink: self videoSink.! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'get value' stamp: 'JMM 3/30/2008 21:36'! getFrameRateDenominator ^self primSqueakSinkGetFrameRateDenominator: videoSink! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'get value' stamp: 'JMM 3/30/2008 21:36'! getFrameRateNumerator ^self primSqueakSinkGetFrameRateNumerator: videoSink! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'get value' stamp: 'JMM 3/30/2008 21:35'! getHeight ^self primSqueakSinkGetHeight: videoSink! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'get value' stamp: 'JMM 3/30/2008 23:30'! getVideoSetBitMap: aBitMap ^self primSqueakSinkVideo: self videoSink setBitMap: aBitMap ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'get value' stamp: 'JMM 3/30/2008 21:35'! getWidth ^self primSqueakSinkGetWidth: videoSink! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'system primitives' stamp: 'JMM 3/30/2008 21:33'! primSqueakSinkGetFrameRateDenominator: aSqueakSinkObject self primitiveFailed ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'system primitives' stamp: 'JMM 3/30/2008 21:34'! primSqueakSinkGetFrameRateNumerator: aSqueakSinkObject self primitiveFailed ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'system primitives' stamp: 'JMM 3/30/2008 21:33'! primSqueakSinkGetHeight: aSqueakSinkObject self primitiveFailed ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'system primitives' stamp: 'JMM 3/30/2008 21:33'! primSqueakSinkGetWidth: aSqueakSinkObject self primitiveFailed ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'system primitives' stamp: 'JMM 3/30/2008 14:36'! primSqueakSinkVideo: aSqueakSinkObject setBitMap: aBitMap self primitiveFailed ! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'accessing' stamp: 'JMM 3/30/2008 14:34'! videoSink "Answer the value of videoSink" ^ videoSink! ! !GStreamerElementForSqueakSinkVideo methodsFor: 'accessing' stamp: 'JMM 3/30/2008 14:34'! videoSink: anObject "Set the value of videoSink" videoSink := anObject! ! !GStreamerElementForSqueakSrcAudio methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:44'! audioSrc "Answer the value of audioSrc" ^ audioSrc! ! !GStreamerElementForSqueakSrcAudio methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:44'! audioSrc: anObject "Set the value of audioSrc" audioSrc := anObject! ! !GStreamerElementForSqueakSrcAudio methodsFor: 'system primitives' stamp: 'JMM 4/1/2008 21:44'! primSqueakSrc: aSqueakSrcObject setData: data self primitiveFailed ! ! !GStreamerElementForSqueakSrcAudio methodsFor: 'system primitives' stamp: 'JMM 4/2/2008 19:44'! primSqueakSrc: aSqueakSrcObject setData: data startTime: startTime duration: duration self primitiveFailed ! ! !GStreamerElementForSqueakSrcAudio methodsFor: 'set value' stamp: 'JMM 4/1/2008 21:45'! setData: data ^self primSqueakSrc: self audioSrc setData: data ! ! !GStreamerElementForSqueakSrcAudio methodsFor: 'set value' stamp: 'JMM 4/2/2008 19:45'! setData: data startTime: startTime duration: duration ^self primSqueakSrc: self audioSrc setData: data startTime: startTime duration: duration! ! !GStreamerElementForSqueakSrcVideo methodsFor: 'system primitives' stamp: 'JMM 4/1/2008 19:55'! primSqueakSrc: aSqueakSrcObject setData: data self primitiveFailed ! ! !GStreamerElementForSqueakSrcVideo methodsFor: 'set value' stamp: 'JMM 4/1/2008 20:02'! setData: data ^self primSqueakSrc: self videoSrc setData: data ! ! !GStreamerElementForSqueakSrcVideo methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:15'! videoSrc "Answer the value of videoSrc" ^ videoSrc! ! !GStreamerElementForSqueakSrcVideo methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:15'! videoSrc: anObject "Set the value of videoSrc" videoSrc := anObject! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:40'! getBufferingPercent "not tested yet" ^self primgstmessageparsebuffering: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:40'! getDuration "not tested yet" ^self primgstmessageparseduration: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 09:13'! getErrorAndDebugStrings ^self primgstmessageparseerror: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:39'! getInfoAndDebugStrings "not tested yet" ^self primgstmessageparseinfo: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 4/2/2008 18:26'! getMessagePostingSrcElement ^self primgstmessagesrc: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:40'! getSegmentDone "not tested yet" ^self primgstmessageparsesegmentdone: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 09:22'! getSegmentStart ^self primgstmessageparsesegmentstart: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'jcg 4/22/2008 10:52'! getStateChanged ^(self primgstmessageparsestatechanged: self handle) collect: [:e | GStreamer stateCodeToSymbol: e].! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/21/2008 13:39'! getWarningAndDebugStrings "not tested yet" ^self primgstmessageparsewarning: self handle.! ! !GStreamerMessage methodsFor: 'accessing' stamp: 'JMM 3/18/2008 21:55'! typeString "Get a printable name for the given message type." ^self primgstmessagetypestring: self handle.! ! !GStreamerMessage methodsFor: 'finalize' stamp: 'JMM 4/7/2008 11:59'! objectUnref handle = 0 ifTrue: [^self]. self primgstmessageunref: self handle. handle := 0.! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstmessageparsebuffering: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstmessageparseduration: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstmessageparseerror: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstmessageparseinfo: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstmessageparsesegmentdone: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:04'! primgstmessageparsesegmentstart: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgstmessageparsestatechanged: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgstmessageparsewarning: obj self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 4/2/2008 18:25'! primgstmessagesrc: ooop self primitiveFailed ! ! !GStreamerMessage methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:05'! primgstmessagetypestring: obj self primitiveFailed ! ! !GStreamerObject class methodsFor: 'instance creation' stamp: 'jcg 5/1/2008 11:40'! handle: aHandle self deprecatedExplanation: 'use #withHandle: instead'. "#handle: sounds like an accessor" ^self withHandle: aHandle.! ! !GStreamerObject class methodsFor: 'instance creation' stamp: 'jcg 5/1/2008 11:39'! withHandle: aHandle ^self new handle: aHandle! ! !GStreamerObject class methodsFor: 'register' stamp: 'JMM 3/12/2008 11:40'! register: anObject self registry add: anObject! ! !GStreamerObject class methodsFor: 'register' stamp: 'JMM 3/12/2008 11:41'! registry ^Registry isNil ifTrue:[Registry := WeakRegistry new] ifFalse:[Registry].! ! !GStreamerObject class methodsFor: 'register' stamp: 'JMM 3/12/2008 11:41'! unregister: anObject self registry remove: anObject ifAbsent:[]! ! !GStreamerCaps class methodsFor: 'instance creation' stamp: 'jcg 4/21/2008 14:11'! fromString: aString | item pointer | item := self new. pointer := item primgstcapsfromstring: aString nullTerminated. item handle: pointer. ^item.! ! !GStreamerElement class methodsFor: 'instance creation' stamp: 'jcg 4/22/2008 10:49'! elementFactoryMake: factoryName name: aName "Create a new element of the type defined by the given element factory. If name is NULL, then the element will receive a guaranteed unique name, consisting of the element factory name and a number. If name is given, it will be given the name supplied." ^self handle: (GStreamer default primgstelementfactorymake: factoryName nullTerminated name: aName nullTerminated)! ! !GStreamerElement class methodsFor: 'instance creation' stamp: 'jcg 5/2/2008 14:36'! factoryName "Answer the name of the type of factory that is used to instantiate this type of element. Subclasses may implement this in order to make it convenient to create elements of that type." self subclassResponsibility! ! !GStreamerElement class methodsFor: 'instance creation' stamp: 'jcg 5/2/2008 13:55'! named: elementName ^self withHandle: (GStreamer default primgstelementfactorymake: self factoryName nullTerminated name: elementName nullTerminated)! ! !GStreamerBin class methodsFor: 'instance creation' stamp: 'jcg 4/22/2008 10:49'! name: aName "Creates a new bin with the given name." | item | item := self new. item handle: (GStreamer default primgstbinnew: aName nullTerminated). ^item.! ! !GStreamerElementFactory class methodsFor: 'instance creation' stamp: 'jcg 4/22/2008 10:49'! elementFactoryFind: aName "Search for an element factory of the given name. Refs the returned element factory; caller is responsible for unreffing." ^self handle: (GStreamer default primgstelementfactoryfind: aName nullTerminated)! ! !GStreamerPad methodsFor: 'caps' stamp: 'JMM 3/18/2008 21:57'! acceptsCaps: gstCaps "Check if the given pad accepts the caps." ^self primgstpadacceptcaps: self handle caps: gstCaps handle! ! !GStreamerPad methodsFor: 'caps' stamp: 'JMM 3/18/2008 21:58'! getCaps "Gets the capabilities this pad can produce or consume. Note that this method doesn't necessarily return the caps set by gst_pad_set_caps() - use GST_PAD_CAPS for that instead. gst_pad_get_caps returns all possible caps a pad can operate with, using the pad's get_caps function; this returns the pad template caps if not explicitly set." ^GStreamerCaps handle: (self primgstpadgetcaps: self handle) ! ! !GStreamerPad methodsFor: 'caps' stamp: 'JMM 3/30/2008 20:28'! setCaps: gstCaps "set the caps." ^self primgstpadsetcaps: self handle setCaps: gstCaps handle! ! !GStreamerPad methodsFor: 'finalize' stamp: 'JMM 3/17/2008 13:13'! finalize "Don't, work is done by GStreamerElement" self noCheckHandle: 0! ! !GStreamerPad methodsFor: 'finalize' stamp: 'JMM 4/3/2008 18:09'! releasePadForElement: aElement self release.! ! !GStreamerPad methodsFor: 'pads' stamp: 'jcg 4/21/2008 15:28'! ghostPadNew: aName ^GStreamerPad handle: (self primgstghostpadnew: self handle name: aName nullTerminated) "Create a new ghostpad with target as the target. The direction will be taken from the target pad. target must be unlinked. Will ref the target. name : the name of the new pad, or NULL to assign a default name. target : the pad to ghost. Returns : a new GstPad, or NULL in case of an error."! ! !GStreamerPad methodsFor: 'pads' stamp: 'JMM 3/18/2008 00:45'! setState: aBoolean ^self primgstpadsetactive: self handle state: aBoolean "Activates or deactivates the given pad. Normally called from within core state change functions. If active, makes sure the pad is active. If it is already active, either in push or pull mode, just return. Otherwise dispatches to the pad's activate function to perform the actual activation. If not active, checks the pad's current mode and calls gst_pad_activate_push() or gst_pad_activate_pull(), as appropriate, with a FALSE argument."! ! !GStreamerPad methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstghostpadnew: gstPadOop name: aName self primitiveFailed ! ! !GStreamerPad methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpadacceptcaps: gstPadOop caps: gstCapsOop self primitiveFailed ! ! !GStreamerPad methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpadgetcaps: gstPadOop self primitiveFailed ! ! !GStreamerPad methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpadsetactive: gstPadOop state: aBoolean self primitiveFailed ! ! !GStreamerPad methodsFor: 'system primitives' stamp: 'JMM 3/30/2008 20:27'! primgstpadsetcaps: gstPadOop setCaps: gstCapsOop self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'utility' stamp: 'JMM 3/31/2008 18:41'! getAudiodataIfFoundGiveTo: noone! ! !GStreamerPipeline methodsFor: 'utility' stamp: 'JMM 3/29/2008 16:42'! modifyElements! ! !GStreamerPipeline methodsFor: 'utility' stamp: 'JMM 4/2/2008 19:03'! setStateToThisValue: newState | currentState bus message | currentState := self getSimplifiedState. currentState = newState ifTrue: [^self]. self setStateTo: newState. bus := self getBus. message := bus waitUntilErrorOrMessage: {'state-changed'. 2. newState. self} uptoMilliseconds: 5000. ! ! !GStreamerPipeline methodsFor: 'bus' stamp: 'JMM 3/13/2008 11:51'! getAutoFlushBus "Check if pipeline will automatically flush messages when going to the NULL state. Returns : whether the pipeline will automatically flush its bus when going from READY to NULL state or not. MT safe." ^self primgstpipelinegetautoflushbus: self handle! ! !GStreamerPipeline methodsFor: 'bus' stamp: 'JMM 3/17/2008 00:19'! getBus "Gets the GstBus of pipeline." ^GStreamerBus handle: (self primgstpipelinegetbus: self handle)! ! !GStreamerPipeline methodsFor: 'bus' stamp: 'JMM 3/13/2008 00:27'! setAutoFlushBus: aBoolean "Usually, when a pipeline goes from READY to NULL state, it automatically flushes all pending messages on the bus, which is done for refcounting purposes, to break circular references. This means that applications that update state using (async) bus messages (e.g. do certain things when a pipeline goes from PAUSED to READY) might not get to see messages when the pipeline is shut down, because they might be flushed before they can be dispatched in the main thread. This behaviour can be disabled using this function. It is important that all messages on the bus are handled when the automatic flushing is disabled else memory leaks will be introduced. " self primgstpipelinesetautoflushbus: self handle value: aBoolean ! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 11:39'! getClock "Gets the gstClock of pipeline. Returns : a GstClock, unref after usage." | clockHandle | clockHandle := self primgstpipelinegetclock: self handle. ^GStreamerClock handle: clockHandle.! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 00:24'! getDelay "Get the configured delay (see gst_pipeline_set_delay())." ^self primgstpipelinegetdelay: self handle! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 00:18'! getLastStreamTime "Gets the last stream time of pipeline. If the pipeline is PLAYING, the returned time is the stream time used to configure the element's base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the returned time is the stream time when the pipeline was paused. This function returns GST_CLOCK_TIME_NONE if the pipeline was configured to not handle the management of the element's base time (see gst_pipeline_set_new_stream_time())." ^self primgstpipelinegetlaststreamtime: self handle! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 00:26'! setAutoClock "Let pipeline select a clock automatically. This is the default behaviour. Use this function if you previous forced a fixed clock with gst_pipeline_use_clock() and want to restore the default pipeline clock selection algorithm." self primgstpipelineautoclock: self handle! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 12:21'! setClock: aGStreamerClock "Set the clock for pipeline. The clock will be distributed to all the elements managed by the pipeline. Returns : TRUE if the clock could be set on the pipeline. FALSE if some element did not accept the clock. MT safe. " ^self primgstpipelinesetclock: self handle value: aGStreamerClock handle ! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 00:27'! setDelay: aClockValue "Set the expected delay needed for all elements to perform the PAUSED to PLAYING state change. delay will be added to the base time of the elements so that they wait an additional delay amount of time before starting to process buffers and cannot be GST_CLOCK_TIME_NONE. This option is used for tuning purposes and should normally not be used." self primgstpipelinesetdelay: self handle value: aClockValue ! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 00:17'! setNewStreamTime: aGstClockTime "Set the new stream time of pipeline to time. The stream time is used to set the base time on the elements (see gst_element_set_base_time()) in the PAUSED->PLAYING state transition. Setting time to GST_CLOCK_TIME_NONE will disable the pipeline's management of element base time. The application will then be responsible for performing base time distribution. This is sometimes useful if you want to synchronize capture from multiple pipelines, and you can also ensure that the pipelines have the same clock." self primgstpipelinesetnewstreamtime: self handle value: aGstClockTime ! ! !GStreamerPipeline methodsFor: 'clock' stamp: 'JMM 3/13/2008 12:24'! useClock: aGStreamerClock "Force pipeline to use the given clock. The pipeline will always use the given clock even if new clock providers are added to this pipeline. If clock is NULL all clocking will be disabled which will make the pipeline run as fast as possible." aGStreamerClock ifNil: [ self primgstpipelineuseclock: self handle value: 0. ^self]. self primgstpipelineuseclock: self handle value: aGStreamerClock handle. ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpipelineautoclock: aHandle self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpipelinegetautoflushbus: aHandle self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpipelinegetbus: aHandle self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpipelinegetclock: aHandle self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpipelinegetdelay: aHandle self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:06'! primgstpipelinegetlaststreamtime: aHandle self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpipelinesetautoflushbus: aHandle value: aClockValue self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpipelinesetclock: aHandle value: aClockValue self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpipelinesetdelay: aHandle value: aClockValue self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpipelinesetnewstreamtime: aHandle value: aClockValue self primitiveFailed ! ! !GStreamerPipeline methodsFor: 'system primitives' stamp: 'JMM 3/26/2008 16:07'! primgstpipelineuseclock: aHandle value: aClockValue self primitiveFailed ! ! !GStreamerPipeline class methodsFor: 'instance creation' stamp: 'jcg 5/1/2008 18:25'! createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: aCollectionOfElementNames initialize: initBlock | pipeLine elements result | pipeLine := self name: aPipeLineName. initBlock value: pipeLine. elements := aCollectionOfElementNames collect: [:e | e caseOf: { ['fakesrc'] -> [self makeFakeSrcElement: e]. ['fakesink'] -> [self makeFakeSinkElement: e]. } otherwise: [GStreamerElement elementFactoryMake: e name: e]. ]. elements do: [:e | e isHandleSane ifFalse: [^nil]]. elements do: [:e | result := pipeLine addElement: e. result ifFalse: [^nil]]. pipeLine modifyElements. 1 to: elements size - 1 do: [:i | | first second | first := elements at: i. second := elements at: i+1. result := GStreamer default linkElementSrc: first toDest: second. result ifFalse: [^nil]. ]. ^pipeLine! ! !GStreamerPipeline class methodsFor: 'instance creation' stamp: 'JMM 3/30/2008 14:33'! makeFakeSinkElement: e ! ! !GStreamerPipeline class methodsFor: 'instance creation' stamp: 'jcg 4/22/2008 10:49'! name: aName "Create a new pipeline with the given name." | item | item := self new. item handle: (GStreamer default primgstpipelinenew: aName nullTerminated). ^item.! ! !GStreamerPipelineSqueakSink methodsFor: 'finalize' stamp: 'JMM 3/24/2008 10:04'! handle: anObject "Set the value of handle" handle := anObject. ! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'finalize' stamp: 'jcg 5/2/2008 23:54'! finalize squeakerAudio ifNotNil: [ squeakerAudio finalize. squeakerAudio := nil. ]. super finalize. ! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'utility' stamp: 'jcg 4/22/2008 10:52'! getAudiodataIfFoundGiveTo: player | data | self squeakerAudio ifNil: [^self]. data := self squeakerAudio getAudioData. (data notNil and: [player notNil]) ifTrue: [player add: (GStreamer convertToMixedSound: data sampleRate: 22050)]! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'utility' stamp: 'JMM 3/30/2008 23:11'! playToSqueakAudioForSeconds: aSeconds | player bus message | player := QueueSound new. SoundPlayer stopReverb. bus := self getBus. self setStateTo: #playing. player play. message := bus waitUntilErrorOrMessage: 'eos' uptoMilliseconds: aSeconds*1000 do: [self waitOrPoll: 50 thenQueueSound: player] waitBlock: []. self setStateTo: #null. message ifNotNil: [^message]. ^nil. ! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'utility' stamp: 'jcg 5/2/2008 23:56'! waitOrPoll: aMillisecondValue thenQueueSound: player | sem | sem := self squeakerAudio semaphore ifNil: [^self]. sem waitTimeoutMSecs: aMillisecondValue. self getAudiodataIfFoundGiveTo: player! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'initialize-release' stamp: 'JMM 4/1/2008 12:32'! modifyElements | caps capsfilter | caps := self class audioCapsLittle. capsfilter := self findElementCalled: 'capsfilter'. capsfilter setKey: 'caps' toPointerValue: caps handle. ! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'initialize-release' stamp: 'jcg 5/3/2008 15:10'! setupSemaphore self squeakerAudio: (self findElementCalled: 'fakesinkAudio').! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'accessing' stamp: 'JMM 3/26/2008 20:51'! squeakerAudio "Answer the value of squeakerAudio" ^ squeakerAudio! ! !GStreamerPipelineSqueakAudioSink methodsFor: 'accessing' stamp: 'JMM 3/26/2008 20:51'! squeakerAudio: anObject "Set the value of squeakerAudio" squeakerAudio := anObject! ! !GStreamerPipelineSqueakSink class methodsFor: 'accessing' stamp: 'JMM 4/1/2008 12:32'! audioCapsLittle ^GStreamerCaps fromString: 'audio/x-raw-int, width = (int) 16, depth = (int) 16, endianness = (int) 1234, channels = (int) { 2 }, rate = (int) { 22050 }'! ! !GStreamerPipelineSqueakSink class methodsFor: 'accessing' stamp: 'JMM 4/1/2008 14:08'! videoCapsBig16 ^GStreamerCaps fromString: 'video/x-raw-rgb, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234'! ! !GStreamerPipelineSqueakSink class methodsFor: 'accessing' stamp: 'JMM 4/1/2008 13:48'! videoCapsBig32 ^GStreamerCaps fromString: 'video/x-raw-rgb, bpp=(int)32, endianness=(int)4321, depth=(int)24, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]'! ! !GStreamerPipelineSqueakSink class methodsFor: 'instance creation' stamp: 'JMM 4/1/2008 17:51'! createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: aCollectionOfElementNames | pipeLine | pipeLine := super createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: aCollectionOfElementNames, (Array with: 'capsfilter' with: 'fakesink') initialize: [:pipe | ]. pipeLine handle = 0 ifTrue: [^nil]. pipeLine setupSemaphore. pipeLine register. ^pipeLine ! ! !GStreamerPipelineSqueakSink class methodsFor: 'instance creation' stamp: 'jcg 5/2/2008 18:00'! makeFakeSinkElement: e self subclassResponsibility! ! !GStreamerPipelineSqueakAudioSink class methodsFor: 'instance creation' stamp: 'jcg 5/2/2008 23:29'! makeFakeSinkElement: e | fs | fs := GstElemSqueakAudioSink named: 'fakesinkAudio'. fs setKey: 'sync' toBooleanValue: true. ^fs ! ! !GStreamerPipelineSqueakSrc methodsFor: 'initialize-release' stamp: 'JMM 4/1/2008 17:47'! setupSemaphore! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'initialize-release' stamp: 'JMM 4/2/2008 00:46'! audioCapsLittle ^GStreamerCaps fromString: 'audio/x-raw-int, width = 8, depth = 8, endianness = 1234, channels = 2, rate = ',self frequency printString.! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'initialize-release' stamp: 'JMM 4/1/2008 21:51'! modifyElements | caps capsfilter | caps := self audioCapsLittle. capsfilter := self findElementCalled: 'capsfilter'. capsfilter setKey: 'caps' toPointerValue: caps handle. ! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'initialize-release' stamp: 'jcg 4/22/2008 10:52'! setupSemaphore self squeakerAudio: (self findElementCalled: 'fakesrcAudio'). self squeakerAudio ifNil: [^self]. self semaphoreAudio: Semaphore new. self semaIndexAudio: (Smalltalk registerExternalObject: self semaphoreAudio). self squeakerAudio audioSrc: (GStreamer default allocateSqueakSrc: self bufferSize forElement: self squeakerAudio useSemaphoreIndex: self semaIndexAudio ). self squeakerAudio signal: 'handoff' data: self squeakerAudio audioSrc. self squeakerAudio setKey: 'sizemax' toLongValue: self bufferSize. self squeakerAudio setKey: 'sizetype' toLongValue: 2. self squeakerAudio setKey: 'signal-handoffs' toBooleanValue: true. self squeakerAudio setKey: 'do-timestamp' toBooleanValue: true. ! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/2/2008 00:16'! bufferSize ^8192! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:48'! frequency "Answer the value of frequency" ^ frequency! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:48'! frequency: anObject "Set the value of frequency" frequency := anObject! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:46'! semaIndexAudio "Answer the value of semaIndexAudio" ^ semaIndexAudio! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:46'! semaIndexAudio: anObject "Set the value of semaIndexAudio" semaIndexAudio := anObject! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:46'! semaphoreAudio "Answer the value of semaphoreAudio" ^ semaphoreAudio! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:46'! semaphoreAudio: anObject "Set the value of semaphoreAudio" semaphoreAudio := anObject! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:46'! squeakerAudio "Answer the value of squeakerAudio" ^ squeakerAudio! ! !GStreamerPipelineSqueakAudioSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 21:46'! squeakerAudio: anObject "Set the value of squeakerAudio" squeakerAudio := anObject! ! !GStreamerPipelineSqueakAudioSrc class methodsFor: 'instance creation' stamp: 'JMM 4/2/2008 19:58'! createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: aCollectionOfElementNames frequency: hertz | pipeLine | pipeLine := super createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: (Array with: 'fakesrc' with: 'capsfilter' ),aCollectionOfElementNames initialize: [:pipe | pipe frequency: hertz]. pipeLine handle = 0 ifTrue: [^nil]. pipeLine setupSemaphore. pipeLine register. ^pipeLine ! ! !GStreamerPipelineSqueakAudioSrc class methodsFor: 'instance creation' stamp: 'JMM 4/2/2008 19:59'! makeFakeSrcElement: e | fs | fs := GStreamerElementForSqueakSrcAudio elementFactoryMake: e name: e,'Audio'. ^fs ! ! !GStreamerPipelineSqueakAudioSrc class methodsFor: 'testing' stamp: 'JMM 4/2/2008 20:08'! testForAudioCreation "self testForAudioCreation" | pipeLine data i duration startTime | pipeLine := GStreamerPipelineSqueakAudioSrc createPipeLineCalled: 'foo' thenBuildAndLinkElements: #('audioconvert' 'osxaudiosink') frequency: 44100. data := ByteArray new: 8192. duration := (8192/2/44100.0*1000000000) asInteger. startTime := 0. i := 100. 1 to: 8192 do: [:j | data at: j put: i]. pipeLine squeakerAudio setData: data startTime: startTime duration: duration. pipeLine setStateTo: #playing. 1000 timesRepeat: [ startTime := startTime + duration. pipeLine squeakerAudio setData: data startTime: startTime duration: duration. (Delay forMilliseconds: 15) wait]. pipeLine setStateTo: #null. pipeLine release. ! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'finalize' stamp: 'jcg 5/3/2008 00:53'! finalize squeakerVideo ifNotNil: [ squeakerVideo finalize. squeakerVideo := nil. ]. super finalize. ! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 15:04'! fps "Answer the value of width" ^self squeakerVideo ifNotNilDo: [:s | s frameRate]! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 15:05'! fps: anObject "Set the value of fps" self shouldNotImplement. "we'll get the dimensions directly from the sink." " fps := anObject"! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 15:04'! height "Answer the value of height" ^self squeakerVideo ifNotNilDo: [:s | s height]! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 15:04'! height: anObject "Set the value of height" self shouldNotImplement. "we'll get the dimensions directly from the sink." " height := anObject"! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'JMM 3/26/2008 20:53'! squeakerVideo "Answer the value of squeakerVideo" ^ squeakerVideo! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'JMM 3/26/2008 20:53'! squeakerVideo: anObject "Set the value of squeakerVideo" squeakerVideo := anObject! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 15:04'! width "Answer the value of width" ^self squeakerVideo ifNotNilDo: [:s | s width]! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 15:05'! width: anObject "Set the value of width" self shouldNotImplement. "we'll get the dimensions directly from the sink." " width := anObject"! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'utility' stamp: 'JMM 3/30/2008 22:25'! getVideodataIfFoundGiveTo: player player ifNotNil: [^self squeakerVideo getVideoSetBitMap: player bits]. ^true.! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'utility' stamp: 'JMM 3/27/2008 15:12'! playToSqueakAudioVideoForSeconds: aSeconds ^self playToSqueakAudioVideoForSeconds: aSeconds setInitialState: #playing ! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'utility' stamp: 'JMM 3/31/2008 00:09'! playToSqueakAudioVideoForSeconds: aSeconds setInitialState: initialState | player startPlayer bus message hadFrame | player := QueueSound new. startPlayer := true. SoundPlayer stopReverb. bus := self getBus. self setStateTo: initialState. message := bus waitUntilErrorOrMessage: 'eos' uptoMilliseconds: aSeconds*1000 do: [self waitOrPoll: 100 thenQueueSound: player] waitBlock: [hadFrame := self waitOrPoll: (1000//self fps//2) thenShowFrameOn: nil. (startPlayer and: [hadFrame]) ifTrue: [startPlayer := false. player play]]. player pause. player reset. self setStateTo: #null. message ifNotNil: [^message]. ^nil. ! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'utility' stamp: 'JMM 3/30/2008 21:47'! playToSqueakVideoForSeconds: aSeconds | bus message | bus := self getBus. self setStateTo: #playing. message := bus waitUntilErrorOrMessage: 'eos' uptoMilliseconds: aSeconds*1000 do: [self waitOrPoll: 100 thenShowFrameOn: nil] waitBlock: []. self setStateTo: #null. message ifNotNil: [^message]. ^nil. ! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'utility' stamp: 'jcg 5/3/2008 15:05'! waitOrPoll: aMillisecondValue thenShowFrameOn: player | sem form | sem := self squeakerVideo semaphore ifNil: [^self]. sem waitTimeoutMSecs: aMillisecondValue. form := Form extent: (self width @ self height) depth: 32. self squeakerVideo getVideoSetBitMap: form bits. form displayOn: Display. ^true! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'initialize-release' stamp: 'JMM 4/1/2008 12:30'! modifyElements | caps capsfilter | caps := self class videoCapsBig32. capsfilter := self findElementCalled: 'capsfilter'. capsfilter setKey: 'caps' toPointerValue: caps handle. ! ! !GStreamerPipelineSqueakVideoSink methodsFor: 'initialize-release' stamp: 'jcg 5/3/2008 15:10'! setupSemaphore super setupSemaphore. self squeakerVideo: (self findElementCalled: 'fakesinkVideo'). ! ! !GStreamerPipelineSqueakVideoSink class methodsFor: 'instance creation' stamp: 'jcg 5/3/2008 00:43'! makeFakeSinkElement: e | fs | fs := GstElemSqueakVideoSink named: 'fakesinkVideo'. fs setKey: 'sync' toBooleanValue: true. ^fs ! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:45'! depth "Answer the value of depth" ^ depth! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:45'! depth: anObject "Set the value of depth" depth := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! fps "Answer the value of fps" ^ fps! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! fps: anObject "Set the value of fps" fps := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! height "Answer the value of height" ^ height! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! height: anObject "Set the value of height" height := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! semaIndexVideo "Answer the value of semaIndexVideo" ^ semaIndexVideo! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! semaIndexVideo: anObject "Set the value of semaIndexVideo" semaIndexVideo := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! semaphoreVideo "Answer the value of semaphoreVideo" ^ semaphoreVideo! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! semaphoreVideo: anObject "Set the value of semaphoreVideo" semaphoreVideo := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! squeakerVideo "Answer the value of squeakerVideo" ^ squeakerVideo! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! squeakerVideo: anObject "Set the value of squeakerVideo" squeakerVideo := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! width "Answer the value of width" ^ width! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'accessing' stamp: 'JMM 4/1/2008 17:20'! width: anObject "Set the value of width" width := anObject! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'initialize-release' stamp: 'JMM 4/1/2008 21:31'! modifyElements | caps capsfilter | caps := self videoCapsBig32. capsfilter := self findElementCalled: 'capsfilter'. capsfilter setKey: 'caps' toPointerValue: caps handle. ! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'initialize-release' stamp: 'jcg 4/22/2008 10:52'! setupSemaphore | bytesForDepth | self squeakerVideo: (self findElementCalled: 'fakesrcVideo'). self squeakerVideo ifNil: [^self]. self semaphoreVideo: Semaphore new. self semaIndexVideo: (Smalltalk registerExternalObject: self semaphoreVideo). bytesForDepth := self depth = 32 ifTrue: [4] ifFalse: [2]. self squeakerVideo videoSrc: (GStreamer default allocateSqueakSrc: (bytesForDepth * self height * self width) forElement: self squeakerVideo useSemaphoreIndex: self semaIndexVideo ). self squeakerVideo signal: 'handoff' data: self squeakerVideo videoSrc. self squeakerVideo setKey: 'sizemax' toLongValue: bytesForDepth * self height * self width. self squeakerVideo setKey: 'sizetype' toLongValue: 2. self squeakerVideo setKey: 'signal-handoffs' toBooleanValue: true ! ! !GStreamerPipelineSqueakVideoSrc methodsFor: 'initialize-release' stamp: 'JMM 4/1/2008 20:56'! videoCapsBig32 ^GStreamerCaps fromString: 'video/x-raw-rgb, bpp=(int)32, endianness=(int)4321, depth=(int)24, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=',self width printString, ', height=',self height printString, ', framerate=1/', self fps printString.! ! !GStreamerPipelineSqueakVideoSrc class methodsFor: 'instance creation' stamp: 'JMM 4/1/2008 20:52'! createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: aCollectionOfElementNames width: width height: height depth: depth fps: fps | pipeLine | pipeLine := super createPipeLineCalled: aPipeLineName thenBuildAndLinkElements: (Array with: 'fakesrc' with: 'capsfilter'),aCollectionOfElementNames initialize: [:pipe | pipe height: height. pipe width: width. pipe depth: depth. pipe fps: fps]. pipeLine handle = 0 ifTrue: [^nil]. pipeLine setupSemaphore. pipeLine register. ^pipeLine ! ! !GStreamerPipelineSqueakVideoSrc class methodsFor: 'instance creation' stamp: 'JMM 4/1/2008 21:48'! makeFakeSrcElement: e | fs | fs := GStreamerElementForSqueakSrcVideo elementFactoryMake: e name: e,'Video'. ^fs ! ! !GStreamerPipelineSqueakVideoSrc class methodsFor: 'testing' stamp: 'JMM 4/1/2008 21:41'! testForVideoCreation "self testForVideoCreation" | pipeLine form task result | pipeLine := GStreamerPipelineSqueakVideoSrc createPipeLineCalled: 'foo' thenBuildAndLinkElements: #('ffmpegcolorspace' 'ximagesink') width: 320 height: 240 depth: 32 fps: 24. form := Form extent: 240@320 depth: 32. task := [ | i | i := 0.0. 1000 timesRepeat: [i := i + 0.001. form fill: (0@0 extent: form extent) rule: Form over fillColor: (Color h: i s: i v: i). result := pipeLine squeakerVideo setData: form bits. (Delay forMilliseconds: 10) wait] ] fork. pipeLine setStateTo: #playing. (Delay forSeconds: 15) wait. pipeLine setStateTo: #null. pipeLine release. ! ! !GStreamerRequestPad methodsFor: 'finalize' stamp: 'JMM 4/3/2008 18:50'! releasePadForElement: aElement "Makes the element free the previously requested pad as obtained with gst_element_get_request_pad()." aElement noCheckHandle = 0 ifTrue: [^self]. aElement primigstelementreleaserequestpad: aElement handle pad: self handle. self noCheckHandle: 0. aElement unregister. ! ! !GstElemFakeSink methodsFor: 'initialize' stamp: 'jcg 5/2/2008 22:07'! finalize sem ifNotNil: [ Smalltalk unregisterExternalObject: semInd. sem := semInd := nil. ]. squeakSink ifNotNil: [ GStreamer default freeSqueakSink: squeakSink. squeakSink := nil ].! ! !GstElemFakeSink methodsFor: 'initialize' stamp: 'jcg 5/2/2008 23:51'! handle: newHandle super handle: newHandle. newHandle isZero ifFalse: [self initializeSqueakSink].! ! !GstElemFakeSink methodsFor: 'initialize' stamp: 'jcg 5/2/2008 22:08'! initialize sem := Semaphore new. semInd := Smalltalk registerExternalObject: sem! ! !GstElemFakeSink methodsFor: 'initialize' stamp: 'jcg 5/2/2008 22:09'! initializeSqueakSink self subclassResponsibility! ! !GstElemFakeSink methodsFor: 'accessing' stamp: 'jcg 5/2/2008 23:30'! getAudioData ^self primSqueakSinkAudioGetData: squeakSink! ! !GstElemFakeSink methodsFor: 'accessing' stamp: 'jcg 5/2/2008 23:36'! semaphore ^sem! ! !GstElemFakeSink methodsFor: 'system primitives' stamp: 'jcg 5/2/2008 23:30'! primSqueakSinkAudioGetData: sinkOop self primitiveFailed ! ! !GstElemFakeSink class methodsFor: 'instance creation' stamp: 'jcg 5/2/2008 18:22'! factoryName ^'fakesink'! ! !GstElemSqueakAudioSink methodsFor: 'initialize' stamp: 'jcg 5/2/2008 22:08'! initializeSqueakSink squeakSink := GStreamer default allocateSqueakSinkAudioForElement: self useSemaphoreIndex: semInd. self signal: 'handoff' data: squeakSink. self setKey: 'signal-handoffs' toBooleanValue: true.! ! !GstElemSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 00:48'! frameRate ^ (self primSqueakSinkGetFrameRateNumerator: squeakSink) / (self primSqueakSinkGetFrameRateDenominator: squeakSink)! ! !GstElemSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 00:49'! getVideoSetBitMap: aBitMap ^self primSqueakSinkVideo: squeakSink setBitMap: aBitMap ! ! !GstElemSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 00:45'! height ^self primSqueakSinkGetHeight: squeakSink! ! !GstElemSqueakVideoSink methodsFor: 'accessing' stamp: 'jcg 5/3/2008 00:45'! width ^self primSqueakSinkGetWidth: squeakSink! ! !GstElemSqueakVideoSink methodsFor: 'initialize' stamp: 'jcg 5/2/2008 22:10'! initializeSqueakSink squeakSink := GStreamer default allocateSqueakSinkVideoForElement: self useSemaphoreIndex: semInd. self signal: 'handoff' data: squeakSink. self signal: 'preroll-handoff' data: squeakSink. self setKey: 'signal-handoffs' toBooleanValue: true.! ! !GstElemSqueakVideoSink methodsFor: 'system primitives' stamp: 'jcg 5/3/2008 00:46'! primSqueakSinkGetFrameRateDenominator: aSqueakSinkObject self primitiveFailed ! ! !GstElemSqueakVideoSink methodsFor: 'system primitives' stamp: 'jcg 5/3/2008 00:46'! primSqueakSinkGetFrameRateNumerator: aSqueakSinkObject self primitiveFailed ! ! !GstElemSqueakVideoSink methodsFor: 'system primitives' stamp: 'jcg 5/3/2008 00:46'! primSqueakSinkGetHeight: aSqueakSinkObject self primitiveFailed ! ! !GstElemSqueakVideoSink methodsFor: 'system primitives' stamp: 'jcg 5/3/2008 00:46'! primSqueakSinkGetWidth: aSqueakSinkObject self primitiveFailed ! ! !GstElemSqueakVideoSink methodsFor: 'system primitives' stamp: 'jcg 5/3/2008 00:49'! primSqueakSinkVideo: aSqueakSinkObject setBitMap: aBitMap self primitiveFailed ! ! !String methodsFor: '*GStreamer-Base' stamp: 'jcg 4/21/2008 01:22'! nullTerminated (self basicAt: self size) == 0 ifTrue: [^self "already null-terminated"] ifFalse: [^self copyWith: (Character value: 0)]. ! ! GStreamer initialize!