Chapter 14: Sounds
Chapter Objectives
This chapter discusses the following:
- How sound is physically recorded and played back and our internal storage of sound
- Operations that can be performed with the original time trace
- The ability to transform the data into the frequency domain and the physical significance of the transformed data
- Operations that can be performed in the frequency domain
14.1 The Physics of Sound
Any sound source produces sound in the form of pressure fluctuations in the air. While the air molecules move infinitesimal distances in order to propagate the sound, the important part of sound propagation is that pressure waves move rapidly through the air by causing air molecules to “jostle” each other. These pressure fluctuations can be viewed as analog signals—data that have a continuous range of values. These signals have two attributes: their amplitude and their frequency characteristics.
In absolute terms, sound is measured as the amplitude of pressure fluctuations on a surface like an eardrum or a microphone. However, the challenging characteristic of these data is their dynamic range. Our ears are able to detect small sounds with amplitudes around 1010 (10 billion) times smaller than the loudest comfortable sound. Sound intensity is therefore usually reported logarithmically, measured in decibels where the intensity of a sound in decibels is calculated as follows:
IDB = 10 log10(I / I0)
where I is the measured pressure fluctuation and I0 is a reference pressure usually established as the lowest pressure fluctuation a really good ear can detect, 2 x 10−4 dynes/cm2.
Also, sounds are pressure fluctuations at certain frequencies. The human ear can hear sounds as low as 50 Hz and as high as 20 kHz. Voices on the telephone sound odd because the upper frequency is limited by the telephone equipment to 4 kHz. Typically, hearing damage due to aging or exposure to excessive sound levels causes an ear to lose sensitivity to high and/or low frequencies.
14.2 Recording and Playback
Figure 14.1: Recording and Playback
Early attempts at sound recording concentrated first on mechanical, and later magnetic, methods for storing and reproducing sound. The phonograph/record player depended on the motion of a needle in a groove as a cylinder or disk rotated at constant speed under the playback head. Not surprisingly, when you see the incredible dynamic range required, even the best stereos could not reproduce high-quality sound. Later, analog magnetic tape in various forms replaced the phonograph, offering less wear on the recording and better, but still limited, dynamic range. Digital recording has almost completely supplanted analog recording and will be the subject of this chapter.
Of course, sound amplitude in analog form is unintelligible to a computer—it must be turned into an electrical signal by a microphone, amplified to suitable voltage levels, digitized, and stored, as shown in Figure 14.1. The key to successful digital recording and playback—whether by digital tape machines, compact disks, or computer files—is the design of the analog-to-digital (A/D) and digital-to-analog (D/A) devices. The reader should remember that this is still low-level data. Each word coming out of the A/D or going into the D/A merely represents the pressure on the microphone at a point in time.
The primary parameter governing the sound quality is the recording rate—how quickly the mechanism records samples of the sound (the sampling rate). Basic sampling theory suggests that we should use a sampling rate twice the highest frequency you are interested in reproducing, usually around 20,000 samples per second for good music, 5,000 samples per second for speech.
Technical Insight 14.1
The background theory of sampling is beyond the scope of this text. Interested readers should research Nyquist on a good search engine.
The other parameter, the resolution of the recorded data, has remarkably little effect on the quality of the recording to an untrained ear. The resolution is usually either 8 bits (−128 to 127) or 16 bits (−32,768 to 32767). While 8-bit resolution ought to offer very limited dynamic range, and theoretically should be used only for recording speech, in practice it results in a quality of reproduction for music that is, to an untrained ear, indistinguishable from that provided by 16-bit resolution.
These parameters must be stored with any digital sound recording medium and retrieved by the tools that play those sounds. To be able to play such a file, we must receive not only the data stream, but also information indicating the sample frequency, Fs
, and the word size.
14.3 Implementation
MATLAB offers a number of tools for reading sound files: audioread(...)
, for example. This function returns two variables: a vector of sound values and the sampling frequency in Hz (samples per second).
To play a sound file, MATLAB provides the function sound(data, rate)
where data
is the vector of sound values, and rate
is the playback frequency, usually the frequency at which the sound values were recorded. We will see that the function sound(...)
passes the data directly to the computer’s sound card, but different implementations will manage the behavior of the software that plays the sound in one of two ways.
Blocking vs. Non-blocking: "Blocking" refers to the behavior of your system after you have called the sound(...)
function to play a sound. Blocking players will not return control to the code playing the sound until the sound has completed. This will allow only one sound to be played from an application at a time. Non-blocking players will not wait for the sound card to finish playing the sound, so multiple calls to the sound(...)
function will overlay different sounds. You will need to experiment with your particular system to determine whether it blocks or not.
14.4 Time Domain Operations
First, we consider three kinds of operations on sound files in the time domain: slicing, playback frequency changes, and sound file frequency changes.
14.4.1 Slicing and Concatenating Sound
Figure 14.2: Gone With the Wind Speech
Consider the problem of constructing comedic sayings by choosing and assembling words from published speeches. One example of a speech clip is "Frankly, my dear..." from Gone with the Wind. Listing 14.1 describes the process of assembling parts of this speech into a semi-coherent conversation.
In Listing 14.1, we first read and play the sound from the "frankly, my dear..." speech; the plotted data can be seen in Figure 14.2. Then, we play it louder by increasing the amplitude and then play it softer by decreasing the amplitude. It is then played faster by dropping half the data and then played slower by reducing the playback frequency. Then, all of the speech pieces are pasted together to construct the final sound clip.
"Frankly, my dear..." speech
Bond speech
Beam Speech
Combined Speech
14.4.2 Musical Background
Figure 14.3: Musical Notes
For good historical reasons, music is usually described graphically on a music score. The graphics describe for each note to be played its pitch and its duration, together with other notations indicating how to introduce expression and quality into the music. However, this graphical notation is not amenable to the simple representation of music we need for these experiments. Rather, we will use the representation illustrated in Figure 14.3. The right side of this figure shows a standard piano keyboard, the index of each white note, and the number of half steps necessary to achieve the pitch of each note. On the left side of the figure, we see the method to be used in this text to describe simple tunes. It will consist of an array with two columns and n rows, where n is the number of notes to be played for each tune. The first column is the key number to play, and the second column is the number of beats each note should be played.
The example to follow in Listing 14.2 will manipulate the file instr_piano.wav
to produce a snippet of music. This file is a recording of a single note played on a piano. There are two ways to accomplish this, as follows:
- Playing each note at a different playback frequency
- Stretching or shrinking each note to match the required note pitch and playing them all at the same playback frequency
The first way is easier to understand and code, but very inflexible; the second method is a little more difficult to implement, but completely extensible. Musically speaking, if a sound is played at twice its natural frequency, it is heard as one musical octave higher. When you play a scale by playing each white key in turn from one note to the next octave, there are 8 keys to play with 7 frequency changes: 5 whole note steps (those separated by a black note) and 2 half note steps, for a total of 12 half note steps. These 12 half steps are logarithmically divided where the frequency multiplier between half note steps is 21/12.
Piano Note
14.4.3 Changing Sound Frequency
Figure 14.4: Creating a Tune File
We will leave as an exercise for the reader the question of playing a tune by changing the playback frequency of each note, which is really never a practical thing to do, and concentrate on playing all the notes of a tune with the same playback frequency. This allows the different notes to be copied into a single sound file and saved to be played back on any digital sound system.
In order to change the perceived note frequency without changing the playback frequency, we have to change the number of data samples in the original data file much as we stretched or shrunk an image in Section 13.4.1.
Play a Scale Listing 14.2 shows a script that uses this capability to play the C Major scale (all white notes) on the piano. It repeatedly shortens the vector to increase the frequency of the note played.
Play a Simple Tune We now write a script to build a playable .wav
file using the note shrinking technique, also shown in Listing 14.2. It reads in the script ramblinWreck
to define the tune in which the first column of each cell array specifies the relative pitch (the note on the scale) and the second the duration in "beats".
The goal is to put the notes into a single sound array called wreck
, as illustrated in Figure 14.4, rather than playing the notes "on the fly." For each part, or instrument, this is accomplished as follows:
- In the
play_part
function, create an empty array,part
, of the appropriate length (the length of the original note plus the total number of beats in the song) - Initialize
where
to store the first note at the start of the tune - Iterate across the
part
definition arrayscore
with the following steps:- In the
getPitch
function, start with the originalnote
- Get the power of the note to decide how many times to raise the note array by half a step
- Raise the
power
to the right pitch and save it aspitch
- Add that
pitch
vector to thepart
vector, starting atwhere
- Move the
where
variable down thepart
vector a distance equivalent to the duration of that note
- In the
- When all the parts have been added to the tune file, play the tune and save it as a
.wav
file.
14.5 The Fast Fourier Transform
Typically, the time history display of a sound shows you the amplitude of the sound as a function of time but makes no attempt at showing the frequency content. While this works for the exercises above, we are often more interested in the frequency content of a sound file, for which we need a different presentation—a spectrum display.
14.5.1 Background
Figure 14.5: A typical spectrum display
In general, a spectrum display shows the amount of sound energy in a given frequency band throughout the duration of the sound analyzed but ignores the time at which the sound at that frequency was generated. Many acoustic amplifiers (see Figure 14.5) include two features that allow you to customize the sound output:
- A spectral display that changes values as the sound is played, indicating the amount of sound energy (vertically) in different frequency bands (horizontally)
- Filter controls to change the relative amplification in different frequency bands
Figure 14.6: Mechanics of the Fourier Transform
In the following paragraphs, we will consider only the analysis of the sound frequency content. The ability to reshape the sound frequency content as the sound plays is beyond the scope of this text.
To achieve the motion of the spectrum display, software to analyze a segment of the sound file runs periodically and updates the spectrum display. Typically, perhaps 20 times a second, 1/20th second of sound file is analyzed and transformed. The software used for this conversion is known as the Fourier transform.
While the mathematics of the Fourier transform is beyond the scope of this book, we can make use of the tools it offers without concerning ourselves with the details. There are a number of implementations of this transform; perhaps the most commonly used is the Fast Fourier Transform (FFT). The FFT uses clever matrix manipulations to optimize the algorithm needed to generate the forward (time to frequency) and reverse (frequency to time) transforms.
14.5.2 Implementation
Figure 14.6 illustrates the overall process of transforming between the time domain and frequency domain. It starts with a simple sound file, a vector of N sound values in the range (−1.0 to 1.0), which, if played back at a sample frequency Fs
samples per second, reproduces the sound. The parameters of interest for characterizing the time trace are:
N |
the number of samples |
Fs |
the sampling frequency |
Δt |
the time between samples, computed as 1/Fs |
Tmax |
the maximum time is N x Δt |
The FFT consumes a file describing the time history of the sound sampled at regular intervals Δt and produces a frequency spectrum with a corresponding set of characteristics. The frequency spectrum consists of the same number, N
, of data points, each of which is a complex value with real and imaginary parts. (While many displays actually plot the magnitude of the spectrum values, to accomplish the inverse transform, the complex values must be retained.) The frequency values are "folded" on the plot so that zero frequency occurs at either end of the spectrum, and the maximum frequency occurs in the middle, at spectrum data point N/2
.
The equivalent characteristics for the spectrum data are as follows:
N |
the number of samples |
Δf |
the frequency difference between samples, computed as 1/Tmax |
Fmax |
the frequency value at the end of the plot, is N x Δf However, since the mathematics force this frequency to actually replicate the beginning frequency, the maximum effective frequency actually occurs at the mid-point with value Fmax/2 . |
Technical Insight 14.2
The fact that the actual maximum frequency is half of the sampling frequency is consistent with the Nyquist criterion that the maximum frequency you can discern with digital sampling is half the sampling frequency.
The FFT is mechanized using the function fft(...)
, which consumes the time history and produces the complex spectrum file. The inverse FFT function, ifft(...)
, takes a spectrum array and reconstructs the time history. This pair of functions provides a powerful set of tools for manipulating sound files.
14.5.3 Simple Spectral Analysis
Figure 14.7: FFT of a sine wave
Listing 14.3 illustrates a script that creates 10 seconds of an 8 Hz sine wave, plots the first second of it, performs the FFT, and plots the real and imaginary parts of the spectrum. Notice the following:
- A sine wave in the time domain transforms to a line in the frequency domain because all its energy is concentrated at that frequency — 8 Hz in this example.
- Since the FFT is a linear process, multiple sine or cosine waves added together at different frequencies have additive effects in the spectrum.
- The resulting spectrum is complex (with real and imaginary parts) and symmetrical about its center, the point of maximum frequency. On the plot, of course, one cannot make the frequency axis labels reduce from the center to the end.
- The real part of the spectrum is mirrored about the center; the imaginary part is mirrored and inverted (the complex conjugate of the original data).
- The phase of the complex spectrum retains the position of the sine wave in the time domain — it would be totally real for a cosine wave symmetrically placed in time and totally imaginary for a sine wave in the same relationship.
The script in Listing 14.3 creates three sub-plots: the original sine wave and then the amplitude and phase of the spectrum.
Figure 14.7 shows the result from running this script. It confirms the earlier statement that the real part of the spectrum is mirrored about the center frequency, and the imaginary part is mirrored and inverted.
14.6 Frequency Domain Operations
This section is intended to set up the process of building a synthesizer that will replicate with a reasonable level of fidelity the sound of a piano without resorting, as we did above, to reading and manipulating a piano time history. To do this, we must understand the basics of the frequency spectrum of the instrument and shaping its time history.
As a typical example of operating in the frequency domain, we will consider analyzing the spectral quality of different musical instruments. The intent of this section is to develop a plot showing the spectra of a selection of different musical instruments. Listing 14.4 shows a function that reads the .wav file of an instrument. The author is deeply indebted to the University of Miami's Audio and Signal Processing Laboratory who gave permission to use their musical instrument sound collection. This provided us with a series of sound traces recording different instruments. All were recorded in a quiet room playing the same musical note giving us clean, pure recordings of a large number of instruments. http://chronos.ece.miami.edu/~dasp/samples/samples.html.
Violin Frequency Spectrum
Trumpet Frequency Spectrum
Train Whistle Frequency Spectrum
Figure 14.8: Instrument Spectra
The results are shown in Figure 14.8. It is interesting to notice the following:
- None of the instruments produce a pure tone. The lowest frequency at which there is energy is usually called the fundamental frequency, and successive peaks to the right at multiples of the fundamental frequency are referred to, for example, as the first, second, and third harmonics.
- Several instruments have much more energy in the harmonics than in the fundamental frequency.
- "Families" of instruments have similar spectral shapes — the strings, for example, have strong fundamental and second harmonic energy. In principle, these characteristic spectral "signatures" can be used to synthesize the sound of instruments, and even to identify individual instruments when played in groups.
14.6.1 Details of the Spectral Data
Figure 14.9: Instrument Spectra
We will now look carefully at the characteristics of the Frequency Spectrum using the code in Listing 14.5. The first view we create is the spectrum plot of a sine wave at 261.6 Hz which musicians would recognize as Middle C. Since all the sound energy is at that one frequency, the spectrum is a vertical line at 261.6 Hz. The scaling on the vertical axis is complicated and irrelevant to this discussion. Consider the vertical axis to show the relative amounts of energy as a function of frequency. Note that the FFT function is assuming that the sound being analyzed is the sum of a number of sine waves at different frequencies. The task of the FFT is to separate out and display the sound energy at each frequency. In this example, there is only one frequency.
Figure 14.10: Spectrum of a trumpet
In this next example, we will plot the absolute values of the frequency spectrum of a trumpet playing the same note at 261.6 Hz. Notice some interesting characteristics of this spectrum:
- There is some energy at 261.6 Hz (normally called the "fundamental frequency" - the note intended to to be played by the musician.)
- However, the bulk of the sound energy is at higher frequencies.
- "Musical" sounds in general are composed of energy at the fundamental frequency combined with energy at integer multipliers of the fundamental frequency referred to as the "harmonics." Contrast this with the "dirty" looking frequency spectrum of the train whistle in Figure 14.8 that is not normally classed as "musical"
- Notice with the trumpet that the maximum energy is in the 4th harmonic and the first ten harmonics all have more energy than the fundamental. This gives the trumpet its "brilliant" sound.
Figure 14.11: The Spectrum is actually complex
In this next example, we will plot the real and imaginary parts of the same trumpet frequency spectrum. Notice that the physical mechanics of the shape of the trumpet has created frequency spectrum values that are "out of phase" with other spectrum values. We will not really be concerned with this except to observe that we need to reproduce the phase as well as the magnitude of the energy if we are to produce a faithful reproduction of the spectrum of an instrument.
14.6.2 Notes fading with time
Figure 14.12: trumpet time history
Many instruments have a relatively constant amplitude when played. For example, a trumpet's amplitude is controlled by the musician's breath, and could be assumed to be constant over the duration of the note as illustrated in Figure 14.12. If this is the case, everything necessary to make a synthesizer has been accomplished. Listing 14.6 was used to generate this figure, together with the frequency spectrum not repeated here.
Figure 14.13: piano time history
Some instruments, however, are played by striking a string, for example, and the allowing the reverberation of the sound to continue, gradually fading over time. Figure 14.13 illustrates the changes over time when a piano note is played. In order to apply a profile over time to our synthetic piano note, we need to reach ahead to Chapter 15 to use curve fitting to model the shape of the sound decay. We will merely report the general steps here and refer the reader to section 15.2 for the details.
- In general, we need first to define some data points shown as red plus signs that define the decay.
- We then use the tools of chapter 15 to compute a small number of coefficients that force a polynomial curve to best fit these data points shown as the cyan colored curve.
- Finally, we generate that curve and multiply the sound at each sample point by the interpolated value of that curve.
14.7 Engineering Example - Music Synthesizer
A music synthesizer is an electronic instrument with a piano style keyboard that is able to simulate the sound of multiple instruments. Unlike the instrument sounds we have used so far, the instrument sounds are not stored as large time histories. Rather, they are stored as the Fourier coefficients similar to those illustrated in Figure 14.11. The sound is then reconstructed by multiplying sin or cosine waves of the right frequency by the stored coefficients. For some instruments, this is sufficient. Other instruments such as pianos need to have the amplitude of the resulting sound modified to match a typical profile. Listings 14.8 illustrates a possible technique for extracting the most important Fourier coefficients from the piano sound. We would then apply the fading curve created in section 14.6.2 above to each note and create the music from the individual notes.
Anton Dvorak: "Humoresque"
Chapter Summary
This chapter presented the following:
- Sounds are read with specific readers that provide a time history and sampling frequency
- Sounds can be played through the computer's sound system and saved to disk as a sound file ready for playing on any digital player
- We can slice and concatenate sounds to edit speeches and change the frequency of the sound to change its pitch
- We can analyze the frequency content of sound using the Fast Fourier Transform (FFT)
- We can modify the spectra by adding, deleting, or changing the sound levels at chosen frequencies under certain controlled conditions
- We can reconstruct a sound from the FFT coefficients.
Self Test
True or False
- Playing a sound file at double the recorded sample frequency raises its pitch by an octave.
- Removing every other sample from a sound file lowers the pitch by an octave.
- The resolution of the recorded data has a significant effect on the quality of the recording.
- After performing an FFT, the zero frequency occurs at either end of the spectrum and the maximum frequency occurs in the middle.
- Since the mathematics of the FFT are linear, the spectrum of a sound added in the time domain is also added in the frequency domain.
Fill in the Blanks
- Sound pressure fluctuations have two attributes: their _______________ and their _______________.
- Each word coming out of the _____________ or going into the _______________ merely represents the _______________ on the microphone at a point in time.
- The steps from one note to the next higher octave are divided into _______________ increments: _______________ whole note steps and _______________ half note steps, for a total of _______________ half note steps.
- A spectrum display shows the amount of _______________ in a given _______________ throughout the duration of the sound analyzed.
Programming Projects
- These are fundamental exercises with sound files. You should not
hard-code any of the answers for this problem, and you should not
need iteration.
- Select and read a suitable .wav file, and save the sound values and sampling frequency.
- Create a new sound that has double the frequency of the original sound, and store your answer in the variable sound_Double.
- Create a new sound that is the same as the original except that the pitch is raised by five half tones. Store your answer in the variable raised_pitch.
- We need a figure showing two views each of these three
sounds, created using subplot.
In the left column, plot the original sound, sound_Double, and raised_pitch, labeling each plot accordingly.
In the right column, plot the first quarter of the values of the power spectrum of each sound with the proper frequency values on the horizontal axis. - Play each of the sounds in the following order: original sound, sound_Double , and raised_pitch each at the original sampling frequency.
- Write a function that will accept a string specifying a sound file and
do the following:
- Play back the sound..
- Plot the sound in the time domain, titling and labeling your plot appropriately..
- Compute the frequency with the most energy in this file. Validate your answer by plotting the lower quarter of the frequencies of the Fourier Transform of the sound. Don't forget that the Fourier Transform is complex; you will need to reason with and plot the absolute value of the spectrum..
- Test this function with suitable .wav files.
- Write a function named plotSound that takes in the name of a sound
file and produces a 1 3 2 figure with two plots. The first plot should
be a plot of the sound in the time domain. The second plot should
be a plot of the sound in the frequency domain. Your function
should not return anything. Label the first plot 'Time Domain' and
label its axes appropriately. Label second plot 'Frequency Domain'
and label its axes appropriately.
The Time Domain plot should be an amplitude vs. time plot. For
simplicity make sure that your time vector starts at dt (delta time)
and goes to n*dt (t max ) where n is the number of samples.
The Frequency Domain plot should be a power vs. frequency plot where power is the absolute value of the FFT of the amplitude values. For simplicity make sure that your frequency vector starts at df (delta frequency) and goes to n*df (2*f max ). - In this exercise, we will write a script to create an instrument sound
from scratch.
- Create a vector, t , of time values from 0 to 2 seconds with length 40,000 samples.
- Convert the frequency of middle C (261.6 Hz) to v radians per second.
- Compute a sound sample as cos(vt) over the range of t in part a.
- Play that sound at a sample frequency of 20,000, and verify that it sounds "about right."
- Perform the Fourier Transform on the sound vector, establish the correct axis values, and prove that the sound is exactly Middle C.
- Write a function named playNote that takes in a string representing
a note on the piano. Your function should return a vector
representing the amplitude values of the note in addition to the
correct sampling frequency to be used to play it back. You should
do this by modifying the sound in the provided instr_piano.wav file
which is Middle C played on the piano. Note that the returned
sampling frequency should be the same as that in instr_piano..wav .
Here is a list of all the possible note names representing notes that
your function should work with and below that is the number of
half steps above/below the middle C for that note:
where c4 is the middle C, c5 is 1 octave above it, and c3 is 1 octave below it. Similarly, f5 is 1 octave higher than f4, etc. For example, [y1 fs] = playNote('c5'); should return a vector such that sound(y1, fs) should sound like middle Ccn cn# dn dn# en fn fn# gn gn# a(n+1) a(n+1)# b(n+1) c(n+1) -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 - Finally, you will use these tools to play your favorite song.
- Find the music for your favorite song, and translate it into the symbology of Problem 14.5.
- Write a script that uses the playNote function to play your song on the piano.
- Modify playNote to use your synthetic instrument from Problem 14.3, and save it as playSynthetic .
- Write a script that uses playSynthetic to play your song in futuristic style.


--- layout: page title: Issues API ---
Issues are a way for Content Owners and Translation Resources to communicate about translation work. Each Issue is attached to one unique source string in a Smartling project. The issue is either a Source string issue or a Translation issue. If an issue is a translation issue then it is also associated with a specific target translation language. An issue is either Open or Closed and can have any number of user comments attached. Source Issues are visible to all resources in a project who can see the associated string. Translation Issues are visible only to resources who work on the language. Automatic email notifications are generated through the lifecycle of issues, depending on individual user’s profile settings.
For more information about how Issues work in the Smartling Dashboard, see our user documentation.
Smartling’s Issues API provides methods for Creating issues, changing the state of an issue, commenting on an issue and requesting detailed information and reports on issues and comments.
GET requests require no parameters except path variables to identify Projects, Issues and Comments. For POST requests, parameters should be passed in JSON format rather than multi-part form.
The following parameters may be used in Issues API requests and responses. See the pages for each method to find which parameters are available for that method.
Unique identifier for a Smartling project containing an issue. Project ID can be found on the API page of the Smartling Dashboard.
Unique identifier for an issue within a Smartling project.
Identifies the issue type. issueTypeCode is either SOURCE
or TRANSLATION
. Each have their own set of issueSubType values:
Unique identifier for a string in Smartling. Used by the Issues API to attach an issue to a string. Depending on the request, may be a single value or an array.
An identifying code for a language in Smartling. See the full list of locale codes. Depending on the request, may be a single value or an array.
Either OPENED
or RESOLVED
.
Unformatted plain text field explaining an issue.a
Unformatted plain text of a comment on an issue.
Searches for Issues created before a given date. See Date Format for details.
Searches for Issues created after a given date. See Date Format for details.
Determines the number of results returned and index offset for large result sets. See Limit and Offset
Unique identifier for the user who closed the issue.
Unique identifier for the user who opened the issue.
Boolean - true
if the string the issue is associated with is active in the Smartling Project, false
if the string is inactive.
Date an issue was created.
Date an issue was most recently closed.
The Smartling locale code for the source language of a string with an issue
The Smartling locale code for the target language for a string with a translation issue
{% for Parameter in site.data.IssueParameters %}{{Parameter.Description}}
{% if Parameter.Values.size > 0 %}| {{Value.Value}} {% if Value.Default == 'YES' %}(default){% endif %} | {{Value.Description}} |
|---|


Text goes here.
Name
HP
MP
$
XP
Mather Demo v.0.2.33. A
Methods of Math
Production.
Created by
Punkbass
.
Contribute to the project at
Github
.


‘Still I Rise’ – these are the words emblazoned across the back of Lewis Hamilton’s helmet and tattooed across his shoulders, and ever since annihilating expectations with one of the greatest rookie performances in F1 history in 2007, that’s literally all he’s done: risen to the top of the all-time pole positions list ahead of his hero Ayrton Senna, surged into second place in the wins column behind only the inimitable Michael Schumacher, and surpassed the legendary Sir Jackie Stewart for the most championship titles by a British driver.
Could he be the G.O.A.T? Few would deny that he’s in the conversation – and what’s more he’s got there his way, twinning his relentless speed with a refusal to conform to stereotypes for how a racing driver should think, dress or behave.
Respect is hard earned in F1, but Hamilton has it from every one of his peers. Why? Because they know that whatever the track, whatever the conditions, whatever the situation, when his visor goes down and the lights go out, it’s Hammertime.
"As a driver, you've always got to believe in your heart that you've got what it takes to win it. You've always got to believe in yourself. You've always got to arrive on the day and believe it can happen. You've always got to believe in the positives." - Lewis Hamilton
If you want to know more about Lewis Click on this link


[gecode-users] reified domain constraints failing for empty domains
Guido Tack
tack at gecode.org
Mon Aug 23 18:53:35 CEST 2010
Kish Shen wrote:
> I have noticed that the reified version of the dom constraint seems to fail when the domain is empty (min > max):
>
> dom(*solver, x, min, max, reif)
>
> solver->failed() seems to return true if min > max, even if reif is not set, or 0.
>
> To me, it seems more correct for dom to succeed if reif is 0, and to not fail if reif is not yet set to 0 or 1. Is it possible to do this?
That's a bug, thanks for reporting it! I fixed it in the svn.
Cheers,
Guido
--
Guido Tack, http://people.cs.kuleuven.be/~guido.tack/
More information about the users
mailing list


Affiliate Marketing
An Affiliate Marketplace Template for Marketers
FIRST DEMO
SECOND DEMO
GITHUB REPO


Uploading Image to Firebase Storage in Flutter App (Android & iOS)
Posted on August 16, 2020 in Flutter
Target Audience: Beginner
Recipe: Implement uploading image to Firebase Storage on Flutter Native.
Goal: In this code recipe, we'll pick an image from device camera or gallery and upload it to the Firebase Storage. Note: I'll be using Android emulator to demonstrate this code recipe. The camera functionality doesn't work in iOS simulator. You need an iOS device to use camera.
Pick Image
Upload Image
Checkout the Youtube video:
Step #1. pubspec.yaml
dependencies
Flutter plugin for accessing images in FirebaseStorage for Native apps:
dependencies:
firebase_storage: ^3.0.8
firebase_core: ^0.4.0+9
firebase_analytics: ^5.0.6
Image picker plugin to select an image from device or emulator:
dependencies:
#Picking image from gallery
image_picker: ^0.6.7+4
Note: This code recipe should work on Flutter Web and/or Desktop to upload image as far as it's able to get reference to the File
on device. The image_picker
plugin to select an image is only supported on Android and iOS platforms.
Step #2. Firebase Project review
Check out my previous article on loading image from Firebase Storage to set up Firebase project. In this code recipe, you'll need to configure firebase rule to write to the FirebaseStorage.
Step #3. Picking Image
An image file _imageFile
is selected on device and/or emulator using ImagePicker
Fluter plugin.
class UploadingImageToFirebaseStorage extends StatefulWidget {
@override
_UploadingImageToFirebaseStorageState createState() =>
_UploadingImageToFirebaseStorageState();
}
class _UploadingImageToFirebaseStorageState
extends State<UploadingImageToFirebaseStorage> {
File _imageFile;
///NOTE: Only supported on Android & iOS
///Needs image_picker plugin {https://pub.dev/packages/image_picker}
final picker = ImagePicker();
Future pickImage() async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
setState(() {
_imageFile = File(pickedFile.path);
});
}
...
}
Step #4 Uploading Image to FirebaseStorage
Once an image is selected using ImagePicker, it will be displayed in the screen. Clicking on 'Upload Image' button on screen will upload the image to Firebase Storage. Make sure that FirebaseStorage write
rules are configured appropriately. I'm temporarily enabling write access on FirebaseStorage access using allow write: if true;
. Make sure to disable it once you've confirmed the functionality. It's always good idea to put write access behind the successful user login.
The following code will take the image file on device and upload it to the uploads
folder in the FirebaseStorage.
class _UploadingImageToFirebaseStorageState
extends State<UploadingImageToFirebaseStorage> {
File _imageFile;
...
Future uploadImageToFirebase(BuildContext context) async {
String fileName = basename(_imageFile.path);
StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child('uploads/$fileName');
StorageUploadTask uploadTask = firebaseStorageRef.putFile(_imageFile);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
taskSnapshot.ref.getDownloadURL().then(
(value) => print("Done: $value"),
);
}
...
}
iOS Info.list
Don't forget to add camera related permissions to Info.plist
.
<key>NSCameraUsageDescription</key>
<string>Need to access your camera to capture a photo add and update profile picture.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Need to access your photo library to select a photo add and update profile picture</string>
Source code repo
References:
- Loading image from Firebase Storage in Flutter App (Android, iOS & Web)
- Configure Firebase project for Flutter Native Android app
- Configure Firebase project for Flutter Native iOS app
Happy cooking with Flutter :)
_Liked the article? Let me know with 👏👏👏
Couldn't find a topic of interest? Please leave comments or email me about topics you would like me to write ! BTW I love cupcakes and coffee both :)_


We appreciate your support! If you have any questions, please email!!
If you are not redirected in five seconds, click here.


Benjamin Saller
Abstract Edge
<EMAIL_ADDRESS>(formerly known as CMFTypes) is Zope Product which simplifys the creation of new content types under Zope 2 and the Content Management Framework (CMF). Many content management projects involve introducing new types of content, which in the non-trivial case requires an informed understanding of how Zope and the CMF work. Archetypes provides a simple, extensible framework that can ease both the development and maintenance costs of CMF content types while reducing the learning curve for the simpler cases.
The Zope/CMF world is populated with many projects that deal with multiple content types. Most of these deal with one or two aspects of content management, mainly specifying what kinds of data constitute a type and what might serve as an acceptable source of data for populating a content object. By these I mean defining what fields constitute a type (body, teaser, etc) and products that deal with converting rich original content (Office Products, PDF, Docbook, etc) into web ready forms.
Archetypes introduces a framework that provides some layering between concerns and provide a reasonable set of default policy and integration with Zope’s leading CMF implementation, Plone (www.plone.org).
Archetypes works by declaring data about the object using its custom schema definition format. A schema is simply a list of Field objects that describe the data and specify the various concerns that should be implemented/generated/dealt-with on behalf of the content objects. At its most basic a schema is very simple
This declares a schema with two fields, teaser and body. When inserted into a class this would cause each Field to be associated with accessors and mutators, generate edit and view forms, validation scripts, a unique ID for the object, the ability to handle references between objects and a host of other features.
While its interesting that little else is required you are also capable of defining a variety of policy in the schema and in the Python code referred to by the schema. Below is the same example with a bit more detail and policy.
By providing a bit more information we are able to make forms that indicate that body is required (with supporting validation), that both Fields contribute to the SearchableText (a way of saying what parts of a content object are “full text searchable” in CMF terms) and providing some descriptive labels for the generated forms. What is also interesting is that we have specified information for the body field that deals with content transformation, we have indicated that the Archetypes runtime should deal with content originating in all of the listed mime-types (which results in the automatic generation of an HTML version of the content as well as keeping the original). By requesting that the ‘RichWidget’ be used on the form we are given the chance to enter text into a textarea or upload a file in one of the know mime-types. It also exposes the field for use with External Editor allowing content authors to edit the Field locally using a content editor of their choosing and save updates directly to the resulting content object (with all of the transformation and cataloging concerns automatically addressed).
Archetypes continues by providing a set of abstractions of things like data type mapping and data storage. It is my hope that projects can provide custom implementations of Field for new data types, new types of transformations, new storage models and that these will be largely interchangeable and useful on other projects. The project provides simpler ways to set things like icons, actions and other elements associated with content types in the CMF.
Archetypes defines active schemas when creating new types. Rather than just defining the properties and policies of a new type the schema definition implements policy and binds it to different concerns. This has many interesting implications. Projects can define custom Field types that introduce policy for new Field types. This means that developers can build collections of policy that are useful in a variety of new and different types, something that is not as simple when writing custom accessors and mutators for each field by hand. It is an important goal of the Archetypes project that all of the inner-workings of the project become exposed at the programmatic level for adaptation to individual projects needs while not requiring changes to the core.
At the same time its quite possible for developers to implement their own policy and ignore most of the inner workings of the runtime system. The Archetypes framework carries a rich set of configurable behaviors but if the existing framework is not sufficient or cannot be extended then it makes every effort to stay out of the developers way. Standard Object Oriented techniques like using subclassing to specialize content types still works normally and developers can choose to provide their own implementation of almost any behavior. To facilitate this (and to ease the common case where the developer does wish to depend on the Archetypes system) a class generation layer is employed when ever a change to the schema is detected.
The Class Generator will inspect the schema, attempt to figure out names for accessors and mutators (either registered names or via a default naming convention) and then figure out if the methods need to be generated or not. This point is important, if methods with the expected names of the accessor and mutator exist on the class then nothing further is done, but if not the field is bound to the active schema using a generated method.
In Archetypes the default is that each class retains a pointer to the schema accessible though the Schema() method call. The schema grants runtime access to the names of the accessors and mutators as well as containing the field objects which hold the actual implementation.
The following shows access to the attributes at runtime and getting a handle to the accessor.
Field objects implement a get/set protocol which is what the automatically generated methods delegate to. Examples of what these generated method might look like follow:
A very simple Field level implementation of get is shown below.
Where self.getName() is the name of that field as it was registered in the schema. Here we delegate to the storage concern which can be defined/overridden in the schema again. A sample of what a storage get method might look like is shown below.
This simple layering allows for fields that might store their field level data in different ways or that require different data mapping before storage can be done (for example converting the field to an different data type, i.e. DateTime objects). It is possible then to use as little or much of the layering machinery as needed by a particular project or simply provide your own implementation.
As an example if you require a Field that normalizes it's data you could define your own field implementation that mapped the value before calling the storage layer, or simply write your own custom mutator. The example below might be the mutator for a field named 'foo', that converts its argument to a lowercased string.
Within a given/particular site, Archetypes based objects each
register with the ArchetypeTool and are assigned a unique
Id. This UID should remain consistent in the face of rename and
move operations. References to other Archetypes based objects
are possible and back-references are maintained.
Archetypes
has a built in notion of validation for the object. Two forms of
validation exist, the first and simplest is to delegate to the
validation service that resides in the Archetypes CVS repository.
Using this tool reusable elements of validation can be referred to in
the schema. Using this tool is as simple as defining a tuple of named
validators. For example to indicate that the field 'url' should
validate as a URL we specify the following in the schema. In
many cases this is enough, but in cases where more complex validation
is required (or is needed to suppliment the validators list) custom
validators can easily be written. The API exposed is very simple and
is automatically invoked during form submission. If we need to
validate that the field 'number' were in some range we could easily
write a method with the name validate_number. If
and when errors are returned they are automatically encoded for use
in form level error reporting. As
an example I include a complete, but simple, example of using
Archetypes from a new project. The project is available in the
Archetypes CVS repository as ArchExample. I encourage you to
look in CVS for versions of this example that track changes to
the framework over time. The
following files are required to make a project function. The complete code for Article follows: Article
uses the public API file and requires very little code to get going.
This will create a type with a blurb and a TextArea widget, and a
body field that allows for file uploads and a richer set of content
types. The
__init__ file is equally simple. This
simply makes the type available to the CMF machinery in the normal
way. The
external method, Install in the Extensions directory is also quite
simple and uses utilities in the Archetypes project to do all the
heavy lifting. At
the end of this you are left with a new type inside your Plone site.
All the forms are dynamically rendered and are seamless to use. The
new type can use references, transformations, and can easily be
updated and extended with schema changes. The more complex a project
and the more types it has the greater the gain. When requirements are
volatile the cost of having to update multiple forms and code files
can be quite costly. Hopefully this example shows just how little (in
this case just the schema in Article) needs to be changed and
updated. Archetypes
addresses with some success the creation of new content types in Zope
2, CMF and Plone. It has been met with an enthusiastic response
within the Plone development community and offers a powerful set of
features with out having to expressly deal with all the concerns that
might be involved in dealing with large complex objects. There is
currently talk about rebuilding the content elements of Plone to use
all Archetypes based content types in its next release.
There
are some powerful abstractions such as delegating access and mutation
through the Fields. Data mapping and storage layers operate in a way
that is seamless to the developer except when they explicitly need to
address those concerns. There are a number of lessons learned for
both the Zope 2 and Zope 3 development communities. Archetypes
is currently available as a released package in a CMF/Plone project
on SourceForge known as the collective (which hosts a number of
wonderful CMF/Plone products). Archetypes
http://sf.net/projects/archetypes Plone
http://plone.org/ Zope
http://zope.org/ Python
http://python.org/


Are you sure you want to delete this?
Your changes will be lost. Are you sure?
Are you sure you want to capture this payment?
Are you sure you want to cancel this upload?
Are you sure you want to capture a partial amount? You can only do one capture for a payment and any uncaptured amount will be refunded.
Are you sure you want to process this refund?
Are you sure you want to record this chargeback? Note that when you record a chargeback, no money is sent to the customer.
Are you sure you want to cancel this payment? This cannot be undone.
Are you sure you want to cancel this subscription?
Are you sure you want to cancel this subscription item?
Are you sure you want to remove these changes?
Are you sure you want to uninstall version {{confirm.version}} of {{confirm.name}}? Any app related settings you have configured for this version will be lost.
Are you sure you want to uninstall this app? Any app related settings you have configured for this app may be lost.
Are you sure you want to start using version {{confirm.version}} of {{confirm.name}}? Before proceeding, you should test the new version to review any potential changes to the design, features and functionality.
Fast forwarding a subscription brings the subscription to the end of the current period, which is useful for testing the subscription lifecycle.
After you fast forward, the subscription will take the next scheduled action within 1-2 minutes.


Harold Lawrence Hoyt
Democrat
Special counsel to Boulder County Board of Adjustment
BA, University of Colorado 1973; JD, University of Denver 1976.
80031
Appeared on behalf of Consumer Reports re: zero emissions auto standards at Colorado Air Quality Control Commission, worked with Sierra Club re: climate action plan, lobbied (volunteer) with One Colorado at state legislature.
Colorado Democratic Party; Congressman Joe Neguse; Congressman Ed Perlmutter; Congressman Jason Crow; various Dem candidates for Colorado General Assembly; Adams County Democrats; Stonewall Democrats.
American Bar Assn., Colorado Bar Assn., Adams County Bar Assn., Colorado LGBT Bar Association, Stonewall Democrats, ACLU, Conservation Colorado, Consumer Reports.
I believe in creation of fair districts that are not based upon political affiliations but rather upon communities of interest, as compact as possible.
I will work with fellow commissioners to discharge our duties amicably and efficiently.
As an attorney for over 40 years, including 26 years as a county attorney, I have applied the law to the facts and provided clients with good advice and solutions to legal problems. I have assisted the Boulder County Board of County Commissioners in their decennial redistricting decisions in 1991, 2001, and 2011, applying the relevant constitutional and statutory guidelines to the facts in Boulder County.
Male


Man Utd interested in speedy Championship striker, claims reputable source
Reading striker Danny Loader is attracting the interest of Manchester United, according to a reliable source.
Sky Sports News report that “United are one of several Premier League clubs considering a bid for Reading’s talented young striker”.
The 20-year-old, who made his debut under Jaap Stam as a 16-year-old, almost left the Madejski Stadium on deadline day last summer.
Loader was heading for a move to Wolves, but the deal fell through and shortly after he said: “Everyone knows a Premier League club tried to sign me in the transfer window, but it wasn’t to be.
“I’m very ambitious, my dream is to play on the biggest stage and you never know when these opportunities will come around again.
“I hope that is understandable. To be clear I never handed in a transfer request and I trained on Thursday and Friday.
“I’ve been at Reading for years and I’ll always be respectful towards the club. I’m still a Reading player and that means I will give 100 per cent, as I always have done.
“My focus now is to continue to build on the positives I had last season and always looking on where I can improve. Thanks for all your continued support.”
The speedy Loader is though out of contract this summer and apparently talks on a new deal have stalled with the Royals and United are interested in signing the former England youth player, who has made six first-team appearances this season.
Loader would fit United’s brief of signing talented, young British players with plenty of potential.


A picture means a thousand words
Tropics In The East Coast
One of the photos that I took in Hawaii is now displayed at someone's new home in the East Coast and it's giving off major tropical vibes. Find out what our loyal client Tammy says about our work.
Read more...New Location Opening Soon
We’re proud to announce that we’ve acquired a new location in Palos Verdes! We just finalized the deal so there’s still a lot of work to do, but we’re excited to share the news with you! Have a look at the photos on our the coming soon page of our website.
Read more...Finding the Balance
The spiritual sense of the word yoga first arises in Epic Sanskrit, in the second half of the 1st millennium BCE, and is associated with the philosophical system presented in the Yoga Sutras of Patanjali, with the chief aim of "uniting" the human spirit with the Divine spirit.
Read more...Nature Meets Art
Nature photography is a wide range of photography taken outdoors and devoted to displaying natural elements such as landscapes, wildlife, plants, and close-ups of natural scenes and textures. Nature photography tends to put a stronger emphasis on the aesthetic value of the photo than other photography genres, such as photojournalism and documentary photography.
Read more...At the highest point in Los Angeles
Mount Baldy or Mount Baldy Village, formerly Camp Baynham and Camp Baldy, is an unincorporated community in the San Gabriel Mountains, in San Bernardino County near the eastern border of Los Angeles County, in Southern California. It is located below Mount San Antonio, commonly known as "Mount Baldy", hence its name.
Read more...My favorite animal subject to shoot
Squirrels live in almost every habitat, from tropical rainforest to semiarid desert, avoiding only the high polar regions and the driest of deserts. They are predominantly herbivorous, subsisting on seeds and nuts, but many will eat insects and even small vertebrates.
Read more...Nature Meets Art
Nature photography is a wide range of photography taken outdoors and devoted to displaying natural elements such as landscapes, wildlife, plants, and close-ups of natural scenes and textures. Nature photography tends to put a stronger emphasis on the aesthetic value of the photo than other photography genres, such as photojournalism and documentary photography.
Read more...Meet the Artists
Hello! We are Jiashi and Steven, photography hobbyists based in Los Angeles, California. We met in 2017 and quickly discovered our common passion for nature and art. We love to go camping and use our camera to capture our memories and document our travels.
Read more...Tokyo 2020 (Before Covid)
Tokyo, Japan’s busy capital, mixes the ultramodern and the traditional, from neon-lit skyscrapers to historic temples. The opulent Meiji Shinto Shrine is known for its towering gate and surrounding woods. The Imperial Palace sits amid large public gardens.
Read more...Camping With Friends
We sometimes take our friends on our camping trips, especially those who aren't experienced in camping. One of the things we love about nature photography is that it inspires people to appreciate Mother Nature and to go out and take breaks more often.
Read more...


{% extends "base.html" %} {% block content %} {% include 'profile-tabs-snippet.html' with author=user %}
You are about to delete your folder {{ folder.name }}.  All submissions in the folder are safe; this folder will simply be removed from their list of folders.


class Miner::Query
- Miner::Query
- Reference
- Object
Overview
This class creates query objects, which will later be compiled into SQL statements by the query builder
Defined in:
Class Method Summary
-
.new(table : Table | String, database = Miner.default_database)
Create a new query
Instance Method Summary
- #clauses : Hash(String, Array({String, Miner::Query::Value, String, Miner::Query::Value}))
-
#compile : String?
Compile the query, and store the compiled SQL statement
- #compiled : Bool
- #database : Miner::Database
-
#delete : self
Set the query type to delete, and execute the query
-
#execute : Boolean
Execute the query
-
#fetch : Collection?
Execute the query, and return the result set
- #fields : Array(String)
- #from(table : Table | String) : self
-
#group_by(*fields : String)
Set the group fields for the query
-
#having(column : Value, operator : String, value : Value) : self
Add a HAVING clause to the query, with AND as a delimiter
-
#insert(values : Hash(String, Value)) : self
Set the query type to insert, set the insert values, and execute the query
-
#join(table : Table | String, type : JoinType = JoinType::Left) : self
Add a join to the query
- #join_type : Miner::Query::JoinType?
- #joins : Array(Miner::Query)
-
#on(column : Value, operator : String, value : Value) : self
Add an ON clause to the query, with AND as a delimiter
-
#or_having(column : Value, operator : String, value : Value) : self
Add a HAVING clause to the query, with OR as a delimiter
-
#or_on(column : Value, operator : String, value : Value) : self
Add an ON clause to the query, with AND as a delimiter
-
#or_where(column : Value, operator : String, value : Value) : self
Add a WHERE clause to the query, with OR as a delimiter
-
#order_by(*fields : String | Tuple(String, Sort))
A shorthand for setting multiple sort fields at once
-
#order_by(field : String, direction : Sort = Sort::Asc)
Set the order fields for the query
- #parent : Miner::Query?
-
#select(*fields : String) : self
Set the query type to select, and set the fields to be selected
-
#set_join_type(join_type : JoinType) : self
Sets the join type for a child query
-
#set_parent(parent : Query) : self
Set a parent query for subqueries and joins
-
#set_type(type : Type) : self
Sets the type for the query
- #sql : String?
- #table : Miner::Table
- #type : Miner::Query::Type
-
#update(values : Hash(String, Value)) : self
Set the query type to update, set the update values, and execute the query
- #values : Hash(String, Miner::Query::Value)?
-
#where(column : Value, operator : String, value : Value) : self
Add a WHERE clause to the query, with AND as a delimiter
Class Method Detail
Create a new query
Queries can be created by passing a table name, or an instance of Miner::Table
# With a table name
query = Miner::Query.new "countries"
# With a Miner::Table instance
table = Miner::Table.new "countries"
query = Miner::Query.new table
By default, queries are executed against the database defined
in Miner.default_database
. This can be overridden by passing
an instance of Miner::Database
as a second parameter
config = Miner::Config.new({
"name" => "my_other_database",
"username" => "my_user",
"password" => "my_password"
})
database = Miner::Database.new config
query = Miner::Query.new "my_table"
Instance Method Detail
Add a HAVING clause to the query, with AND as a delimiter
query = Miner::Query.new("city")
.having("country_id", "=", 12)
.having("population", ">=", 4000)
Set the query type to insert, set the insert values, and execute the query
Add a join to the query
Joins can be defined using a table name
query = Miner::Query.new("city")
.join "country"
or an instance of Miner::Table
query = Miner::Query.new("city")
.join Miner::Table.new("country")
Accessing parent fields
When specifying ON clauses for a join, fields on the parent
table can be accessed using the #parent
keyword
query = Miner::Query.new("city")
.join("country")
.on("id", "=", "parent.country_id")
Join Types
The join type can be specified by passing a member of
Miner::Query::JoinType
as the second argument
query = Miner::Query.new("city")
.join "country", Miner::Query::JoinType::Right
Nesting
Joins return a new instance of Miner::Query
, and can
be nested indefinitely
query = Miner::Query.new("city")
.join("country")
.on("id", "=", "parent.country_id")
.join("language")
.on("country_id", "=", "parent.id")
Add an ON clause to the query, with AND as a delimiter
query = Miner::Query.new("city")
.join("country")
.on("id", "=", "parent.country_id")
.on("population", ">=", 4000)
An exception is raised if an on clause is applied to a query which is not a join
query = Miner::Query.new("city")
.on("id", "=", 12) # Raises an exception
Add a HAVING clause to the query, with OR as a delimiter
query = Miner::Query.new("city")
.having("country_id", "=", 12)
.or_having("population", ">=", 4000)
Add an ON clause to the query, with AND as a delimiter
query = Miner::Query.new("city")
.join("country")
.on("id", "=", "parent.country_id")
.or_on("population", ">=", 4000)
An exception is raised if an on clause is applied to a query which is not a join
query = Miner::Query.new("city")
.on("id", "=", 12) # Raises an exception
.or_on("population", ">=", 4000)
Add a WHERE clause to the query, with OR as a delimiter
query = Miner::Query.new("city")
.where("country_id", "=", 12)
.or_where("population", ">=", 4000)
A shorthand for setting multiple sort fields at once
query = Miner::Query.new("countries")
.order_by("name", "language")
The sort direction can be specified by passing tuples containing the
field name and a member of Miner::Query::Sort
query = Miner::Query.new("countries")
.order_by(
{"name", Miner::Query::Sort::Desc},
{"language", Miner::Query::Sort::Asc}
)
Set the order fields for the query
query = Miner::Query.new("countries")
.order_by("name")
The sort direction can be specified by passing a member of
Miner::Query::Sort
as a second argument
query = Miner::Query.new("countries")
.order_by("name", Miner::Query::Sort::Desc)
Multiple fields can be specified by chaining the method
query = Miner::Query.new("countries")
.order_by("language", Miner::Query::Sort::Asc)
.order_by("name", Miner::Query::Sort::Asc)
Set the query type to select, and set the fields to be selected
Set the query type to update, set the update values, and execute the query
Add a WHERE clause to the query, with AND as a delimiter
query = Miner::Query.new("city")
.where("country_id", "=", 12)
.where("population", ">=", 4000)
Sub-queries can be passed into where clauses by creating a new instance of Miner::Query
query = Miner::Query.new("city")
.where("country_id", "IN", Miner::Query.new("country"))
.select("id")
.where("language", "=", "British")
)


ThinMusic needs JavaScript enabled to work!
ThinMusic is a web player for Apple Music.
Please stand by while we prepare some tunes!


| Conversation::__construct |
( |
|
$mode, |
|
|
|
$preview |
|
) |
| |
| Conversation::add_thread |
( |
|
$item | ) |
|
Add a thread to the conversation
Returns: _ The inserted item on success _ false on failure
| Conversation::get_mode |
( |
| ) |
|
| Conversation::get_observer |
( |
| ) |
|
| Conversation::get_profile_owner |
( |
| ) |
|
| Conversation::get_template_data |
( |
|
$alike, |
|
|
|
$dlike |
|
) |
| |
Get data in a form usable by a conversation template
We should find a way to avoid using those arguments (at least most of them)
Returns: _ The data requested on success _ false on failure
| Conversation::get_thread |
( |
|
$id | ) |
|
|
private |
Get a thread based on its item id
Returns: _ The found item on success _ false on failure
Referenced by add_thread().
| Conversation::is_commentable |
( |
| ) |
|
| Conversation::is_preview |
( |
| ) |
|
Check if page is a preview
| Conversation::is_writable |
( |
| ) |
|
Check if page is writable
| Conversation::set_mode |
( |
|
$mode | ) |
|
|
private |
| Conversation::set_profile_owner |
( |
|
$uid | ) |
|
| Conversation::$commentable = false |
|
private |
| Conversation::$mode = null |
|
private |
| Conversation::$observer = null |
|
private |
| Conversation::$preview = false |
|
private |
| Conversation::$profile_owner = 0 |
|
private |
| Conversation::$threads = array() |
|
private |
| Conversation::$writable = false |
|
private |
The documentation for this class was generated from the following file:


I am a lifeguard at the beach. As part of our training, we spend time getting to know our work environment, and the conditions of our immediate area.
Whether it's furniture for ourselves, toys for the kiddos, or ocean toys for the big kiddos, I like to spend time designing and making "stuff" out of wood in my shop.
Sometimes it's a surfboard that I made. Other times it is a new fin design that a friend comes up with. Regardless of what it is, I combine my love for the ocean, and for making by riding what my friends & I make. The image to the right is from an early R&D session of Perfect Storm Fins, before it went into production.


|
Conductor: Mario Dobernig
Mario is the resident conductor of the Preston Symphony and the Musical Director of Victoria Chorale. |
|
Tickets on sale soon!
7:30 pm Saturday 17 July at Townsville CivicTheatre $38 Adult - $34 Concession - Child/student $15 NQE Member - $32 |
|
| Cards accepted as concession price tickets - Pension, Tertiary Students Full-time and Senior cards. |
|
Special Guests:
Adam Lopez – Developed his multi-octave voice while studying opera in Australia. Domenico Taraborrelli – one of Brisbane’s most experienced and versatile multicultural entertainers. David Hudson – musician, entertainer, artist and actor |
|
Tickets on sale soon!
7:30 pm Monday 5 September at Townsville CivicTheatre $38 Adult - $34 Concession - Child/student $15 NQE Member - $32 |
|
| Cards accepted as concession price tickets - Pension, Tertiary Students Full-time and Senior cards. |
|
Conductor: Richard McIntyre
Richard has maintained a long and distinguished career as bassoonist, music educator, conductor and arranger. A Composition graduate from Sydney University, he was appointed Associate Principal Bassoon with the Sydney Symphony Orchestra as a 20-year-old in 1968, moving to The Canberra School of Music as a foundation member of the Canberra Wind Soloists in 1978. |
|
Tickets on sale soon!
7:30 pm Tuesday 8 March at Townsville CivicTheatre $38 Adult - $34 Concession - Child/student $15 NQE Member - $32 |
|
| Cards accepted as concession price tickets - Pension, Tertiary Students Full-time and Senior cards. |


Dependency
public final class Dependency: CustomStringConvertible, Codable
An external package that the current project relies on.
These are stored in the manifest’s dependencies
array.
-
Keys used to encode/decode a
Target
object.Declaration
Swift
public typealias CodingKeys = DependencyCodingKeys
-
The URI or path to the dependency.
Declaration
Swift
public let url: String
-
The version of the dependency. This could be one of multiple cases
Declaration
Swift
public var version: DependencyVersionType
-
Declaration
Swift
public init(url: String, version: DependencyVersionType)
-
Declaration
Swift
public init(from decoder: Decoder) throws
-
The dependency formatted for the manifest.
Declaration
Swift
public var description: String
-
Declaration
Swift
public func encode(to encoder: Encoder) throws
-
Updates the dependency’s instance in the project’s manifest. If the instance does not exist yet, it will be created.
Throws
Errors that occur when creating a RegEx pattern or reading or writing the manifest.Declaration
Swift
public func save() throws
-
Removes the dependency instance from the manifest’s
Package.dependencies
array.Throws
Errors that occur when creating a RegEx pattern or reading or writing the manifest.Declaration
Swift
public func delete() throws


Charles Schwab to buy TD Ameritrade in US$26 billion deal
Charles Schwab Corp said on Monday it would buy TD Ameritrade Holding Corp in an all-stock deal valued at about US$26 billion.
REUTERS: Charles Schwab Corp said on Monday it would buy TD Ameritrade Holding Corp in an all-stock deal valued at about US$26 billion.
As part of the deal, Ameritrade stockholders will receive 1.0837 Schwab shares for every share held.
The deal, which would combine the two largest U.S. discount brokerages, is expected to close in the second half of 2020.
(Reporting by Bharath Manjesh in Bengaluru; Editing by Shounak Dasgupta)


VBScripts' function
MonthName
is used to get a month:
January
February
Abbreviated name of a month:
Jan
Feb
Current month:
March
Mar


Although now in ruins, this ancient port was an important trading centre for 3,000 years. It was built with coral which required constant maintenance and once trade moved to the more modern port of Sudan, it quickly fell into disrepair.
It is located about 30nm south of Port Sudan.
This is a good first landfall after crossing of the Gulf of Aden as it is not necessary to clear into Sudan to visit here, and refuelling and provisioning here is easy.
Although Suakin is not an official port of entry, boats arriving here from the south have been allowed to clear into Sudan and formalities are reported to be simpler than at Port Sudan.
On approach, be sure to call Port Control on Channel 14.
Local agent Mohammed (phone: +249 912 142 678) will know of your arrival and will be waiting for you on the south side of the Old Town island inside the harbour. He will attract your attention and you will need to collect him in your dinghy.
He will then accompany you to authorities to help with formalities (he charges about US$40 for his services, less than Port Sudan).
Mohammed can also help obtain fuel and sweet water (by jerry can), laundry, gas refills, fresh produce, as well as trips to Port Sudan.
You need a passport photo each for shore passes. Costs are about $100 US to clear/port charges. Mohammed will do all the paper work and bring back shore passes the same day or next morning, depending on time you cleared in. Nothing extra for anchoring.
Shore passes will be issued for a short duration only. Formalities must be gone through again if continuing to Port Sudan. Formalities are simpler if one arrives with a Sudanese visa. Passports are retained until clearing out.
When clearing out from Suakin one can obtain a cruising permit which permits cruising up the coast to Port Sudan through the Sudan reefs. This is recommended to avoid any problems (see comment at bottom of page). Using Mohammed, clearing out is simple, fast and efficient.
Last updated January 2015.
The approach to the inner harbour is shallow but easy if you can avoid being distracted by the fascinating surroundings.
Very good all-round shelter.
Last updated January 2015.


Create a new device¶
I will simply comment here on what I had to do to write an Arduino device for labscript
Get blacs and runmanager installed. Not quite as trivial as it might sound…
For running [blacs](https://github.com/labscript-suite/blacs) the first time there is a description called docs/UsingBlacs.pdf
I will now follow the guide “How to add a new device” in the blacs folder
However, it seems slightly out of date/incomplete. So will try to follow the recommendations of Philipp Starkeys thesis.
https://www.dropbox.com/s/mxoumrc2djibs3l/PhD_Starkey.pdf?dl=0
Devices can be found in labscript_devices. To make things work, we need to add four classes:
labscript API - it must be name the same way as the file it lives in. It is marked through the python decorator @labscript_device
BLACS GUI - can be named as one wishes and has the decorator @BLACS_tab
BLACS worker process - can be named as one wishes and has the decorator @BLACS_worker
4. runviewer - can be named as one wishes and has the decorator @runviewer_parser Creating a compilable boilerplate - So let me start out with creating ArduinoUno.py in the folder labscript_devices.
I then added the following header:
from labscript import IntermediateDevice
from blacs.device_base_class import DeviceTab
from blacs.tab_base_classes import Worker
from labscript_devices import BLACS_tab, BLACS_worker
The first step is to actually define some dummy device now. We then will most likely not create a pseudoclock, which means that we will make the device an IntermediateDevice.
class ArduinoUno(IntermediateDevice):
# A human readable name for device model used in error messages
description = 'Arduino Uno'
# The maximum update rate of this device (in Hz)
clock_limit = 100
def __init__(self, name, parent_device, com_port = "", baud_rate= 115200):
IntermediateDevice.__init__(self, name, parent_device)
self.BLACS_connection = '%s,%s'%(com_port , str(baud_rate))
def generate_code(self, hdf5_file):
# Run the labscript suite base class method
# (we assume inheritance from PseudoclockDevice here)
# This generates instruction data for every child and
# subsequent generation of children that is attached
# to this device
IntermediateDevice.generate_code(self, hdf5_file)
# Create the HDF5 group for storage of
# device attributes and instructions
group = self.init_device_group(hdf5_file)
# device specific code here ...
We then have to work on the specific control of the device, but this would seem like a minimal code. The next step is to set up the GUI in BLACS through the DeviceTab class.
@BLACS_tab
class ArduinoUnoTab(DeviceTab):
def initialise_GUI(self):
# create the layout of the widgets
dds_widgets,ao_widgets,do_widgets = self.auto_create_widgets()
self.auto_place_widgets(dds_widgets,do_widgets)
# Create and set the primary worker
# the last ingredient are the parameters for the worker
self.create_worker("main_worker",ArduinoUnoWorker,{})
self.primary_worker = "main_worker"
# Set the capabilities of this device
self.supports_remote_value_check(False)
self.supports_smart_programming(False)
Finally, we have to create a worker that will make the contact between the GUI and the Hardware itself.
class ArduinoUnoWorker(Worker):
def init(self):
# Once off device initialisation code called when the
# worker process is first started.
# Usually this is used to create the connection to the
# device and/or instantiate the API from the device
# manufacturer
pass
def shutdown(self):
# Once off device shutdown code called when the
# BLACS exits
pass
def program_manual(self, front_panel_values):
# Update the output state of each channel using the values
# in front_panel_values (which takes the form of a
# dictionary keyed by the channel names specified
# BLACS GUI configuration
# return a dictionary of coerced/quantised values
# channel, keyed by the channel name (or an empty dictionary)
return {}
We have now setup the full the ArduinoUno.py file.
Create the GUI¶
The next step is to bind it into the GUI. So we create file, which we call connectiontable.py. And we save it in the folder userlib/labscriptlib/my_pc/ It then contains:
from labscript import *
from labscript_devices.ArduinoUno import ArduinoUno
from labscript_devices.DummyPseudoclock.labscript_device import DummyPseudoclock
DummyPseudoclock(name='clock_0')
ArduinoUno(name='arduino_0', parent_device=clock_0.clockline)
if __name__ == '__main__':
start()
stop(1)
The next step is to run this script in [runmanager](https://github.com/labscript-suite/runmanager) as this creates the necessary h5 file for #blacs.
So once we have run it in #runmanager it should have compiled without error you should find the file DATE_connectiontable_arduino_0.h5 .
This file has to be renamed connectiontable.h5 and moved into the position, which was specied in the the labconfig.
- You should now be able to start blacs through
python -m blacs
without any errors. Only an empty useless widget should be present for the moment.
Establishing a serial communication¶
In a next step we have to give the whole thing some live. Which means that we already have to establish a serial connection with the arduino. If you have an arduino around and know on which port it lives you can skip this step. Otherwise, we will explain here how you can simulate such a serial port. For that we simply create a file simSerialPort.py in the folder /userlib/pythonlib/ of your #labscript installation. The file reads then:
import os, pty
import time
import numpy as np
def test_serial():
setpoint = 750;
master, slave = pty.openpty()
s_name = os.ttyname(slave)
print(s_name)
while True:
meas = np.random.randint(700, 800)
err = setpoint - meas;
control = np.random.randint(10)
gain =1
tauI = 100
tauD = 1
mode = os.read(master, 1);
if mode:
print('mode {}'.format(mode))
if mode == b'w':
ard_str = str(setpoint) + ',' + str(meas) + ',' + str(err) + ',' + str(control)
ard_str = ard_str + ',' + str(gain) + ',' + str(tauI) +',' + str(tauD) + '\r\n'
out = ard_str.encode('windows-1252')
os.write(master, out)
if mode == b's':
set = os.read(master, 20);
setpoint = int(set.decode('windows-1252'));
print('s{}'.format(setpoint));
time.sleep(0.1)
if __name__=='__main__':
test_serial()
This program basically emulates the behavior of an arduino used for temperature control. We can start it in the shell through (being in the right directory):
python simSerialPort.py
It will answer at the beginning with a single output, which will read something like this:
/dev/ttys004
This is now the serial port on which #blacs can look for the Arduino.
Setting up a basic user interface¶
We now have some serial device


new TimeUUID
TimeUUID
Parameters:
| Name | Type | Description |
|---|---|---|
id |
String | The TimeUUID to craete a TimeUUID object from |
- Source:
- uuid.js, line 66
Methods
-
<static> fromBinary
-
Creates a TimeUUID from a binary string
- Source:
- uuid.js, line 95
-
<static> fromBuffer
-
Creates a TimeUUID from a buffer
- Source:
- uuid.js, line 87
-
<static> fromTimestamp
-
Creates a TimeUUID from a Timestamp
Parameters:
Name Type Description ts
Date The Timestamp to create the TimeUUID from - Source:
- uuid.js, line 79


{% include head.html %}
Newsletter
Portfolio
<
m
a
x
s
t
o
i
b
e
r
/
>
Open Source Developer
{{ content }} {% include footer.html %}
⚠ mxstbr.blog is deprecated! Go to
mxstbr.com/thoughts
for new posts ⚠


AWS Lambda event source mappings
An event source mapping is an AWS Lambda resource that reads from an event source and invokes a Lambda function. You can use event source mappings to process items from a stream or queue in services that don't invoke Lambda functions directly. Lambda provides event source mappings for the following services.
Services that Lambda reads events from
An event source mapping uses permissions in the function's execution role to read and manage items in the event source. Permissions, event structure, settings, and polling behavior vary by event source. For more information, see the linked topic for the service that you use as an event source.
To manage an event source with the AWS CLI or AWS SDK
The following example uses the AWS CLI to map a function named my-function
to a DynamoDB stream
that is specified by its Amazon Resource Name (ARN), with a batch size of 500.
aws lambda create-event-source-mapping --function-name my-function --batch-size 500 --starting-position LATEST \ --event-source-arn arn:aws:dynamodb:
us-east-2:123456789012:table/my-table/stream/2019-06-10T19:26:16.525
You should see the following output:
{ "UUID": "14e0db71-5d35-4eb5-b481-8945cf9d10c2", "BatchSize": 500, "MaximumBatchingWindowInSeconds": 0, "ParallelizationFactor": 1, "EventSourceArn": "arn:aws:dynamodb:us-east-2:123456789012:table/my-table/stream/2019-06-10T19:26:16.525", "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:my-function", "LastModified":<PHONE_NUMBER>.963, "LastProcessingResult": "No records processed", "State": "Creating", "StateTransitionReason": "User action", "DestinationConfig": {}, "MaximumRecordAgeInSeconds": 604800, "BisectBatchOnFunctionError": false, "MaximumRetryAttempts": 10000 }
Event source mappings read items from a stream or queue in batches. They include multiple items in the event that your function receives. You can configure the size of the batch that the event source mapping sends to your function, up to a maximum that varies by service. The number of items in the event can be smaller than the batch size if there aren't enough items available, or if the batch is too large to send in one event and has to be split up.
The following example shows an event source mapping that reads from a Kinesis stream. If a batch of events fails all processing attempts, the event source mapping sends details about the batch to an SQS queue.
The event batch is the event that Lambda sends to the function. It is a batch of records or messages compiled from the items that the event source mapping reads from a stream or queue. Batch size and other settings only apply to the event batch.
For streams, an event source mapping creates an iterator for each shard in the stream and processes items in each shard in order. You can configure the event source mapping to read only new items that appear in the stream, or to start with older items. Processed items aren't removed from the stream and can be processed by other functions or consumers.
By default, if your function returns an error, the entire batch is reprocessed until the function succeeds, or the items in the batch expire. To ensure in-order processing, processing for the affected shard is paused until the error is resolved. You can configure the event source mapping to discard old events, restrict the number of retries, or process multiple batches in parallel. If you process multiple batches in parallel, in-order processing is still guaranteed for each partition key, but multiple partition keys in the same shard are processed simultaneously.
You can also configure the event source mapping to send an invocation record to another service when it discards an event batch. Lambda supports the following destinations for event source mappings.
-
Amazon SQS – An SQS queue.
-
Amazon SNS – An SNS topic.
The invocation record contains details about the failed event batch in JSON format.
The following example shows an invocation record for a Kinesis stream.
Example invocation Record
{ "requestContext": { "requestId": "c9b8fa9f-5a7f-xmpl-af9c-0c604cde93a5", "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:myfunction", "condition": "RetryAttemptsExhausted", "approximateInvokeCount": 1 }, "responseContext": { "statusCode": 200, "executedVersion": "$LATEST", "functionError": "Unhandled" }, "version": "1.0", "timestamp": "2019-11-14T00:38:06.021Z", "KinesisBatchInfo": { "shardId": "shardId-000000000001", "startSequenceNumber": "49601189658422359378836298521827638475320189012309704722", "endSequenceNumber": "49601189658422359378836298522902373528957594348623495186", "approximateArrivalOfFirstRecord": "2019-11-14T00:38:04.835Z", "approximateArrivalOfLastRecord": "2019-11-14T00:38:05.580Z", "batchSize": 500, "streamArn": "arn:aws:kinesis:us-east-2:123456789012:stream/mystream" } }
Lambda also supports in-order processing for FIFO (first-in, first-out) queues, scaling up to the number of active message groups. For standard queues, items aren't necessarily processed in order. Lambda scales up to process a standard queue as quickly as possible. When an error occurs, batches are returned to the queue as individual items and might be processed in a different grouping than the original batch. Occasionally, the event source mapping might receive the same item from the queue twice, even if no function error occurred. Lambda deletes items from the queue after they're processed successfully. You can configure the source queue to send items to a dead-letter queue if they can't be processed.
For information about services that invoke Lambda functions directly, see Using AWS Lambda with other services.


asBEHAVE_CONSTRUCT asBEHAVE_DESTRUCT asBEHAVE_ASSIGNMENT asBEHAVE_ADD_ASSIGN asBEHAVE_SUB_ASSIGN asBEHAVE_MUL_ASSIGN asBEHAVE_DIV_ASSIGN asBEHAVE_MOD_ASSIGN asBEHAVE_OR_ASSIGN asBEHAVE_AND_ASSIGN asBEHAVE_XOR_ASSIGN asBEHAVE_SLL_ASSIGN asBEHAVE_SRL_ASSIGN asBEHAVE_SRA_ASSIGN asBEHAVE_ADD asBEHAVE_SUBTRACT asBEHAVE_MULTIPLY asBEHAVE_DIVIDE asBEHAVE_MODULO asBEHAVE_EQUAL asBEHAVE_NOTEQUAL asBEHAVE_LESSTHAN asBEHAVE_GREATERTHAN asBEHAVE_LEQUAL asBEHAVE_GEQUAL asBEHAVE_LOGIC_OR asBEHAVE_LOGIC_AND asBEHAVE_BIT_OR asBEHAVE_BIT_AND asBEHAVE_BIT_XOR asBEHAVE_BIT_SLL asBEHAVE_BIT_SRL asBEHAVE_BIT_SRA asBEHAVE_INDEX asBEHAVE_NEGATE asBEHAVE_ADDREF asBEHAVE_RELEASE asBEHAVE_GETREFCOUNT asBEHAVE_SETGCFLAG asBEHAVE_GETGCFLAG asBEHAVE_ENUMREFS asBEHAVE_RELEASEREFS asBEHAVE_FACTORY asBEHAVE_VALUE_CAST
Constructor, called when variables comes into scope.
Warning: Do not register a virtual method as a constructor. The virtual function pointer table will be initialized by the constructor function, thus the virtual method will fail.
Example:
void Constructor(Object *o) { new(o) Object(); } engine->RegisterObjectBehaviour("object", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Constructor), asCALL_DECL_OBJLAST);
For objects that should be handled by the garbage collection, to be able to automatically detect and handle circular references, the constructor must call the method NotifyGarbageCollectorOfNewObject on the engine. When doing so the gc will take a reference to the object.
Destructor, called when variable goes out of scope.
Example:
void Destructor(Object *o) { o->~Object(); } engine->RegisterObjectBehaviour("object", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destructor), asCALL_CDECL_OBJLAST);
Assignment '='.
The assignment behaviour should return a reference to itself. The operator parameter can have any type. If the parameter is a reference to an object of the same type as itself the function is used as a copy operator, which is important if the object needs to treat members especially, for example if the class holds pointers to resources.
If you pass parameters by &in, then it is a good idea to also make them const, as it can allow the compiler to make a few optimizations.
Example 1:
Object &Assign(Object *self, Object &other) { *self = other; return *self; } engine->RegisterObjectBehaviour("object", asBEHAVE_ASSIGNMENT, "object &f(const object &in)", asFUNCTION(Assign), asCALL_CDECL_OBJFIRST);
Example 2:
Object &Object::operator=(int val) { this->val = val; return *this; } engine->RegisterObjectBehaviour("object", asBEHAVE_ASSIGNMENT, "object &f(int)", asMETHOD(Object, operator=), asCALL_THISCALL);
Add and assign '+='.
See assignment.
Subtract and assign '-='.
See assignment.
Multiply and assign '*='.
See assignment.
Divide and assign '/='.
See assignment.
Mod and assign '%='.
See assignment.
Bitwise or and assign '|='.
See assignment.
Bitwise and and assign '&='.
See assignment.
Bitwise xor and assign '^='.
See assignment.
Shift left and assign '<<='.
See assignment.
Shift right logically and assign '>>='.
See assignment.
Shift right arithmetically and assign '>>>='.
See assignment.
Add '+'.
This is a global behaviour that takes two operands and creates a new value. The function should not return a reference and shouldn't store the input values. The operands can be any type, reference or not, but one of the operands must be a registered type.
If you pass parameters by &in, then it is a good idea to also make them const, as it can allow the compiler to make a few optimizations.
Example 1:
Object Add(Object &a, Object &b) { return a + b; } engine->RegisterGlobalBehaviour(asBEHAVE_ADD, "object f(const object &in, const object &in)", asFUNCTION(Add), asCALL_CDECL);
Example 2:
Object Add(Object &a, int i) { return a + i; } engine->RegisterGlobalBehaviour(asBEHAVE_ADD, "object f(const object &in, int)", asFUNCTION(Add), asCALL_CDECL);
Subtract '-'.
See addition.
Multiply '*'.
See addition.
Divide '/'.
See addition.
Modulo '%'.
See addition.
Equal '=='.

Not equal '!='.
See equal.
Less than '<'.
See equal.
Greater than '>'.
See equal.
Less than or equal '<='.
See equal.
Greater than or equal '>='.
See equal.
Logical or 'or'/'||'.
See addition.
Logical and 'and'/'&&'.
See addition.
Bitwise or '|'.
See addition.
Bitwise and '&'.
See addition.
Bitwise exclusive or '^'.
See addition.
Bitwise shift left logically '<<'.
See addition.
Bitwise shift right logically '>>', ie. clear left most bits.
See addition.
Bitwise shift right arithmetically '>>>', ie. set left most bits to the sign bit.
See addition.
Indexing operator []. Must be registered as a object behaviour.
This behaviour is normally used to access an element in a collection based on an index, wether it be a numerical index or some other form. The behaviour normally returns a reference to the element so that it can be altered by the script, but it is allowed to return the element by value.
You'll normally want to register two versions of this behaviour, one that allow the element to be altered, and one that return a read-only value. This is useful when having constant objects.
Example:
int *Object::operator[](uint idx) { if( idx >= collection.size() ) { asIScriptContext *ctx = asGetActiveContext(); if( ctx ) ctx->SetException("Out of range"); return 0; } return &collection[int]; } engine->RegisterObjectBehaviour("object", asBEHAVE_INDEX, "int &f(uint)", asMETHOD(Object, operator[]), asCALL_THISCALL); engine->RegisterObjectBehaviour("object", asBEHAVE_INDEX, "const int &f(uint) const", asMETHOD(Object, operator[]), asCALL_THISCALL);
Unary negate operator -. Must be registered as a object behaviour.
This behaviour should return a new object with the effect of the operation applied to it.
Example:
Object Negate(Object *self) { Object obj; obj.val = -self->val; return obj; } engine->RegisterObjectBehaviour("object", asBEHAVE_NEGATE, "object f()", asFUNCTION(Negate), asCALL_CDECL_OBJLAST);
Necessary for object handles to work. Allows the library to increase the reference counter for the object.
Example:
void Object::AddRef() { refCount++; } engine->RegisterObjectBehaviour("object", asBEHAVE_ADDREF, "void f()", asMETHOD(Object, AddRef), asCALL_THISCALL);
For objects treated by the garbage collector, the AddRef method must clear the flag set by the SetGCFlag behaviour. Example:
void Object::AddRef() { // gc flag is kept in the most significant bit refCount = (refCount & 0x80000000) + 1; }
Necessary for object handles to work. Allows the library to decrease the reference counter for the object. When the reference counter reaches zero the function should release any resources held by the object and free its memory.
Example:
void Object::Release() { if( --refCount == 0 ) delete this; } engine->RegisterObjectBehaviour("object", asBEHAVE_RELEASE, "void f()", asMETHOD(Object, Release), asCALL_THISCALL);
For objects treated by the garbage collector, the Release method must clear the flag set by the SetGCFlag behaviour.
void Object::Release() { // gc flag is kept in the most significant bit refCount = (refCount & 0x80000000) + 1; if( refCount == 0 ) delete this; }
This behaviour is called by the garbage collector, and is required to be registered for those objects that should be handled by the gc.
int Object::GetRefCount(); engine->RegisterObjectBehaviour("object", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(Object,GetRefCount), asCALL_THISCALL);
The GetRefCount() should return the ref count, which the gc will use to determine whether it can release the object or not. If the ref count is 1, then it means that the gc is the only one holding a reference to the object thus it can be released.
The behaviour may use any compatible calling convention, including asCALL_THISCALL even if AS_MAX_PORTABILITY is defined.
This behaviour is called by the garbage collector, and is required to be registered for those objects that should be handled by the gc.
void Object::SetGCFlag(); engine->RegisterObjectBehaviour("object", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(Object,SetGCFlag), asCALL_THISCALL);
This method is called by the gc when it's trying to determine which objects are really dead objects and should be released. When the method is called a flag must be set for the object. If the number of references to this object changes this flag must be cleared, e.g. when the AddRef and Release behaviours are called. This flag is what tells the gc that the reference count hasn't changed for this object since it started counting the references it sees.
The behaviour may use any compatible calling convention, including asCALL_THISCALL even if AS_MAX_PORTABILITY is defined.
This behaviour is called by the garbage collector, and is required to be registered for those objects that should be handled by the gc.
bool Object::GetGCFlag(); engine->RegisterObjectBehaviour("object", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(Object,GetGCFlag), asCALL_THISCALL);
This method should return true if the flag is still set, i.e. no calls to AddRef or Release has been made since the last SetGCFlag call.
The behaviour may use any compatible calling convention, including asCALL_THISCALL even if AS_MAX_PORTABILITY is defined.
This behaviour is called by the garbage collector, and is required to be registered for those objects that should be handled by the gc.
void Object::EnumReferences(asIScriptEngine *engine); engine->RegisterObjectBehaviour("object", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(Object,EnumReferences), asCALL_THISCALL);
When this method is called the object should enumerate over all the references it holds and call the asIScriptEngine::GCEnumCallback method for each of them. The engine pointer is passed in as a parameter to the method to simplify the implementation. The gc will use this to follow the chain of references in order to determine which objects are dead even though the ref count may be larger than 1, i.e. circular references.
The behaviour may use any compatible calling convention, including asCALL_THISCALL even if AS_MAX_PORTABILITY is defined.
This behaviour is called by the garbage collector, and is required to be registered for those objects that should be handled by the gc.
void Object::ReleaseAllReferences(asIScriptEngine *engine); engine->RegisterObjectBehaviour("object", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(Object,ReleaseAllReferences), asCALL_THISCALL);
When this method is called the object should enumerate over all the references it holds and release them. The engine pointer is passed in as a parameter to the method to simplify the implementation. This method is called when the gc has determined that the object is part of a group of objects with interchanging references isn't reachable from the application anymore. By releasing all of the references the circular references will be broken and the ref count brought down to 1, which is when the gc will release the final reference causing the object to be destroyed.
The behaviour may use any compatible calling convention, including asCALL_THISCALL even if AS_MAX_PORTABILITY is defined.
Factory, called when variables comes into scope.
Example:
Object *Factory() { return new Object(); } engine->RegisterObjectBehaviour("object", asBEHAVE_FACTORY, "object@ f()", asFUNCTION(Factory), asCALL_CDECL);
For objects that should be handled by the garbage collection, to be able to automatically detect and handle circular references, the constructor must call the method NotifyGarbageCollectorOfNewObject on the engine. When doing so the gc will take a reference to the object.
An object behaviour, that permits a cast operator to be registered for an object. This can allow objects to be cast to different types, including primitives.
Example:
int Object::castToInt() { return intValue; } engine->RegisterObjectBehaviour("object", asBEHAVE_VALUE_CAST, "int f()", asMETHOD(Object,castToInt), asCALL_THISCALL);